Skip to content

Commit ab6ca60

Browse files
authored
feat(v4)!: Respect precision for Odata V4 type Edm.DateTimeOffset (#5361)
1 parent 3b4fe5d commit ab6ca60

File tree

30 files changed

+144
-49
lines changed

30 files changed

+144
-49
lines changed

.changeset/funny-shrimps-visit.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@sap-cloud-sdk/generator': major
3+
'@sap-cloud-sdk/odata-v4': major
4+
'@sap-cloud-sdk/odata-common': major
5+
---
6+
7+
[Improvement] Support precision handling during serialization of `Edm.DateTimeOffset` fields in OData v4.

packages/generator/src/edmx-parser/common/edmx-types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ export interface EdmxProperty extends EdmxDocumented, EdmxNamed {
6161
* @internal
6262
*/
6363
Type: string;
64+
/**
65+
* @internal
66+
*/
67+
Precision?: string;
6468
}
6569
/**
6670
* @internal

packages/generator/src/edmx-to-vdm/common/entity.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ function properties(
119119
description: propertyDescription(p, swaggerProp),
120120
nullable: isNullableProperty(p),
121121
maxLength: p.MaxLength,
122+
precision: p.Precision === undefined ? undefined : parseInt(p.Precision),
122123
isComplex,
123124
isEnum,
124125
isCollection

packages/generator/src/entity/namespace.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ function getFieldInitializer(
7979
*/
8080
export function createPropertyFieldInitializerForEntity(
8181
prop: VdmProperty,
82-
fieldBuilderName = '_fieldBuilder'
82+
fieldBuilderName = '_fieldBuilder',
83+
service?: VdmServiceMetadata
8384
): string {
8485
if (prop.isCollection) {
8586
if (prop.isComplex) {
@@ -99,9 +100,20 @@ export function createPropertyFieldInitializerForEntity(
99100
return `${fieldBuilderName}.buildEnumField('${prop.originalName}', ${prop.jsType}, ${prop.nullable})`;
100101
}
101102

102-
return `${fieldBuilderName}.buildEdmTypeField('${prop.originalName}', '${prop.edmType}', ${prop.nullable})`;
103+
return `${fieldBuilderName}.buildEdmTypeField('${prop.originalName}', '${
104+
prop.edmType
105+
}', ${prop.nullable}${
106+
prop.precision !== undefined &&
107+
isPrecisionAwareEdmType(prop.edmType) &&
108+
service?.oDataVersion === 'v4'
109+
? `, ${prop.precision}`
110+
: ''
111+
})`;
103112
}
104113

114+
function isPrecisionAwareEdmType(value: string): boolean {
115+
return value === 'Edm.DateTimeOffset';
116+
}
105117
/**
106118
* @internal
107119
*/

packages/generator/src/generator-without-ts-morph/entity-api/class.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Use the service function as described in the documentation to get an API instanc
9595
get schema() {
9696
if (!this._schema) {
9797
const fieldBuilder = this.fieldBuilder;
98-
this._schema = ${getSchema(entity)};
98+
this._schema = ${getSchema(entity, service)};
9999
}
100100
101101
return this._schema;

packages/generator/src/generator-without-ts-morph/entity-api/schema.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,40 @@
11
import { documentationBlock } from '@sap-cloud-sdk/util';
22
import { addLeadingNewline, getStaticPropertyDescription } from '../../typedoc';
33
import { createPropertyFieldInitializerForEntity } from '../../entity';
4-
import type { VdmEntity, VdmProperty } from '../../vdm-types';
4+
import type {
5+
VdmEntity,
6+
VdmProperty,
7+
VdmServiceMetadata
8+
} from '../../vdm-types';
59

610
/**
711
* @internal
812
*/
9-
export function getSchema(entity: VdmEntity): string {
13+
export function getSchema(
14+
entity: VdmEntity,
15+
service?: VdmServiceMetadata
16+
): string {
1017
return `{
1118
${[
12-
...properties(entity),
19+
...properties(entity, service),
1320
'...this.navigationPropertyFields',
1421
// ...navigationProperties(entity, service),
1522
allFieldsSelector(entity)
1623
].join(',\n')}
1724
}`;
1825
}
1926

20-
function properties(entity: VdmEntity): string[] {
21-
return entity.properties.map(prop => property(prop));
27+
function properties(entity: VdmEntity, service?: VdmServiceMetadata): string[] {
28+
return entity.properties.map(prop => property(prop, service));
2229
}
2330

24-
function property(prop: VdmProperty): string {
31+
function property(prop: VdmProperty, service?: VdmServiceMetadata): string {
2532
return [
2633
documentationBlock`${getStaticPropertyDescription(prop)}`,
2734
`${prop.staticPropertyName}: ${createPropertyFieldInitializerForEntity(
2835
prop,
29-
'fieldBuilder'
36+
'fieldBuilder',
37+
service
3038
)}`
3139
].join('\n');
3240
}

packages/generator/src/typedoc.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ function addConstraints(
173173
if (constraints.nullable) {
174174
description += `${unixEOL}@nullable`;
175175
}
176+
if (constraints.precision !== undefined) {
177+
description += `${unixEOL}Precision: ${constraints.precision}.`;
178+
}
176179

177180
return description;
178181
}

packages/generator/src/vdm-types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ export interface VdmPropertyValueConstraints {
176176
* @internal
177177
*/
178178
nullable: boolean;
179+
/**
180+
* @internal
181+
*/
182+
precision?: number;
179183
}
180184
/**
181185
* @internal

packages/odata-common/src/de-serializers/de-serializers.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export interface DeSerializer<DeserializedT> {
9898
* @param value - Deserialized value to serialize.
9999
* @returns Serialized value.
100100
*/
101-
serialize: (value: DeserializedT) => any;
101+
serialize: (value: DeserializedT, precision?: number) => any;
102102

103103
/**
104104
* Function to serialize a value for use in a URI.
@@ -152,9 +152,9 @@ export function createValueDeserializer<DeSerializersT extends DeSerializers>(
152152
*/
153153
export function createValueSerializer<DeSerializersT extends DeSerializers>(
154154
deSerializers: DeSerializersT
155-
): <EdmT>(value: any, edmType: EdmT) => any {
156-
return (value, edmType) => {
155+
): <EdmT>(value: any, edmType: EdmT, precision?: number) => any {
156+
return (value, edmType, precision) => {
157157
const serialize = deSerializers[edmType as any]?.serialize;
158-
return serialize ? serialize(value) : value;
158+
return serialize ? serialize(value, precision) : value;
159159
};
160160
}

packages/odata-common/src/de-serializers/default-de-serializers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,12 @@ export const defaultDeSerializersRaw: DefaultDeSerializers = {
124124
function wrapDefaultSerializer<T>(
125125
serialize: DeSerializer<T>['serialize']
126126
): DeSerializer<T>['serialize'] {
127-
return function (value) {
127+
return function (value, precision?) {
128128
if (value === null) {
129129
return 'null';
130130
}
131131
if (serialize) {
132-
return serialize(value);
132+
return serialize(value, precision);
133133
}
134134
return value;
135135
};

0 commit comments

Comments
 (0)