⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
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
  • Fix encoding type detection to use effectiveType (handles type arrays)
  • Support integer formats (int8-uint64) for number type with x-ms-duration
  • 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:
    • Accept effectiveType parameter to properly handle OpenAPI 3.1 type arrays like ["integer", "null"]
    • Generate appropriate @encode decorators based on both the x-ms-duration value and the schema's format
    • Support all integer formats (int8, int16, int32, int64, uint8, uint16, uint32, uint64) even when type is "number"
    • Support all number formats (float, double, decimal, decimal128)
    • Use effectiveType instead of schema.type to avoid defaulting to float32 when type is an array
  • 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 (33 tests)
  • Added test cases in generate-type.test.ts for inline type expressions (82 tests)
  • All tests pass successfully
  • Manual testing confirms correct encoding types for all formats (int8-uint64, float32, float64, decimal, etc.)

Supported scenarios:

OAS type OAS format OAS x-ms-duration TypeSpec Output
string duration not applicable duration
integer int32 absent int32
integer int32 present, set to seconds @extension("x-ms-duration", "seconds") @encode("seconds", int32) ... duration
number int64 present, set to seconds @extension("x-ms-duration", "seconds") @encode("seconds", int64) ... duration
number float absent float32
number float present, set to seconds @extension("x-ms-duration", "seconds") @encode("seconds", float32) ... duration
number decimal present, set to seconds @extension("x-ms-duration", "seconds") @encode("seconds", decimal) ... duration
number double present, set to milliseconds @extension("x-ms-duration", "milliseconds") @encode("milliseconds", float64) ... duration

Example transformations:

Integer type with int32 format:

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

Number type with int64 format:

# OpenAPI
DurationNumberInt64:
  type: number
  format: int64
  x-ms-duration: seconds
// TypeSpec
@extension("x-ms-duration", "seconds")
@encode("seconds", int64)
scalar DurationNumberInt64 extends duration;

Number type with decimal format:

# OpenAPI
DurationDecimalSeconds:
  type: number
  format: decimal
  x-ms-duration: seconds
// TypeSpec
@extension("x-ms-duration", "seconds")
@encode("seconds", decimal)
scalar DurationDecimalSeconds 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: 2cc9286

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

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.

…encoding format

- Pass effectiveType to getDurationSchemaDecorators to handle OpenAPI 3.1 type arrays
- Fixes issue where format was always float32 regardless of actual format
- Update test expectations to match TypeSpec compiler's decorator ordering
- Now correctly generates int32, float32, float64, decimal based on schema format

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

Copilot AI 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.

Fixed in commit 446c2e1. The issue was that getDurationSchemaDecorators was using schema.type directly, which fails for OpenAPI 3.1 type arrays like ["integer", "null"]. Now it uses effectiveType (the extracted non-null type) to correctly determine the encoding format. All formats (int32, float32, float64, decimal, etc.) now work correctly.

Copilot AI requested a review from baywet January 21, 2026 18:24
@baywet
Copy link
Member

baywet commented Jan 22, 2026

@copilot Add a data-types test for this format combination:

type: number
format: int64
x-ms-duration: seconds

The result should be @encode("seconds", int64) (and the type duration)
If the test fails, correct the implementation so it passes.

… with x-ms-duration

- Add support for integer formats (int8, int16, int32, int64, uint8, uint16, uint32, uint64) when type is number
- Fixes scenario where type: number, format: int64, x-ms-duration: seconds now correctly generates @encode("seconds", int64)
- Add test case for number with int64 format and x-ms-duration extension
- All 33 data-types tests pass

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

Copilot AI commented Jan 22, 2026

@copilot Add a data-types test for this format combination:

...

Added test in commit 8772da4. The test initially failed (was generating @encode("seconds", float32) instead of @encode("seconds", int64)), so I updated the implementation to support all integer formats (int8-uint64) when the type is "number". The test now passes and correctly generates @encode("seconds", int64) for type: number, format: int64, x-ms-duration: seconds.

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