@odata-effect/odata-effect-generator 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/digester/TypeMapper.js +98 -22
- package/dist/cjs/digester/TypeMapper.js.map +1 -1
- package/dist/cjs/generator/Generator.js +10 -5
- package/dist/cjs/generator/Generator.js.map +1 -1
- package/dist/cjs/generator/IndexGenerator.js +7 -6
- package/dist/cjs/generator/IndexGenerator.js.map +1 -1
- package/dist/cjs/generator/ModelsGenerator.js +44 -0
- package/dist/cjs/generator/ModelsGenerator.js.map +1 -1
- package/dist/cjs/generator/NamingHelper.js +23 -1
- package/dist/cjs/generator/NamingHelper.js.map +1 -1
- package/dist/cjs/generator/NavigationGenerator.js +5 -4
- package/dist/cjs/generator/NavigationGenerator.js.map +1 -1
- package/dist/cjs/generator/OperationsGenerator.js +5 -4
- package/dist/cjs/generator/OperationsGenerator.js.map +1 -1
- package/dist/cjs/generator/QueryModelsGenerator.js +3 -2
- package/dist/cjs/generator/QueryModelsGenerator.js.map +1 -1
- package/dist/cjs/generator/ServiceFnGenerator.js +5 -4
- package/dist/cjs/generator/ServiceFnGenerator.js.map +1 -1
- package/dist/cjs/model/GeneratorConfig.js.map +1 -1
- package/dist/dts/digester/TypeMapper.d.ts.map +1 -1
- package/dist/dts/generator/Generator.d.ts +6 -0
- package/dist/dts/generator/Generator.d.ts.map +1 -1
- package/dist/dts/generator/IndexGenerator.d.ts +14 -1
- package/dist/dts/generator/IndexGenerator.d.ts.map +1 -1
- package/dist/dts/generator/ModelsGenerator.d.ts.map +1 -1
- package/dist/dts/generator/NamingHelper.d.ts +15 -0
- package/dist/dts/generator/NamingHelper.d.ts.map +1 -1
- package/dist/dts/generator/NavigationGenerator.d.ts +14 -1
- package/dist/dts/generator/NavigationGenerator.d.ts.map +1 -1
- package/dist/dts/generator/OperationsGenerator.d.ts +14 -1
- package/dist/dts/generator/OperationsGenerator.d.ts.map +1 -1
- package/dist/dts/generator/QueryModelsGenerator.d.ts +14 -1
- package/dist/dts/generator/QueryModelsGenerator.d.ts.map +1 -1
- package/dist/dts/generator/ServiceFnGenerator.d.ts +14 -1
- package/dist/dts/generator/ServiceFnGenerator.d.ts.map +1 -1
- package/dist/dts/model/GeneratorConfig.d.ts +20 -0
- package/dist/dts/model/GeneratorConfig.d.ts.map +1 -1
- package/dist/esm/digester/TypeMapper.js +98 -22
- package/dist/esm/digester/TypeMapper.js.map +1 -1
- package/dist/esm/generator/Generator.js +10 -5
- package/dist/esm/generator/Generator.js.map +1 -1
- package/dist/esm/generator/IndexGenerator.js +8 -7
- package/dist/esm/generator/IndexGenerator.js.map +1 -1
- package/dist/esm/generator/ModelsGenerator.js +44 -0
- package/dist/esm/generator/ModelsGenerator.js.map +1 -1
- package/dist/esm/generator/NamingHelper.js +21 -0
- package/dist/esm/generator/NamingHelper.js.map +1 -1
- package/dist/esm/generator/NavigationGenerator.js +6 -5
- package/dist/esm/generator/NavigationGenerator.js.map +1 -1
- package/dist/esm/generator/OperationsGenerator.js +6 -5
- package/dist/esm/generator/OperationsGenerator.js.map +1 -1
- package/dist/esm/generator/QueryModelsGenerator.js +4 -3
- package/dist/esm/generator/QueryModelsGenerator.js.map +1 -1
- package/dist/esm/generator/ServiceFnGenerator.js +6 -5
- package/dist/esm/generator/ServiceFnGenerator.js.map +1 -1
- package/dist/esm/model/GeneratorConfig.js.map +1 -1
- package/package.json +1 -1
- package/src/digester/TypeMapper.ts +72 -16
- package/src/generator/Generator.ts +15 -5
- package/src/generator/IndexGenerator.ts +27 -6
- package/src/generator/ModelsGenerator.ts +54 -0
- package/src/generator/NamingHelper.ts +26 -0
- package/src/generator/NavigationGenerator.ts +23 -5
- package/src/generator/OperationsGenerator.ts +25 -5
- package/src/generator/QueryModelsGenerator.ts +27 -3
- package/src/generator/ServiceFnGenerator.ts +23 -5
- package/src/model/GeneratorConfig.ts +22 -0
|
@@ -85,6 +85,48 @@ const sortTypesByDependency = <T extends ComplexTypeModel | EntityTypeModel>(
|
|
|
85
85
|
return sorted
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Check if any property uses ODataSchema types.
|
|
90
|
+
*/
|
|
91
|
+
const needsODataSchemaImport = (dataModel: DataModel): boolean => {
|
|
92
|
+
const checkProperties = (properties: ReadonlyArray<PropertyModel>): boolean =>
|
|
93
|
+
properties.some((p) => p.typeMapping.effectSchema.startsWith("ODataSchema."))
|
|
94
|
+
|
|
95
|
+
for (const type of dataModel.entityTypes.values()) {
|
|
96
|
+
if (checkProperties(type.properties)) return true
|
|
97
|
+
}
|
|
98
|
+
for (const type of dataModel.complexTypes.values()) {
|
|
99
|
+
if (checkProperties(type.properties)) return true
|
|
100
|
+
}
|
|
101
|
+
return false
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Check which Effect type imports are needed based on tsType usage.
|
|
106
|
+
*/
|
|
107
|
+
const getNeededEffectTypeImports = (dataModel: DataModel): Set<string> => {
|
|
108
|
+
const needed = new Set<string>()
|
|
109
|
+
|
|
110
|
+
const checkTsType = (tsType: string): void => {
|
|
111
|
+
if (tsType.startsWith("DateTime.")) needed.add("DateTime")
|
|
112
|
+
if (tsType.startsWith("BigDecimal.")) needed.add("BigDecimal")
|
|
113
|
+
if (tsType.startsWith("Duration.")) needed.add("Duration")
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
for (const type of dataModel.entityTypes.values()) {
|
|
117
|
+
for (const prop of type.properties) {
|
|
118
|
+
checkTsType(prop.typeMapping.tsType)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
for (const type of dataModel.complexTypes.values()) {
|
|
122
|
+
for (const prop of type.properties) {
|
|
123
|
+
checkTsType(prop.typeMapping.tsType)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return needed
|
|
128
|
+
}
|
|
129
|
+
|
|
88
130
|
/**
|
|
89
131
|
* Generate the Models.ts file content.
|
|
90
132
|
*
|
|
@@ -106,6 +148,18 @@ export const generateModels = (dataModel: DataModel): string => {
|
|
|
106
148
|
lines.push(` * @since 1.0.0`)
|
|
107
149
|
lines.push(` */`)
|
|
108
150
|
lines.push(`import * as Schema from "effect/Schema"`)
|
|
151
|
+
|
|
152
|
+
// Add Effect type imports if needed (for DateTime, BigDecimal, Duration)
|
|
153
|
+
const effectTypeImports = getNeededEffectTypeImports(dataModel)
|
|
154
|
+
for (const effectType of effectTypeImports) {
|
|
155
|
+
lines.push(`import type * as ${effectType} from "effect/${effectType}"`)
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Add ODataSchema import if needed
|
|
159
|
+
if (needsODataSchemaImport(dataModel)) {
|
|
160
|
+
lines.push(`import { ODataSchema } from "@odata-effect/odata-effect"`)
|
|
161
|
+
}
|
|
162
|
+
|
|
109
163
|
lines.push(``)
|
|
110
164
|
|
|
111
165
|
// Generate enum types (no dependencies, always first)
|
|
@@ -279,3 +279,29 @@ export const getOperationParameterNameWithOverrides = (
|
|
|
279
279
|
// Fall back to default camelCase conversion
|
|
280
280
|
return getPropertyName(odataParamName)
|
|
281
281
|
}
|
|
282
|
+
|
|
283
|
+
// ============================================================================
|
|
284
|
+
// Import path utilities
|
|
285
|
+
// ============================================================================
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Format a relative import path, optionally adding .js extension for ESM compatibility.
|
|
289
|
+
*
|
|
290
|
+
* @param moduleName - The module name (e.g., "Models", "Services")
|
|
291
|
+
* @param esmExtensions - Whether to add .js extension (default: true)
|
|
292
|
+
* @returns The formatted import path (e.g., "./Models.js" or "./Models")
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* formatRelativeImport("Models", true) // "./Models.js"
|
|
296
|
+
* formatRelativeImport("Models", false) // "./Models"
|
|
297
|
+
*
|
|
298
|
+
* @since 1.0.0
|
|
299
|
+
* @category imports
|
|
300
|
+
*/
|
|
301
|
+
export const formatRelativeImport = (
|
|
302
|
+
moduleName: string,
|
|
303
|
+
esmExtensions: boolean = true
|
|
304
|
+
): string => {
|
|
305
|
+
const ext = esmExtensions ? ".js" : ""
|
|
306
|
+
return `./${moduleName}${ext}`
|
|
307
|
+
}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
import type { DataModel, EntityTypeModel } from "../model/DataModel.js"
|
|
25
25
|
import type { ODataVersion } from "../parser/EdmxSchema.js"
|
|
26
|
-
import { getClassName, toCamelCase } from "./NamingHelper.js"
|
|
26
|
+
import { formatRelativeImport, getClassName, toCamelCase } from "./NamingHelper.js"
|
|
27
27
|
|
|
28
28
|
/**
|
|
29
29
|
* Version-specific configuration.
|
|
@@ -166,15 +166,33 @@ const getDerivedTypes = (
|
|
|
166
166
|
return derived
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Options for navigation generation.
|
|
171
|
+
*
|
|
172
|
+
* @since 1.0.0
|
|
173
|
+
* @category types
|
|
174
|
+
*/
|
|
175
|
+
export interface NavigationGeneratorOptions {
|
|
176
|
+
/**
|
|
177
|
+
* Add .js extensions to relative imports for ESM compatibility.
|
|
178
|
+
* @default true
|
|
179
|
+
*/
|
|
180
|
+
readonly esmExtensions?: boolean
|
|
181
|
+
}
|
|
182
|
+
|
|
169
183
|
/**
|
|
170
184
|
* Generate navigation builders.
|
|
171
185
|
*
|
|
172
186
|
* @since 1.0.0
|
|
173
187
|
* @category generation
|
|
174
188
|
*/
|
|
175
|
-
export const generateNavigations = (
|
|
189
|
+
export const generateNavigations = (
|
|
190
|
+
dataModel: DataModel,
|
|
191
|
+
options?: NavigationGeneratorOptions
|
|
192
|
+
): NavigationGenerationResult => {
|
|
193
|
+
const esmExtensions = options?.esmExtensions ?? true
|
|
176
194
|
const moduleName = getPathBuildersModuleName()
|
|
177
|
-
const content = generatePathBuildersFile(dataModel)
|
|
195
|
+
const content = generatePathBuildersFile(dataModel, esmExtensions)
|
|
178
196
|
|
|
179
197
|
return {
|
|
180
198
|
navigationFiles: [{
|
|
@@ -187,7 +205,7 @@ export const generateNavigations = (dataModel: DataModel): NavigationGenerationR
|
|
|
187
205
|
/**
|
|
188
206
|
* Generate the PathBuilders.ts file.
|
|
189
207
|
*/
|
|
190
|
-
const generatePathBuildersFile = (dataModel: DataModel): string => {
|
|
208
|
+
const generatePathBuildersFile = (dataModel: DataModel, esmExtensions: boolean): string => {
|
|
191
209
|
const lines: Array<string> = []
|
|
192
210
|
const versionConfig = getVersionConfig(dataModel.version)
|
|
193
211
|
|
|
@@ -235,7 +253,7 @@ const generatePathBuildersFile = (dataModel: DataModel): string => {
|
|
|
235
253
|
const isLast = i === typesList.length - 1
|
|
236
254
|
lines.push(` ${typesList[i]} as ${typesList[i]}Model${isLast ? "" : ","}`)
|
|
237
255
|
}
|
|
238
|
-
lines.push(`} from "
|
|
256
|
+
lines.push(`} from "${formatRelativeImport("Models", esmExtensions)}"`)
|
|
239
257
|
lines.push(``)
|
|
240
258
|
}
|
|
241
259
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { DataModel, OperationModel, OperationParameterModel } from "../model/DataModel.js"
|
|
10
10
|
import type { ODataVersion } from "../parser/EdmxSchema.js"
|
|
11
|
-
import { toPascalCase } from "./NamingHelper.js"
|
|
11
|
+
import { formatRelativeImport, toPascalCase } from "./NamingHelper.js"
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Version-specific imports and identifiers.
|
|
@@ -73,13 +73,32 @@ export interface OperationsGenerationResult {
|
|
|
73
73
|
readonly operationsFile: GeneratedOperationsFile | null
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Options for operations generation.
|
|
78
|
+
*
|
|
79
|
+
* @since 1.0.0
|
|
80
|
+
* @category types
|
|
81
|
+
*/
|
|
82
|
+
export interface OperationsGeneratorOptions {
|
|
83
|
+
/**
|
|
84
|
+
* Add .js extensions to relative imports for ESM compatibility.
|
|
85
|
+
* @default true
|
|
86
|
+
*/
|
|
87
|
+
readonly esmExtensions?: boolean
|
|
88
|
+
}
|
|
89
|
+
|
|
76
90
|
/**
|
|
77
91
|
* Generate the operations file.
|
|
78
92
|
*
|
|
79
93
|
* @since 1.0.0
|
|
80
94
|
* @category generation
|
|
81
95
|
*/
|
|
82
|
-
export const generateOperations = (
|
|
96
|
+
export const generateOperations = (
|
|
97
|
+
dataModel: DataModel,
|
|
98
|
+
options?: OperationsGeneratorOptions
|
|
99
|
+
): OperationsGenerationResult => {
|
|
100
|
+
const esmExtensions = options?.esmExtensions ?? true
|
|
101
|
+
|
|
83
102
|
// Get unbound operations only (bound operations are attached to entity services)
|
|
84
103
|
const unboundOperations = Array.from(dataModel.operations.values()).filter((op) => !op.isBound)
|
|
85
104
|
|
|
@@ -87,7 +106,7 @@ export const generateOperations = (dataModel: DataModel): OperationsGenerationRe
|
|
|
87
106
|
return { operationsFile: null }
|
|
88
107
|
}
|
|
89
108
|
|
|
90
|
-
const content = generateOperationsFile(unboundOperations, dataModel)
|
|
109
|
+
const content = generateOperationsFile(unboundOperations, dataModel, esmExtensions)
|
|
91
110
|
|
|
92
111
|
return {
|
|
93
112
|
operationsFile: {
|
|
@@ -174,7 +193,8 @@ const collectModelImports = (operations: ReadonlyArray<OperationModel>, dataMode
|
|
|
174
193
|
*/
|
|
175
194
|
const generateOperationsFile = (
|
|
176
195
|
operations: ReadonlyArray<OperationModel>,
|
|
177
|
-
dataModel: DataModel
|
|
196
|
+
dataModel: DataModel,
|
|
197
|
+
esmExtensions: boolean
|
|
178
198
|
): string => {
|
|
179
199
|
const lines: Array<string> = []
|
|
180
200
|
const versionConfig = getVersionConfig(dataModel.version)
|
|
@@ -215,7 +235,7 @@ const generateOperationsFile = (
|
|
|
215
235
|
const isLast = i === importsList.length - 1
|
|
216
236
|
lines.push(` ${importsList[i]}${isLast ? "" : ","}`)
|
|
217
237
|
}
|
|
218
|
-
lines.push(`} from "
|
|
238
|
+
lines.push(`} from "${formatRelativeImport("Models", esmExtensions)}"`)
|
|
219
239
|
lines.push(``)
|
|
220
240
|
}
|
|
221
241
|
|
|
@@ -10,7 +10,27 @@ import type {
|
|
|
10
10
|
NavigationPropertyModel,
|
|
11
11
|
PropertyModel
|
|
12
12
|
} from "../model/DataModel.js"
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
formatRelativeImport,
|
|
15
|
+
getClassName,
|
|
16
|
+
getQueryFactoryName,
|
|
17
|
+
getQueryInstanceName,
|
|
18
|
+
getQueryInterfaceName
|
|
19
|
+
} from "./NamingHelper.js"
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Options for query models generation.
|
|
23
|
+
*
|
|
24
|
+
* @since 1.0.0
|
|
25
|
+
* @category types
|
|
26
|
+
*/
|
|
27
|
+
export interface QueryModelsGeneratorOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Add .js extensions to relative imports for ESM compatibility.
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
readonly esmExtensions?: boolean
|
|
33
|
+
}
|
|
14
34
|
|
|
15
35
|
/**
|
|
16
36
|
* Generate the QueryModels.ts file content.
|
|
@@ -18,7 +38,11 @@ import { getClassName, getQueryFactoryName, getQueryInstanceName, getQueryInterf
|
|
|
18
38
|
* @since 1.0.0
|
|
19
39
|
* @category generation
|
|
20
40
|
*/
|
|
21
|
-
export const generateQueryModels = (
|
|
41
|
+
export const generateQueryModels = (
|
|
42
|
+
dataModel: DataModel,
|
|
43
|
+
options?: QueryModelsGeneratorOptions
|
|
44
|
+
): string => {
|
|
45
|
+
const esmExtensions = options?.esmExtensions ?? true
|
|
22
46
|
const lines: Array<string> = []
|
|
23
47
|
|
|
24
48
|
// Collect all query path types needed
|
|
@@ -48,7 +72,7 @@ export const generateQueryModels = (dataModel: DataModel): string => {
|
|
|
48
72
|
if (usedEntityNames.length > 0) {
|
|
49
73
|
lines.push(`import type {`)
|
|
50
74
|
lines.push(` ${usedEntityNames.join(",\n ")}`)
|
|
51
|
-
lines.push(`} from "
|
|
75
|
+
lines.push(`} from "${formatRelativeImport("Models", esmExtensions)}"`)
|
|
52
76
|
}
|
|
53
77
|
lines.push(``)
|
|
54
78
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { DataModel, EntitySetModel, EntityTypeModel } from "../model/DataModel.js"
|
|
10
10
|
import type { ODataVersion } from "../parser/EdmxSchema.js"
|
|
11
|
-
import { getEditableTypeName, getIdTypeName, getServiceClassName } from "./NamingHelper.js"
|
|
11
|
+
import { formatRelativeImport, getEditableTypeName, getIdTypeName, getServiceClassName } from "./NamingHelper.js"
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Generated service file.
|
|
@@ -31,14 +31,32 @@ export interface ServiceGenerationResult {
|
|
|
31
31
|
readonly servicesFile: GeneratedServiceFile
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Options for service generation.
|
|
36
|
+
*
|
|
37
|
+
* @since 1.0.0
|
|
38
|
+
* @category types
|
|
39
|
+
*/
|
|
40
|
+
export interface ServiceGeneratorOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Add .js extensions to relative imports for ESM compatibility.
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
readonly esmExtensions?: boolean
|
|
46
|
+
}
|
|
47
|
+
|
|
34
48
|
/**
|
|
35
49
|
* Generate the Services.ts file using crud factory.
|
|
36
50
|
*
|
|
37
51
|
* @since 1.0.0
|
|
38
52
|
* @category generation
|
|
39
53
|
*/
|
|
40
|
-
export const generateServiceFns = (
|
|
41
|
-
|
|
54
|
+
export const generateServiceFns = (
|
|
55
|
+
dataModel: DataModel,
|
|
56
|
+
options?: ServiceGeneratorOptions
|
|
57
|
+
): ServiceGenerationResult => {
|
|
58
|
+
const esmExtensions = options?.esmExtensions ?? true
|
|
59
|
+
const content = generateServicesFile(dataModel, esmExtensions)
|
|
42
60
|
return {
|
|
43
61
|
servicesFile: {
|
|
44
62
|
fileName: "Services.ts",
|
|
@@ -50,7 +68,7 @@ export const generateServiceFns = (dataModel: DataModel): ServiceGenerationResul
|
|
|
50
68
|
/**
|
|
51
69
|
* Generate the Services.ts file content.
|
|
52
70
|
*/
|
|
53
|
-
const generateServicesFile = (dataModel: DataModel): string => {
|
|
71
|
+
const generateServicesFile = (dataModel: DataModel, esmExtensions: boolean): string => {
|
|
54
72
|
const lines: Array<string> = []
|
|
55
73
|
const isV4 = dataModel.version === "V4"
|
|
56
74
|
const crudImportPath = isV4
|
|
@@ -97,7 +115,7 @@ const generateServicesFile = (dataModel: DataModel): string => {
|
|
|
97
115
|
const isLast = i === modelImports.length - 1
|
|
98
116
|
lines.push(` ${modelImports[i]}${isLast ? "" : ","}`)
|
|
99
117
|
}
|
|
100
|
-
lines.push(`} from "
|
|
118
|
+
lines.push(`} from "${formatRelativeImport("Models", esmExtensions)}"`)
|
|
101
119
|
lines.push(``)
|
|
102
120
|
|
|
103
121
|
// Re-export types from the crud module
|
|
@@ -4,6 +4,28 @@
|
|
|
4
4
|
* @since 1.0.0
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Generator options for code generation.
|
|
9
|
+
*
|
|
10
|
+
* @since 1.0.0
|
|
11
|
+
* @category config
|
|
12
|
+
*/
|
|
13
|
+
export interface GeneratorOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Add .js extensions to relative imports for ESM compatibility.
|
|
16
|
+
* Required for moduleResolution: node16/nodenext.
|
|
17
|
+
* Default: true (recommended for ESM projects)
|
|
18
|
+
*
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
readonly esmExtensions?: boolean
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Naming overrides for customizing generated type and property names.
|
|
25
|
+
*/
|
|
26
|
+
readonly overrides?: NamingOverrides
|
|
27
|
+
}
|
|
28
|
+
|
|
7
29
|
/**
|
|
8
30
|
* Override configuration for property names.
|
|
9
31
|
* Maps OData property names to TypeScript property names.
|