Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 19, 2026

OpenAPI duration property import with x-ms-duration extension

This PR implements support for duration types in the OpenAPI importer using the x-ms-duration extension, with round-trip capability via the @extension decorator.

Changes completed:

  • Add test cases for all duration scenarios with x-ms-duration extension
  • Update getNumberType and getIntegerType functions to handle x-ms-duration extension (import)
  • Add decorator generation for x-ms-duration with seconds/milliseconds encoding (import)
  • Add @extension decorator for x-ms-duration to enable round-tripping
  • Run tests to validate all scenarios
  • Format code before final commit
  • Add changelog entry using chronus
  • Add regression test for string duration format (no encode decorator)

Implementation details:

Import (OpenAPI → TypeSpec):

  • Modified getNumberType() and getIntegerType() in generate-types.ts to check for x-ms-duration extension (values: seconds or milliseconds)
  • Updated getDurationSchemaDecorators() function in decorators.ts to generate appropriate @encode decorators based on both the x-ms-duration value and the schema's format (int32, float, decimal, etc.)
  • Removed filtering of x-ms-duration from getExtensions() so it's also added as an @extension decorator for proper round-tripping

Export (TypeSpec → OpenAPI):

  • Round-tripping is achieved via the standard @extension decorator mechanism
  • When TypeSpec has @extension("x-ms-duration", "seconds"), the standard extension handling emits it to OpenAPI

Test coverage:

  • Added comprehensive test suite in data-types.test.ts covering all import scenarios from requirements table (32 tests)
  • Added test cases in generate-type.test.ts for inline type expressions (82 tests)
  • All tests pass successfully

Supported scenarios:

OAS type OAS format OAS x-ms-duration TypeSpec Type Decorators
string duration not applicable duration none
integer or number int32 absent int32 none
integer or number int32 present, set to seconds duration @extension("x-ms-duration", "seconds") @encode("seconds", int32)
integer or number int32 present, set to milliseconds duration @extension("x-ms-duration", "milliseconds") @encode("milliseconds", int32)
number float or decimal absent float or decimal none
number float or decimal present, set to seconds duration @extension("x-ms-duration", "seconds") @encode("seconds", float/decimal)
number float or decimal present, set to milliseconds duration @extension("x-ms-duration", "milliseconds") @encode("milliseconds", float/decimal)

Example transformations:

Import (OpenAPI → TypeSpec):

# OpenAPI
DurationIntSeconds:
  type: integer
  format: int32
  x-ms-duration: seconds
// TypeSpec
@extension("x-ms-duration", "seconds")
@encode("seconds", int32)
scalar DurationIntSeconds extends duration;

Export (TypeSpec → OpenAPI) - Round-tripping:

// TypeSpec (with explicit extension decorator)
@extension("x-ms-duration", "milliseconds")
@encode("milliseconds", float32)
scalar DurationFloatMilliseconds extends duration;
# OpenAPI
DurationFloatMilliseconds:
  type: number
  format: float
  x-ms-duration: milliseconds

String with duration format (existing behavior, no regression):

# OpenAPI
DurationString:
  type: string
  format: duration
// TypeSpec
scalar DurationString extends duration;
Original prompt

This section details on the original issue you should resolve

<issue_title>importer - OpenAPI duration properties should result in a duration properties</issue_title>
<issue_description>### Clear and concise description of the problem

When importing a property with the following schema:

foo:
  type: number
  format: duration

Currently results in this

foo: numeric

But should result in this

@encode("seconds", float32)
foo: duration

Checklist

  • Follow our Code of Conduct
  • Read the docs.
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.</issue_description>

<agent_instructions>use conventional commits.
run the formatting command before any commit.
start by writing the unit tests first.
when done, run the following command to add a feature entry to the changelog npx @chronus/chronus add</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits January 19, 2026 19:27
…with @encode decorator

Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix importer to support OpenAPI duration properties feat(openapi3): convert number type with duration format to duration with @encode decorator Jan 19, 2026
Copilot AI requested a review from baywet January 19, 2026 19:35
@baywet
Copy link
Member

baywet commented Jan 19, 2026

@copilot add another unit test to validate there are no regressions if it does not exist already.

The following OpenAPI description

foo:
  type: string
  format: duration

Should result in this TypeSpec

bar: duration

Note there are no encode attribute in that case.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 19, 2026

Open in StackBlitz

