-
Notifications
You must be signed in to change notification settings - Fork 360
Feature: Add @dateFormat decorator
#1796
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d176f35
4c9dcb3
61cb5af
7be46b9
0e8b73e
aff8a16
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "changes": [ | ||
| { | ||
| "packageName": "@typespec/compiler", | ||
| "comment": "**Added** New `@dateFormat` decorator", | ||
| "type": "none" | ||
| } | ||
| ], | ||
| "packageName": "@typespec/compiler" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| { | ||
| "changes": [ | ||
| { | ||
| "packageName": "@typespec/openapi3", | ||
| "comment": "**Added** Support for new `@dateFormat` decorator", | ||
| "type": "none" | ||
| } | ||
| ], | ||
| "packageName": "@typespec/openapi3" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -531,6 +531,23 @@ model Dog extends Pet {kind: "dog", bark: boolean} | |
| ``` | ||
|
|
||
|
|
||
| ### `@dateFormat` {#@dateFormat} | ||
|
|
||
|
|
||
| ```typespec | ||
| dec dateFormat(target: zonedDateTime | ModelProperty, format: rfc1123 | rfc7231 | unixTimeStamp | string) | ||
| ``` | ||
|
|
||
| #### Target | ||
|
|
||
| `union zonedDateTime | ModelProperty` | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this work for duration as well? |
||
|
|
||
| #### Parameters | ||
| | Name | Type | Description | | ||
| |------|------|-------------| | ||
| | format | `union rfc1123 \| rfc7231 \| unixTimeStamp \| string` | | | ||
|
|
||
|
|
||
| ### `@visibility` {#@visibility} | ||
|
|
||
| Indicates that a property is only considered to be present or applicable ("visible") with | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -337,6 +337,9 @@ extern dec projectedName(target: unknown, targetName: string, projectedName: str | |
| */ | ||
| extern dec discriminator(target: object | Union, propertyName: string); | ||
|
|
||
| alias KnownDateFormat = "rfc1123" | "rfc7231" | "unixTimeStamp"; | ||
| extern dec dateFormat(target: zonedDateTime | ModelProperty, format: KnownDateFormat | string); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like shorter names, but dateSerializationFormat is more accurate |
||
|
|
||
| /** | ||
| * Indicates that a property is only considered to be present or applicable ("visible") with | ||
| * the in the given named contexts ("visibilities"). When a property has no visibilities applied | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ import { | |
| EnumMember, | ||
| getAllTags, | ||
| getAnyExtensionFromPath, | ||
| getDateFormat, | ||
| getDiscriminatedUnion, | ||
| getDiscriminator, | ||
| getDoc, | ||
|
|
@@ -1307,6 +1308,16 @@ function createOAPIEmitter(program: Program, options: ResolvedOpenAPI3EmitterOpt | |
| newTarget.format = "password"; | ||
| } | ||
|
|
||
| const dateFormat = getDateFormat(program, typespecType); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also set the default dateFormat, which requires knowing whether the date is used in a header (rfc7231) or elsewhere (rfc 3339)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We’ll in openapi date-time already assume that from what I understand.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK, no, see: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md?plain=1#L170 date-time should be the default for non-header types, but for headers, we need to be explicit
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see, I’ll update |
||
| if (dateFormat) { | ||
| if (dateFormat === "unixTimeStamp") { | ||
| newTarget.type = "integer"; | ||
| newTarget.format = "timestamp"; | ||
| } else { | ||
| newTarget.format = `date-time-${dateFormat}`; | ||
| } | ||
| } | ||
|
|
||
| if (isString) { | ||
| const values = getKnownValues(program, typespecType); | ||
| if (values) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -189,4 +189,56 @@ describe("openapi3: primitives", () => { | |||||
| }); | ||||||
| }); | ||||||
| }); | ||||||
|
|
||||||
| describe("date format", () => { | ||||||
| it("set format to 'date-time' by default", async () => { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should have an alternate where this is ued in a header, and the default format is rfc-7231 |
||||||
| const res = await oapiForModel( | ||||||
| "MyDate", | ||||||
| ` | ||||||
| scalar MyDate extends zonedDateTime; | ||||||
| ` | ||||||
| ); | ||||||
| deepStrictEqual(res.schemas.MyDate, { type: "string", format: "date-time" }); | ||||||
| }); | ||||||
|
|
||||||
| it("set format to 'timestamp' and type to 'ingeger' for 'unixtimestamp' format", async () => { | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| const res = await oapiForModel( | ||||||
| "MyDate", | ||||||
| ` | ||||||
| @dateFormat("unixTimeStamp") | ||||||
| scalar MyDate extends zonedDateTime; | ||||||
| ` | ||||||
| ); | ||||||
| deepStrictEqual(res.schemas.MyDate, { type: "integer", format: "timestamp" }); | ||||||
| }); | ||||||
|
|
||||||
| it("set format to 'date-time-{date-format}' when set on scalar", async () => { | ||||||
| const res = await oapiForModel( | ||||||
| "MyDate", | ||||||
| ` | ||||||
| @dateFormat("rfc1123") | ||||||
| scalar MyDate extends zonedDateTime; | ||||||
| ` | ||||||
| ); | ||||||
| deepStrictEqual(res.schemas.MyDate, { type: "string", format: "date-time-rfc1123" }); | ||||||
| }); | ||||||
|
|
||||||
| it("set format to 'date-time-{date-format}' when set on model property", async () => { | ||||||
| const res = await oapiForModel( | ||||||
| "MyDate", | ||||||
| ` | ||||||
| model MyDate { | ||||||
| @dateFormat("rfc1123") | ||||||
| foo: zonedDateTime; | ||||||
| } | ||||||
|
|
||||||
| op test(): MyDate; | ||||||
| ` | ||||||
| ); | ||||||
| deepStrictEqual(res.schemas.MyDate.properties.foo, { | ||||||
| type: "string", | ||||||
| format: "date-time-rfc1123", | ||||||
| }); | ||||||
| }); | ||||||
| }); | ||||||
| }); | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The values should be rfc3339 and rfc7231. rfc7231 is the replacement for rfc1123