diff --git a/docs/generators/typescript-fetch.md b/docs/generators/typescript-fetch.md
index a51cfe50c40d..1214fd1e5ee1 100644
--- a/docs/generators/typescript-fetch.md
+++ b/docs/generators/typescript-fetch.md
@@ -19,7 +19,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
| Option | Description | Values | Default |
| ------ | ----------- | ------ | ------- |
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
-|dateLibrary|Option. Date library to use.|
- **date**
- Native Date. `format: date` and `format: date-time` are both mapped to Date and (de)serialized by the runtime.
- **string**
- Plain string. Values are passed through untouched, leaving date handling to the consumer.
|date|
+|dateLibrary|Option. Date library to use.|- **date**
- Native Date. `format: date` and `format: date-time` are both mapped to Date and (de)serialized by the runtime.
- **string**
- Plain string. Values are passed through untouched, leaving date handling to the consumer.
- **temporal**
- Native Temporal. `format: date` is mapped to Temporal.PlainDate and `format: date-time` is mapped to Temporal.Instant and (de)serialized by the runtime.
|date|
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|- **false**
- The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.
- **true**
- Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.
|true|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|enumNameSuffix|Suffix that will be appended to all enum names.| |Enum|
@@ -99,6 +99,8 @@ These options may be applied as additional-properties (cli) or configOptions (pl
ReturnType
Set
String
+Temporal.Instant
+Temporal.PlainDate
ThisParameterType
ThisType
Uncapitalize
diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java
index c326ae929ab4..843f9cb89962 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/TypeScriptFetchClientCodegen.java
@@ -67,6 +67,7 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
public static final String DATE_LIBRARY_DESC = "Option. Date library to use.";
public static final String DATE_LIBRARY_DATE = "date";
public static final String DATE_LIBRARY_STRING = "string";
+ public static final String DATE_LIBRARY_TEMPORAL = "temporal";
public static final String STRING_ENUMS = "stringEnums";
public static final String STRING_ENUMS_DESC = "Generate string enums instead of objects for enum values.";
public static final String IMPORT_FILE_EXTENSION_SWITCH = "importFileExtension";
@@ -112,6 +113,8 @@ public class TypeScriptFetchClientCodegen extends AbstractTypeScriptClientCodege
private static final String DATE_TYPE = "date";
private static final String DATE_TIME_TYPE = "DateTime";
private static final String TS_DATE_TYPE = "Date";
+ private static final String TS_TEMPORAL_INSTANT_TYPE = "Temporal.Instant";
+ private static final String TS_TEMPORAL_PLAIN_DATE_TYPE = "Temporal.PlainDate";
protected boolean sagasAndRecords = false;
@Getter @Setter
@@ -143,6 +146,11 @@ public TypeScriptFetchClientCodegen() {
this.addExtraReservedWords();
+ languageSpecificPrimitives.addAll(Arrays.asList(
+ TS_TEMPORAL_INSTANT_TYPE,
+ TS_TEMPORAL_PLAIN_DATE_TYPE
+ ));
+
supportModelPropertyNaming(CodegenConstants.MODEL_PROPERTY_NAMING_TYPE.camelCase);
this.cliOptions.add(new CliOption(NPM_REPOSITORY, "Use this property to set an url your private npmRepo in the package.json"));
this.cliOptions.add(new CliOption(WITH_INTERFACES, "Setting this property to true will generate interfaces next to the default class implementations.", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
@@ -154,6 +162,7 @@ public TypeScriptFetchClientCodegen() {
Map dateOptions = new HashMap<>();
dateOptions.put(DATE_LIBRARY_DATE, "Native Date. `format: date` and `format: date-time` are both mapped to Date and (de)serialized by the runtime.");
dateOptions.put(DATE_LIBRARY_STRING, "Plain string. Values are passed through untouched, leaving date handling to the consumer.");
+ dateOptions.put(DATE_LIBRARY_TEMPORAL, "Native Temporal. `format: date` is mapped to Temporal.PlainDate and `format: date-time` is mapped to Temporal.Instant and (de)serialized by the runtime.");
dateLibraryOption.setEnum(dateOptions);
this.cliOptions.add(dateLibraryOption);
this.cliOptions.add(new CliOption(SAGAS_AND_RECORDS, "Setting this property to true will generate additional files for use with redux-saga and immutablejs.", SchemaTypeUtil.BOOLEAN_TYPE).defaultValue(Boolean.FALSE.toString()));
@@ -349,10 +358,10 @@ public void processOpts() {
// `date` needs the model (de)serialization to convert with, which
// withoutRuntimeChecks removes: the raw string would just be cast to Date.
- if (withoutRuntimeChecks && DATE_LIBRARY_DATE.equals(this.dateLibrary)) {
+ if (withoutRuntimeChecks && (DATE_LIBRARY_DATE.equals(this.dateLibrary) || DATE_LIBRARY_TEMPORAL.equals(this.dateLibrary))) {
if (additionalProperties.containsKey(DATE_LIBRARY)) {
LOGGER.warn("{}={} is not compatible with {}=true; falling back to {}={}.",
- DATE_LIBRARY, DATE_LIBRARY_DATE, WITHOUT_RUNTIME_CHECKS, DATE_LIBRARY, DATE_LIBRARY_STRING);
+ DATE_LIBRARY, this.dateLibrary, WITHOUT_RUNTIME_CHECKS, DATE_LIBRARY, DATE_LIBRARY_STRING);
}
this.dateLibrary = DATE_LIBRARY_STRING;
}
@@ -360,6 +369,9 @@ public void processOpts() {
if (DATE_LIBRARY_DATE.equals(this.dateLibrary)) {
typeMapping.put(DATE_TYPE, TS_DATE_TYPE);
typeMapping.put(DATE_TIME_TYPE, TS_DATE_TYPE);
+ } else if (DATE_LIBRARY_TEMPORAL.equals(this.dateLibrary)) {
+ typeMapping.put(DATE_TYPE, TS_TEMPORAL_PLAIN_DATE_TYPE);
+ typeMapping.put(DATE_TIME_TYPE, TS_TEMPORAL_INSTANT_TYPE);
} else {
typeMapping.put(DATE_TYPE, "string");
typeMapping.put(DATE_TIME_TYPE, "string");
@@ -367,6 +379,8 @@ public void processOpts() {
additionalProperties.put(DATE_LIBRARY, this.dateLibrary);
// Mustache cannot compare strings, so expose the selected library as a flag.
additionalProperties.put("isDateLibraryDate", DATE_LIBRARY_DATE.equals(this.dateLibrary));
+ additionalProperties.put("isDateLibraryString", DATE_LIBRARY_STRING.equals(this.dateLibrary));
+ additionalProperties.put("isDateLibraryTemporal", DATE_LIBRARY_TEMPORAL.equals(this.dateLibrary));
if (additionalProperties.containsKey(SAGAS_AND_RECORDS)) {
this.setSagasAndRecords(convertPropertyToBoolean(SAGAS_AND_RECORDS));
@@ -2125,10 +2139,10 @@ protected String getLicenseNameDefaultValue() {
}
private static boolean isDateType(String dataType) {
- return TS_DATE_TYPE.equals(dataType);
+ return TS_DATE_TYPE.equals(dataType) || TS_TEMPORAL_PLAIN_DATE_TYPE.equals(dataType);
}
private static boolean isDateTimeType(String dataType) {
- return TS_DATE_TYPE.equals(dataType);
+ return TS_DATE_TYPE.equals(dataType) || TS_TEMPORAL_INSTANT_TYPE.equals(dataType);
}
}
diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache
index 339410685eaf..7fa306995134 100644
--- a/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-fetch/apis.mustache
@@ -307,16 +307,28 @@ export class {{classname}} extends runtime.BaseAPI {
let urlPath = `{{{path}}}`;
{{#pathParams}}
{{#isDateTimeType}}
+ {{#isDateLibraryTemporal}}
+ if (requestParameters['{{paramName}}'] instanceof Temporal.Instant) {
+ urlPath = urlPath.replace({{=<< >>=}}'{<>}'<<={{ }}=>>, encodeURIComponent(runtime.serializeDateTime(requestParameters['{{paramName}}'])));
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (requestParameters['{{paramName}}'] instanceof Date) {
urlPath = urlPath.replace({{=<< >>=}}'{<>}'<<={{ }}=>>, encodeURIComponent(runtime.serializeDateTime(requestParameters['{{paramName}}'])));
+ {{/isDateLibraryTemporal}}
} else {
urlPath = urlPath.replace({{=<< >>=}}'{<>}'<<={{ }}=>>, encodeURIComponent(String(requestParameters['{{paramName}}'])));
}
{{/isDateTimeType}}
{{^isDateTimeType}}
{{#isDateType}}
+ {{#isDateLibraryTemporal}}
+ if (requestParameters['{{paramName}}'] instanceof Temporal.PlainDate) {
+ urlPath = urlPath.replace({{=<< >>=}}'{<>}'<<={{ }}=>>, encodeURIComponent(runtime.serializeDate(requestParameters['{{paramName}}'])));
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (requestParameters['{{paramName}}'] instanceof Date) {
urlPath = urlPath.replace({{=<< >>=}}'{<>}'<<={{ }}=>>, encodeURIComponent(runtime.serializeDate(requestParameters['{{paramName}}'])));
+ {{/isDateLibraryTemporal}}
} else {
urlPath = urlPath.replace({{=<< >>=}}'{<>}'<<={{ }}=>>, encodeURIComponent(String(requestParameters['{{paramName}}'])));
}
diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/modelGeneric.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/modelGeneric.mustache
index 7ded36c9d443..547422100bc9 100644
--- a/modules/openapi-generator/src/main/resources/typescript-fetch/modelGeneric.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-fetch/modelGeneric.mustache
@@ -1,4 +1,4 @@
-import { mapValues{{#isDateLibraryDate}}{{#vendorExtensions.x-hasDateVars}}, parseDate, parseDateTime, serializeDate, serializeDateTime{{/vendorExtensions.x-hasDateVars}}{{/isDateLibraryDate}} } from '../runtime{{importFileExtension}}';
+import { mapValues{{^isDateLibraryString}}{{#vendorExtensions.x-hasDateVars}}, parseDate, parseDateTime, serializeDate, serializeDateTime{{/vendorExtensions.x-hasDateVars}}{{/isDateLibraryString}} } from '../runtime{{importFileExtension}}';
{{#hasImports}}
{{#tsImports}}
import type { {{{classname}}} } from './{{filename}}{{importFileExtension}}';
diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache
index d885551721f4..62f9f104f7bf 100644
--- a/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-fetch/modelOneOf.mustache
@@ -1,6 +1,6 @@
-{{#isDateLibraryDate}}
+{{^isDateLibraryString}}
import { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime{{importFileExtension}}';
-{{/isDateLibraryDate}}
+{{/isDateLibraryString}}
{{#hasImports}}
{{#oneOfArrays}}
import type { {{{.}}} } from './{{.}}{{importFileExtension}}';
@@ -72,16 +72,30 @@ export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boole
{{#items}}
{{#isDateType}}
if (Array.isArray(json)) {
+ {{#isDateLibraryTemporal}}
+ try {
+ return json.map(value => parseDate(value));
+ } catch {}
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (json.every(item => !(isNaN(parseDate(item).getTime())))) {
return json.map(value => parseDate(value));
}
+ {{/isDateLibraryTemporal}}
}
{{/isDateType}}
{{#isDateTimeType}}
if (Array.isArray(json)) {
+ {{#isDateLibraryTemporal}}
+ try {
+ return json.map(value => parseDateTime(value));
+ } catch {}
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (json.every(item => !(isNaN(parseDateTime(item).getTime())))) {
return json.map(value => parseDateTime(value));
}
+ {{/isDateLibraryTemporal}}
}
{{/isDateTimeType}}
{{#isNumeric}}
@@ -118,15 +132,29 @@ export function {{classname}}FromJSONTyped(json: any, ignoreDiscriminator: boole
{{#oneOfPrimitives}}
{{^isArray}}
{{#isDateType}}
+ {{#isDateLibraryTemporal}}
+ try {
+ return {{^required}}json == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json == null ? null : {{/isNullable}}{{/required}}parseDate(json));
+ } catch {}
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (!(isNaN(parseDate(json).getTime()))) {
return {{^required}}json == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json == null ? null : {{/isNullable}}{{/required}}parseDate(json));
}
+ {{/isDateLibraryTemporal}}
{{/isDateType}}
{{^isDateType}}
{{#isDateTimeType}}
+ {{#isDateLibraryTemporal}}
+ try {
+ return {{^required}}json == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json == null ? null : {{/isNullable}}{{/required}}parseDateTime(json));
+ } catch {}
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (!(isNaN(parseDateTime(json).getTime()))) {
return {{^required}}json == null ? undefined : {{/required}}({{#required}}{{#isNullable}}json == null ? null : {{/isNullable}}{{/required}}parseDateTime(json));
}
+ {{/isDateLibraryTemporal}}
{{/isDateTimeType}}
{{/isDateType}}
{{#isNumeric}}
@@ -197,16 +225,30 @@ export function {{classname}}ToJSONTyped(value?: {{classname}} | null, ignoreDis
{{#items}}
{{#isDateType}}
if (Array.isArray(value)) {
+ {{#isDateLibraryTemporal}}
+ if (value.every(item => item instanceof Temporal.PlainDate)) {
+ return value.map(value => serializeDate(value));
+ }
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (value.every(item => item instanceof Date)) {
return value.map(value => serializeDate(value));
}
+ {{/isDateLibraryTemporal}}
}
{{/isDateType}}
{{#isDateTimeType}}
if (Array.isArray(value)) {
+ {{#isDateLibraryTemporal}}
+ if (value.every(item => item instanceof Temporal.Instant)) {
+ return value.map(item => serializeDateTime(item));
+ }
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (value.every(item => item instanceof Date)) {
return value.map(item => serializeDateTime(item));
}
+ {{/isDateLibraryTemporal}}
}
{{/isDateTimeType}}
{{#isNumeric}}
@@ -243,14 +285,28 @@ export function {{classname}}ToJSONTyped(value?: {{classname}} | null, ignoreDis
{{#oneOfPrimitives}}
{{^isArray}}
{{#isDateType}}
+ {{#isDateLibraryTemporal}}
+ if (value instanceof Temporal.PlainDate) {
+ return (serializeDate(value{{#isNullable}} as any{{/isNullable}}));
+ }
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (value instanceof Date) {
return (serializeDate(value{{#isNullable}} as any{{/isNullable}}));
}
+ {{/isDateLibraryTemporal}}
{{/isDateType}}
{{#isDateTimeType}}
+ {{#isDateLibraryTemporal}}
+ if (value instanceof Temporal.Instant) {
+ return {{^required}}{{#isNullable}}value === null ? null : {{/isNullable}}{{^isNullable}}value == null ? undefined : {{/isNullable}}{{/required}}(serializeDateTime(value{{#isNullable}} as any{{/isNullable}}));
+ }
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (value instanceof Date) {
return {{^required}}{{#isNullable}}value === null ? null : {{/isNullable}}{{^isNullable}}value == null ? undefined : {{/isNullable}}{{/required}}(serializeDateTime(value{{#isNullable}} as any{{/isNullable}}));
}
+ {{/isDateLibraryTemporal}}
{{/isDateTimeType}}
{{#isNumeric}}
if (typeof value === 'number'{{#isEnum}} && ({{#allowableValues}}{{#values}}value === {{.}}{{^-last}} || {{/-last}}{{/values}}{{/allowableValues}}){{/isEnum}}) {
diff --git a/modules/openapi-generator/src/main/resources/typescript-fetch/runtime.mustache b/modules/openapi-generator/src/main/resources/typescript-fetch/runtime.mustache
index afe6a2bc8b24..ec58f037d84e 100644
--- a/modules/openapi-generator/src/main/resources/typescript-fetch/runtime.mustache
+++ b/modules/openapi-generator/src/main/resources/typescript-fetch/runtime.mustache
@@ -350,9 +350,19 @@ function querystringSingleKey(key: string, value: string | number | null | undef
const valueAsArray = Array.from(value);
return querystringSingleKey(key, valueAsArray, keyPrefix);
}
+ {{#isDateLibraryTemporal}}
+ if (value instanceof Temporal.Instant) {
+ return `${encodeURIComponent(fullKey)}=${encodeURIComponent(serializeDateTime(value))}`;
+ }
+ if (value instanceof Temporal.PlainDate) {
+ return `${encodeURIComponent(fullKey)}=${encodeURIComponent(serializeDate(value))}`;
+ }
+ {{/isDateLibraryTemporal}}
+ {{^isDateLibraryTemporal}}
if (value instanceof Date) {
return `${encodeURIComponent(fullKey)}=${encodeURIComponent(serializeDateTime(value))}`;
}
+ {{/isDateLibraryTemporal}}
if (value instanceof Object) {
return querystring(value as HTTPQuery, fullKey);
}
@@ -364,6 +374,30 @@ export function exists(json: any, key: string) {
return value !== null && value !== undefined;
}
+{{#isDateLibraryTemporal}}
+export function serializeDateTime(value: Temporal.Instant): string {
+ return value.toString();
+}
+
+export function serializeDate(value: Temporal.PlainDate): string {
+ return value.toString({ calendarName: "never" });
+}
+
+export function parseDateTime(value: Temporal.Instant | string): Temporal.Instant {
+ if (value instanceof Temporal.Instant) {
+ return value;
+ }
+ return Temporal.Instant.from(value);
+}
+
+export function parseDate(value: Temporal.PlainDate | string): Temporal.PlainDate {
+ if (value instanceof Temporal.PlainDate) {
+ return value;
+ }
+ return Temporal.PlainDate.from(value);
+}
+{{/isDateLibraryTemporal}}
+{{^isDateLibraryTemporal}}
/**
* Every generated date call site routes through these.
*
@@ -416,6 +450,7 @@ export function parseDateTime(value: any): Date {
return new Date(value);
}
{{/isDateLibraryDate}}
+{{/isDateLibraryTemporal}}
{{^withoutRuntimeChecks}}
export function mapValues(data: any, fn: (item: any) => any) {
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java
index 4c9c71f1f2f2..443e534b03a9 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/typescript/fetch/TypeScriptFetchClientCodegenTest.java
@@ -1100,6 +1100,41 @@ public void testRequiredDatesAreNullGuarded() throws Exception {
"'optionalDateTime': value['optionalDateTime'] == null ? value['optionalDateTime'] : serializeDateTime(value['optionalDateTime']),");
}
+ @Test(description = "Verify required Temporal date and date-time properties are null-guarded on serialization and deserialization")
+ public void testRequiredTemporalInstancesAreNullGuarded() throws Exception {
+ Map properties = new HashMap<>();
+ properties.put("dateLibrary", "temporal");
+ File output = generate(
+ properties,
+ "src/test/resources/3_0/typescript-fetch/required-date.yaml"
+ );
+
+ Path modelPath = Paths.get(output + "/models/Event.ts");
+ TestUtils.assertFileExists(modelPath);
+
+ TestUtils.assertFileContains(modelPath,
+ "'requiredDate': (json['requiredDate'] == null ? json['requiredDate'] : parseDate(json['requiredDate'])),");
+ TestUtils.assertFileContains(modelPath,
+ "'requiredDateTime': (json['requiredDateTime'] == null ? json['requiredDateTime'] : parseDateTime(json['requiredDateTime'])),");
+ TestUtils.assertFileContains(modelPath,
+ "'requiredNullableDate': (json['requiredNullableDate'] == null ? null : parseDate(json['requiredNullableDate'])),");
+ TestUtils.assertFileContains(modelPath,
+ "'requiredNullableDateTime': (json['requiredNullableDateTime'] == null ? null : parseDateTime(json['requiredNullableDateTime'])),");
+ TestUtils.assertFileContains(modelPath,
+ "'optionalDate': json['optionalDate'] == null ? undefined : (parseDate(json['optionalDate'])),");
+ TestUtils.assertFileContains(modelPath,
+ "'optionalDateTime': json['optionalDateTime'] == null ? undefined : (parseDateTime(json['optionalDateTime'])),");
+
+ TestUtils.assertFileContains(modelPath,
+ "'requiredDate': value['requiredDate'] == null ? value['requiredDate'] : serializeDate(value['requiredDate']),");
+ TestUtils.assertFileContains(modelPath,
+ "'requiredDateTime': value['requiredDateTime'] == null ? value['requiredDateTime'] : serializeDateTime(value['requiredDateTime']),");
+ TestUtils.assertFileContains(modelPath,
+ "'requiredNullableDate': value['requiredNullableDate'] == null ? value['requiredNullableDate'] : serializeDate(value['requiredNullableDate']),");
+ TestUtils.assertFileContains(modelPath,
+ "'optionalDateTime': value['optionalDateTime'] == null ? value['optionalDateTime'] : serializeDateTime(value['optionalDateTime']),");
+ }
+
private static File generate(
Map properties
) throws IOException {
@@ -1129,6 +1164,28 @@ public void testDateLibraryDateIsTheDefault() throws IOException {
TestUtils.assertFileContains(venue, "import { mapValues } from '../runtime';");
}
+ @Test(description = "Verify dateLibrary=temporal maps date and date-time to PlainDate and Instant and converts them through the runtime helpers")
+ public void testDateLibraryTemporal() throws IOException {
+ Map properties = new HashMap<>();
+ properties.put("dateLibrary", "temporal");
+ File output = generate(properties, DATE_HANDLING_SPEC);
+
+ Path event = Paths.get(output + "/models/Event.ts");
+ TestUtils.assertFileContains(event, "startsOn: Temporal.PlainDate;");
+ TestUtils.assertFileContains(event, "createdAt?: Temporal.Instant;");
+ TestUtils.assertFileContains(event, "'startsOn': (json['startsOn'] == null ? json['startsOn'] : parseDate(json['startsOn']))");
+ TestUtils.assertFileContains(event, "'createdAt': json['createdAt'] == null ? undefined : (parseDateTime(json['createdAt']))");
+ TestUtils.assertFileContains(event, "'startsOn': value['startsOn'] == null ? value['startsOn'] : serializeDate(value['startsOn'])");
+
+ Path runtime = Paths.get(output + "/runtime.ts");
+ TestUtils.assertFileContains(runtime, "export function parseDate(value: Temporal.PlainDate");
+ TestUtils.assertFileContains(runtime, "export function parseDateTime(value: Temporal.Instant");
+
+ // A model without a date must not import the helpers it cannot use.
+ Path venue = Paths.get(output + "/models/Venue.ts");
+ TestUtils.assertFileContains(venue, "import { mapValues } from '../runtime';");
+ }
+
@Test(description = "Verify dateLibrary=string leaves date values untouched as strings")
public void testDateLibraryString() throws IOException {
Map properties = new HashMap<>();