npm i https://pkg.pr.new/microsoft/typespec/@typespec/openapi@9412
npm i https://pkg.pr.new/microsoft/typespec/@typespec/openapi3@9412

commit: 3eab35d

Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot add another unit test to validate there are no regressions if it does not exist already.

The following OpenAPI description
...

Added regression test in commit 09b3593. The test validates that type: string, format: duration converts to duration without an encode decorator, ensuring no regression from the number duration changes.

@baywet baywet marked this pull request as ready for review January 19, 2026 19:49
@baywet baywet enabled auto-merge January 19, 2026 19:49
@microsoft-github-policy-service microsoft-github-policy-service bot added emitter:openapi3 Issues for @typespec/openapi3 emitter openapi3:converter Issues for @typespec/openapi3 openapi to typespec converter labels Jan 19, 2026
@azure-sdk
Copy link
Collaborator

azure-sdk commented Jan 19, 2026

You can try these changes here

🛝 Playground 🌐 Website 🛝 VSCode Extension

@baywet baywet marked this pull request as draft January 21, 2026 13:11
auto-merge was automatically disabled January 21, 2026 13:11

Pull request was converted to draft

Copilot AI requested a review from baywet January 21, 2026 14:19
@baywet baywet marked this pull request as ready for review January 21, 2026 14:25
@baywet baywet enabled auto-merge January 21, 2026 14:25
@baywet baywet disabled auto-merge January 21, 2026 14:26
@baywet baywet marked this pull request as draft January 21, 2026 14:26
@baywet
Copy link
Member

baywet commented Jan 21, 2026

@copilot also update the OpenAPI generation to emit the extension when the encode decorator is present

…ypes

- Add x-ms-duration extension to OpenAPI output when duration type has @encode decorator
- Support both seconds and milliseconds encoding
- Update applyEncoding to detect duration types and add extension
- Add comprehensive tests for all duration encoding scenarios with extension emission
- Walk up scalar chain to detect duration as base type

Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 21, 2026

@copilot also update the OpenAPI generation to emit the extension when the encode decorator is present

Implemented in commit d7f45bd. The OpenAPI emitter now adds the x-ms-duration extension when a duration type has an @encode decorator with "seconds" or "milliseconds" encoding. The implementation walks up the scalar chain to properly detect duration as the base type and emits the extension for all format combinations (int32, float, decimal, etc.). All 175 primitive-types tests pass, including 4 new tests for extension emission.

@baywet baywet marked this pull request as ready for review January 21, 2026 14:40
@baywet baywet enabled auto-merge January 21, 2026 14:40
Copilot AI changed the title feat(openapi3): add x-ms-duration extension support for duration encoding feat(openapi3): add bidirectional x-ms-duration extension support for duration encoding Jan 21, 2026
Copilot AI requested a review from baywet January 21, 2026 14:40
@baywet baywet disabled auto-merge January 21, 2026 14:56
@baywet
Copy link
Member

baywet commented Jan 21, 2026

@copilot revert the change where the encode decorator generates the extension. Instead make sure the import also adds an extension decorator when the extension is present in the source document.

…d of auto-generating extension

- Revert export functionality that auto-generated x-ms-duration extension
- Update import to add @extension decorator when x-ms-duration is present
- Both @extension and @encode decorators are now added during import
- Removes extension filtering for x-ms-duration
- Update tests to expect both decorators
- Enables proper round-tripping via @extension decorator

Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 21, 2026

@copilot revert the change where the encode decorator generates the extension. Instead make sure the import also adds an extension decorator when the extension is present in the source document.

Reverted export functionality in commit 3eab35d. The importer now adds both @extension("x-ms-duration", "seconds") and @encode("seconds", int32) decorators when x-ms-duration is present in the OpenAPI source. This enables proper round-tripping using the @extension decorator instead of auto-generating the extension from @encode.

Copilot AI changed the title feat(openapi3): add bidirectional x-ms-duration extension support for duration encoding feat(openapi3): add x-ms-duration extension support for duration encoding with round-trip via @extension decorator Jan 21, 2026
@baywet baywet requested a review from timotheeguerin January 21, 2026 15:26
@baywet
Copy link
Member

baywet commented Jan 21, 2026

@copilot while running integration tests, I'm running into the following issue, regardless of the format, the encode as is always float32. Investigate and correct this behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

emitter:openapi3 Issues for @typespec/openapi3 emitter openapi3:converter Issues for @typespec/openapi3 openapi to typespec converter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

importer - OpenAPI duration properties should result in a duration properties

4 participants