@odata2ts/odata2ts 0.23.1 → 0.25.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/CHANGELOG.md +22 -0
- package/lib/FactoryFunctionModel.d.ts +13 -13
- package/lib/FactoryFunctionModel.js +2 -2
- package/lib/FactoryFunctionModel.js.map +1 -1
- package/lib/NamingModel.d.ts +182 -182
- package/lib/NamingModel.js +11 -11
- package/lib/NamingModel.js.map +1 -1
- package/lib/OptionModel.d.ts +228 -223
- package/lib/OptionModel.js +23 -23
- package/lib/OptionModel.js.map +1 -1
- package/lib/app.d.ts +8 -8
- package/lib/app.js +67 -63
- package/lib/app.js.map +1 -1
- package/lib/cli.d.ts +3 -3
- package/lib/cli.js +153 -153
- package/lib/data-model/DataModel.d.ts +88 -85
- package/lib/data-model/DataModel.js +141 -134
- package/lib/data-model/DataModel.js.map +1 -1
- package/lib/data-model/DataModelDigestion.d.ts +48 -44
- package/lib/data-model/DataModelDigestion.js +299 -274
- package/lib/data-model/DataModelDigestion.js.map +1 -1
- package/lib/data-model/DataModelDigestionV2.d.ts +10 -10
- package/lib/data-model/DataModelDigestionV2.js +210 -200
- package/lib/data-model/DataModelDigestionV2.js.map +1 -1
- package/lib/data-model/DataModelDigestionV4.d.ts +3 -3
- package/lib/data-model/DataModelDigestionV4.js +197 -195
- package/lib/data-model/DataModelDigestionV4.js.map +1 -1
- package/lib/data-model/DataTypeModel.d.ts +102 -102
- package/lib/data-model/DataTypeModel.js +8 -8
- package/lib/data-model/DataTypeModel.js.map +1 -1
- package/lib/data-model/NamingHelper.d.ts +57 -55
- package/lib/data-model/NamingHelper.js +231 -214
- package/lib/data-model/NamingHelper.js.map +1 -1
- package/lib/data-model/ServiceConfigHelper.d.ts +21 -21
- package/lib/data-model/ServiceConfigHelper.js +113 -113
- package/lib/data-model/edmx/ODataEdmxModelBase.d.ts +92 -80
- package/lib/data-model/edmx/ODataEdmxModelBase.js +2 -2
- package/lib/data-model/edmx/ODataEdmxModelBase.js.map +1 -1
- package/lib/data-model/edmx/ODataEdmxModelV3.d.ts +63 -63
- package/lib/data-model/edmx/ODataEdmxModelV3.js +2 -2
- package/lib/data-model/edmx/ODataEdmxModelV4.d.ts +67 -67
- package/lib/data-model/edmx/ODataEdmxModelV4.js +2 -2
- package/lib/defaultConfig.d.ts +9 -9
- package/lib/defaultConfig.js +165 -164
- package/lib/defaultConfig.js.map +1 -1
- package/lib/evaluateConfig.d.ts +25 -25
- package/lib/evaluateConfig.js +82 -82
- package/lib/generator/ImportContainer.d.ts +16 -16
- package/lib/generator/ImportContainer.js +91 -91
- package/lib/generator/ModelGenerator.d.ts +2 -2
- package/lib/generator/ModelGenerator.js +211 -183
- package/lib/generator/ModelGenerator.js.map +1 -1
- package/lib/generator/QueryObjectGenerator.d.ts +2 -2
- package/lib/generator/QueryObjectGenerator.js +239 -239
- package/lib/generator/ServiceGenerator.d.ts +8 -8
- package/lib/generator/ServiceGenerator.js +422 -422
- package/lib/generator/index.d.ts +3 -3
- package/lib/generator/index.js +9 -9
- package/lib/index.d.ts +3 -3
- package/lib/index.js +6 -6
- package/lib/project/ProjectManager.d.ts +30 -30
- package/lib/project/ProjectManager.js +177 -175
- package/lib/project/ProjectManager.js.map +1 -1
- package/lib/project/formatter/BaseFormatter.d.ts +49 -49
- package/lib/project/formatter/BaseFormatter.js +30 -30
- package/lib/project/formatter/FileFormatter.d.ts +16 -16
- package/lib/project/formatter/FileFormatter.js +2 -2
- package/lib/project/formatter/NoopFormatter.d.ts +29 -29
- package/lib/project/formatter/NoopFormatter.js +42 -42
- package/lib/project/formatter/PrettierFormatter.d.ts +46 -46
- package/lib/project/formatter/PrettierFormatter.js +92 -92
- package/lib/project/formatter/index.d.ts +2 -2
- package/lib/project/formatter/index.js +14 -14
- package/lib/project/logger/logFilePath.d.ts +1 -1
- package/lib/project/logger/logFilePath.js +12 -12
- package/lib/run-cli.d.ts +2 -2
- package/lib/run-cli.js +6 -6
- package/package.json +27 -28
|
@@ -1,423 +1,423 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateServices = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const odata_core_1 = require("@odata2ts/odata-core");
|
|
6
|
-
const deepmerge_1 = tslib_1.__importDefault(require("deepmerge"));
|
|
7
|
-
const ts_morph_1 = require("ts-morph");
|
|
8
|
-
const upper_case_first_1 = require("upper-case-first");
|
|
9
|
-
const processors_1 = require("xml2js/lib/processors");
|
|
10
|
-
const ImportContainer_1 = require("./ImportContainer");
|
|
11
|
-
const ROOT_SERVICE = "ODataService";
|
|
12
|
-
const RESPONSE_TYPES = {
|
|
13
|
-
collection: "ODataCollectionResponse",
|
|
14
|
-
model: "ODataModelResponse",
|
|
15
|
-
value: "ODataValueResponse",
|
|
16
|
-
};
|
|
17
|
-
function generateServices(dataModel, project, version, namingHelper) {
|
|
18
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
19
|
-
const generator = new ServiceGenerator(dataModel, project, version, namingHelper);
|
|
20
|
-
return generator.generate();
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
exports.generateServices = generateServices;
|
|
24
|
-
class ServiceGenerator {
|
|
25
|
-
constructor(dataModel, project, version, namingHelper) {
|
|
26
|
-
this.dataModel = dataModel;
|
|
27
|
-
this.project = project;
|
|
28
|
-
this.version = version;
|
|
29
|
-
this.namingHelper = namingHelper;
|
|
30
|
-
this.generateQOperationProp = (operation) => {
|
|
31
|
-
return {
|
|
32
|
-
scope: ts_morph_1.Scope.Private,
|
|
33
|
-
name: this.namingHelper.getPrivatePropName(operation.qName),
|
|
34
|
-
type: operation.qName,
|
|
35
|
-
hasQuestionToken: true,
|
|
36
|
-
};
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
generate() {
|
|
40
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
41
|
-
const sourceFile = yield this.project.createMainServiceFile();
|
|
42
|
-
const serviceName = this.namingHelper.getMainServiceName();
|
|
43
|
-
const container = this.dataModel.getEntityContainer();
|
|
44
|
-
const unboundOperations = [...Object.values(container.functions), ...Object.values(container.actions)];
|
|
45
|
-
yield this.generateModelServices();
|
|
46
|
-
const importContainer = new ImportContainer_1.ImportContainer(this.namingHelper.getFileNames());
|
|
47
|
-
importContainer.addFromClientApi("ODataHttpClient");
|
|
48
|
-
importContainer.addFromService(ROOT_SERVICE);
|
|
49
|
-
const { properties, methods } = (0, deepmerge_1.default)(this.generateMainServiceProperties(container, importContainer), this.generateMainServiceOperations(unboundOperations, importContainer));
|
|
50
|
-
sourceFile.addClass({
|
|
51
|
-
isExported: true,
|
|
52
|
-
name: serviceName,
|
|
53
|
-
typeParameters: ["ClientType extends ODataHttpClient"],
|
|
54
|
-
extends: `${ROOT_SERVICE}<ClientType>`,
|
|
55
|
-
properties /*: [
|
|
56
|
-
{
|
|
57
|
-
scope: Scope.Private,
|
|
58
|
-
name: this.namingHelper.getPrivatePropName("name"),
|
|
59
|
-
type: "string",
|
|
60
|
-
initializer: `"${this.namingHelper.getODataServiceName()}"`,
|
|
61
|
-
},
|
|
62
|
-
]*/,
|
|
63
|
-
methods,
|
|
64
|
-
});
|
|
65
|
-
sourceFile.addImportDeclarations(importContainer.getImportDeclarations(false));
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
generateMainServiceProperties(container, importContainer) {
|
|
69
|
-
const result = { properties: [], methods: [] };
|
|
70
|
-
Object.values(container.entitySets).forEach(({ name, entityType }) => {
|
|
71
|
-
result.methods.push(this.generateRelatedServiceGetter(name, entityType, importContainer));
|
|
72
|
-
});
|
|
73
|
-
Object.values(container.singletons).forEach((singleton) => {
|
|
74
|
-
result.properties.push(this.generateSingletonProp(singleton, importContainer));
|
|
75
|
-
result.methods.push(this.generateSingletonGetter(singleton));
|
|
76
|
-
});
|
|
77
|
-
return result;
|
|
78
|
-
}
|
|
79
|
-
generateMainServiceOperations(ops, importContainer) {
|
|
80
|
-
const result = { properties: [], methods: [] };
|
|
81
|
-
ops.forEach(({ operation, name }) => {
|
|
82
|
-
result.properties.push(this.generateQOperationProp(operation));
|
|
83
|
-
result.methods.push(this.generateMethod(name, operation, importContainer));
|
|
84
|
-
});
|
|
85
|
-
return result;
|
|
86
|
-
}
|
|
87
|
-
generateRelatedServiceGetter(propName, entityType, importContainer, currentServiceName) {
|
|
88
|
-
const idName = entityType.idModelName;
|
|
89
|
-
const idFunctionName = entityType.qIdFunctionName;
|
|
90
|
-
const serviceName = this.namingHelper.getServiceName(entityType.name);
|
|
91
|
-
const collectionName = this.namingHelper.getCollectionServiceName(entityType.name);
|
|
92
|
-
importContainer.addFromClientApi("ODataHttpClient");
|
|
93
|
-
importContainer.addGeneratedModel(idName);
|
|
94
|
-
importContainer.addGeneratedQObject(idFunctionName);
|
|
95
|
-
// make sure to not falsely import self-referential stuff
|
|
96
|
-
if (!currentServiceName || currentServiceName !== serviceName) {
|
|
97
|
-
importContainer.addGeneratedService(serviceName, collectionName, serviceName);
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
scope: ts_morph_1.Scope.Public,
|
|
101
|
-
name: this.namingHelper.getRelatedServiceGetter(propName),
|
|
102
|
-
parameters: [
|
|
103
|
-
{
|
|
104
|
-
name: "id",
|
|
105
|
-
type: `${idName} | undefined`,
|
|
106
|
-
hasQuestionToken: true,
|
|
107
|
-
},
|
|
108
|
-
],
|
|
109
|
-
overloads: [
|
|
110
|
-
{
|
|
111
|
-
parameters: [],
|
|
112
|
-
returnType: `${collectionName}<ClientType>`,
|
|
113
|
-
},
|
|
114
|
-
{
|
|
115
|
-
parameters: [
|
|
116
|
-
{
|
|
117
|
-
name: "id",
|
|
118
|
-
type: idName,
|
|
119
|
-
},
|
|
120
|
-
],
|
|
121
|
-
returnType: `${serviceName}<ClientType>`,
|
|
122
|
-
},
|
|
123
|
-
],
|
|
124
|
-
statements: [
|
|
125
|
-
`const fieldName = "${propName}";`,
|
|
126
|
-
'return typeof id === "undefined" || id === null',
|
|
127
|
-
`? new ${collectionName}(this.client, this.getPath(), fieldName)`,
|
|
128
|
-
`: new ${serviceName}(this.client, this.getPath(), new ${idFunctionName}(fieldName).buildUrl(id));`,
|
|
129
|
-
],
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
generateSingletonProp(singleton, importContainer) {
|
|
133
|
-
const { name, entityType } = singleton;
|
|
134
|
-
const type = this.namingHelper.getServiceName(entityType.name);
|
|
135
|
-
importContainer.addGeneratedService(this.namingHelper.getServiceName(entityType.name), type);
|
|
136
|
-
return {
|
|
137
|
-
scope: ts_morph_1.Scope.Private,
|
|
138
|
-
name: this.namingHelper.getPrivatePropName(name),
|
|
139
|
-
type: `${type}<ClientType>`,
|
|
140
|
-
hasQuestionToken: true,
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
generateSingletonGetter(singleton) {
|
|
144
|
-
const { name, odataName, entityType } = singleton;
|
|
145
|
-
const propName = "this." + this.namingHelper.getPrivatePropName(name);
|
|
146
|
-
const serviceType = this.namingHelper.getServiceName(entityType.name);
|
|
147
|
-
return {
|
|
148
|
-
scope: ts_morph_1.Scope.Public,
|
|
149
|
-
name: this.namingHelper.getRelatedServiceGetter(name),
|
|
150
|
-
statements: [
|
|
151
|
-
`if(!${propName}) {`,
|
|
152
|
-
// prettier-ignore
|
|
153
|
-
` ${propName} = new ${serviceType}(this.client, this.getPath(), "${odataName}")`,
|
|
154
|
-
"}",
|
|
155
|
-
`return ${propName}`,
|
|
156
|
-
],
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
getVersionSuffix() {
|
|
160
|
-
return this.version === odata_core_1.ODataVersions.V2 ? "V2" : "V4";
|
|
161
|
-
}
|
|
162
|
-
generateEntityTypeService(model, serviceName, serviceFile, importContainer) {
|
|
163
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
164
|
-
const entityServiceType = "EntityTypeService" + this.getVersionSuffix();
|
|
165
|
-
const editableModelName = model.editableName;
|
|
166
|
-
const qObjectName = (0, processors_1.firstCharLowerCase)(model.qName);
|
|
167
|
-
const operations = this.dataModel.getOperationTypeByBinding(model.name);
|
|
168
|
-
const props = [...model.baseProps, ...model.props];
|
|
169
|
-
importContainer.addFromService(entityServiceType);
|
|
170
|
-
importContainer.addFromClientApi("ODataHttpClient");
|
|
171
|
-
importContainer.addGeneratedModel(model.name, editableModelName);
|
|
172
|
-
importContainer.addGeneratedQObject(model.qName, qObjectName);
|
|
173
|
-
const { properties, methods } = (0, deepmerge_1.default)(this.generateServiceProperties(serviceName, props, importContainer), this.generateServiceOperations(operations, importContainer));
|
|
174
|
-
// generate EntityTypeService
|
|
175
|
-
serviceFile.addClass({
|
|
176
|
-
isExported: true,
|
|
177
|
-
name: serviceName,
|
|
178
|
-
typeParameters: ["ClientType extends ODataHttpClient"],
|
|
179
|
-
extends: entityServiceType + `<ClientType, ${model.name}, ${editableModelName}, ${model.qName}>`,
|
|
180
|
-
ctors: [
|
|
181
|
-
{
|
|
182
|
-
parameters: [
|
|
183
|
-
{ name: "client", type: "ClientType" },
|
|
184
|
-
{ name: "basePath", type: "string" },
|
|
185
|
-
{ name: "name", type: "string" },
|
|
186
|
-
],
|
|
187
|
-
statements: [`super(client, basePath, name, ${qObjectName});`],
|
|
188
|
-
},
|
|
189
|
-
],
|
|
190
|
-
properties,
|
|
191
|
-
methods,
|
|
192
|
-
});
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
generateServiceProperties(serviceName, props, importContainer) {
|
|
196
|
-
const collectionServiceType = "CollectionService" + this.getVersionSuffix();
|
|
197
|
-
const result = { properties: [], methods: [] };
|
|
198
|
-
props.forEach((prop) => {
|
|
199
|
-
if ((prop.dataType === "ModelType" /* DataTypes.ModelType */ && !prop.isCollection) || prop.dataType === "ComplexType" /* DataTypes.ComplexType */) {
|
|
200
|
-
result.properties.push(this.generateModelProp(prop, collectionServiceType, serviceName, importContainer));
|
|
201
|
-
result.methods.push(this.generateModelPropGetter(prop, collectionServiceType));
|
|
202
|
-
}
|
|
203
|
-
else if (prop.isCollection) {
|
|
204
|
-
// collection of entity types
|
|
205
|
-
if (prop.dataType === "ModelType" /* DataTypes.ModelType */) {
|
|
206
|
-
const entityType = this.dataModel.getModel(prop.type);
|
|
207
|
-
result.methods.push(this.generateRelatedServiceGetter(prop.name, entityType, importContainer, serviceName));
|
|
208
|
-
}
|
|
209
|
-
// collection of primitive or complex types
|
|
210
|
-
else {
|
|
211
|
-
result.properties.push(this.generatePrimitiveCollectionProp(prop, collectionServiceType, importContainer));
|
|
212
|
-
result.methods.push(this.generatePrimitiveCollectionGetter(prop, collectionServiceType));
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
return result;
|
|
217
|
-
}
|
|
218
|
-
generateServiceOperations(operations, importContainer) {
|
|
219
|
-
const result = { properties: [], methods: [] };
|
|
220
|
-
operations.forEach((operation) => {
|
|
221
|
-
result.properties.push(this.generateQOperationProp(operation));
|
|
222
|
-
result.methods.push(this.generateMethod(operation.name, operation, importContainer));
|
|
223
|
-
});
|
|
224
|
-
return result;
|
|
225
|
-
}
|
|
226
|
-
generateModelProp(prop, collectionServiceType, serviceName, importContainer) {
|
|
227
|
-
const complexType = this.dataModel.getComplexType(prop.type);
|
|
228
|
-
const key = this.namingHelper.getServiceName(prop.type);
|
|
229
|
-
let propModelType = prop.isCollection ? this.namingHelper.getCollectionServiceName(prop.type) : key;
|
|
230
|
-
if (prop.isCollection && complexType) {
|
|
231
|
-
const editableName = complexType.editableName;
|
|
232
|
-
importContainer.addFromService(collectionServiceType);
|
|
233
|
-
importContainer.addGeneratedModel(complexType.name, editableName);
|
|
234
|
-
importContainer.addGeneratedQObject(complexType.qName, (0, processors_1.firstCharLowerCase)(complexType.qName));
|
|
235
|
-
propModelType = `${collectionServiceType}<ClientType, ${complexType.name}, ${complexType.qName}, ${editableName}>`;
|
|
236
|
-
}
|
|
237
|
-
else {
|
|
238
|
-
// don't include imports for this type
|
|
239
|
-
if (serviceName !== key) {
|
|
240
|
-
importContainer.addGeneratedService(key, propModelType);
|
|
241
|
-
}
|
|
242
|
-
propModelType = `${propModelType}<ClientType>`;
|
|
243
|
-
}
|
|
244
|
-
return {
|
|
245
|
-
scope: ts_morph_1.Scope.Private,
|
|
246
|
-
name: this.namingHelper.getPrivatePropName(prop.name),
|
|
247
|
-
type: propModelType,
|
|
248
|
-
hasQuestionToken: true,
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
generatePrimitiveCollectionProp(prop, collectionServiceType, importContainer) {
|
|
252
|
-
const isEnum = prop.dataType === "EnumType" /* DataTypes.EnumType */;
|
|
253
|
-
const type = isEnum ? `EnumCollection<${prop.type}>` : `${(0, upper_case_first_1.upperCaseFirst)(prop.type)}Collection`;
|
|
254
|
-
const qType = isEnum ? "QEnumCollection" : `Q${type}`;
|
|
255
|
-
const collectionType = `${collectionServiceType}<ClientType, ${type}, ${qType}>`;
|
|
256
|
-
if (!prop.qObject) {
|
|
257
|
-
throw new Error("Illegal State: [qObject] must be provided for Collection types!");
|
|
258
|
-
}
|
|
259
|
-
importContainer.addFromService(collectionServiceType);
|
|
260
|
-
importContainer.addFromQObject(prop.qObject, (0, processors_1.firstCharLowerCase)(prop.qObject));
|
|
261
|
-
if (isEnum) {
|
|
262
|
-
importContainer.addGeneratedModel(prop.type);
|
|
263
|
-
importContainer.addFromQObject("EnumCollection");
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
importContainer.addFromQObject(type);
|
|
267
|
-
}
|
|
268
|
-
return {
|
|
269
|
-
scope: ts_morph_1.Scope.Private,
|
|
270
|
-
name: this.namingHelper.getPrivatePropName(prop.name),
|
|
271
|
-
type: `${collectionType}`,
|
|
272
|
-
hasQuestionToken: true,
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
generateModelPropGetter(prop, collectionServiceType) {
|
|
276
|
-
const complexType = this.dataModel.getComplexType(prop.type);
|
|
277
|
-
const isComplexCollection = prop.isCollection && complexType;
|
|
278
|
-
const type = isComplexCollection
|
|
279
|
-
? collectionServiceType
|
|
280
|
-
: prop.isCollection
|
|
281
|
-
? this.namingHelper.getCollectionServiceName(prop.type)
|
|
282
|
-
: this.namingHelper.getServiceName(prop.type);
|
|
283
|
-
const typeWithGenerics = isComplexCollection
|
|
284
|
-
? `${collectionServiceType}<ClientType, ${complexType.name}, ${complexType.qName}, ${complexType.editableName}>`
|
|
285
|
-
: `${type}<ClientType>`;
|
|
286
|
-
const privateSrvProp = "this." + this.namingHelper.getPrivatePropName(prop.name);
|
|
287
|
-
return {
|
|
288
|
-
scope: ts_morph_1.Scope.Public,
|
|
289
|
-
name: this.namingHelper.getRelatedServiceGetter(prop.name),
|
|
290
|
-
returnType: typeWithGenerics,
|
|
291
|
-
statements: [
|
|
292
|
-
`if(!${privateSrvProp}) {`,
|
|
293
|
-
// prettier-ignore
|
|
294
|
-
` ${privateSrvProp} = new ${type}(this.client, this.getPath(), "${prop.odataName}"${isComplexCollection ? `, ${(0, processors_1.firstCharLowerCase)(complexType.qName)}` : ""})`,
|
|
295
|
-
"}",
|
|
296
|
-
`return ${privateSrvProp}`,
|
|
297
|
-
],
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
generatePrimitiveCollectionGetter(prop, collectionServiceType) {
|
|
301
|
-
const propName = "this." + this.namingHelper.getPrivatePropName(prop.name);
|
|
302
|
-
return {
|
|
303
|
-
scope: ts_morph_1.Scope.Public,
|
|
304
|
-
name: this.namingHelper.getRelatedServiceGetter(prop.name),
|
|
305
|
-
statements: [
|
|
306
|
-
`if(!${propName}) {`,
|
|
307
|
-
// prettier-ignore
|
|
308
|
-
` ${propName} = new ${collectionServiceType}(this.client, this.getPath(), "${prop.odataName}", ${(0, processors_1.firstCharLowerCase)(prop.qObject)})`,
|
|
309
|
-
"}",
|
|
310
|
-
`return ${propName}`,
|
|
311
|
-
],
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
generateEntityCollectionService(model, serviceFile, importContainer) {
|
|
315
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
316
|
-
const entitySetServiceType = "EntitySetService" + this.getVersionSuffix();
|
|
317
|
-
const editableModelName = model.editableName;
|
|
318
|
-
const qObjectName = (0, processors_1.firstCharLowerCase)(model.qName);
|
|
319
|
-
importContainer.addFromService(entitySetServiceType);
|
|
320
|
-
importContainer.addGeneratedModel(model.idModelName);
|
|
321
|
-
importContainer.addGeneratedQObject(model.qIdFunctionName);
|
|
322
|
-
const collectionOperations = this.dataModel.getOperationTypeByBinding(`Collection(${model.name})`);
|
|
323
|
-
const { properties, methods } = this.generateServiceOperations(collectionOperations, importContainer);
|
|
324
|
-
serviceFile.addClass({
|
|
325
|
-
isExported: true,
|
|
326
|
-
name: this.namingHelper.getCollectionServiceName(model.name),
|
|
327
|
-
typeParameters: ["ClientType extends ODataHttpClient"],
|
|
328
|
-
extends: entitySetServiceType +
|
|
329
|
-
`<ClientType, ${model.name}, ${editableModelName}, ${model.qName}, ${model.idModelName}>`,
|
|
330
|
-
ctors: [
|
|
331
|
-
{
|
|
332
|
-
parameters: [
|
|
333
|
-
{ name: "client", type: "ClientType" },
|
|
334
|
-
{ name: "basePath", type: "string" },
|
|
335
|
-
{ name: "name", type: "string" },
|
|
336
|
-
],
|
|
337
|
-
statements: [`super(client, basePath, name, ${qObjectName}, new ${model.qIdFunctionName}(name));`],
|
|
338
|
-
},
|
|
339
|
-
],
|
|
340
|
-
properties,
|
|
341
|
-
methods,
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
generateModelServices() {
|
|
346
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
347
|
-
// build service file for each entity, consisting of EntityTypeService & EntityCollectionService
|
|
348
|
-
for (const model of this.dataModel.getModels()) {
|
|
349
|
-
const serviceName = this.namingHelper.getServiceName(model.name);
|
|
350
|
-
const serviceFile = yield this.project.createServiceFile(serviceName);
|
|
351
|
-
const importContainer = new ImportContainer_1.ImportContainer(this.namingHelper.getFileNames());
|
|
352
|
-
// entity type service
|
|
353
|
-
yield this.generateEntityTypeService(model, serviceName, serviceFile, importContainer);
|
|
354
|
-
// entity collection service
|
|
355
|
-
yield this.generateEntityCollectionService(model, serviceFile, importContainer);
|
|
356
|
-
serviceFile.addImportDeclarations(importContainer.getImportDeclarations(true));
|
|
357
|
-
}
|
|
358
|
-
// build service file for complex types
|
|
359
|
-
for (const model of this.dataModel.getComplexTypes()) {
|
|
360
|
-
const serviceName = this.namingHelper.getServiceName(model.name);
|
|
361
|
-
const serviceFile = yield this.project.createServiceFile(serviceName);
|
|
362
|
-
const importContainer = new ImportContainer_1.ImportContainer(this.namingHelper.getFileNames());
|
|
363
|
-
// entity type service
|
|
364
|
-
yield this.generateEntityTypeService(model, serviceName, serviceFile, importContainer);
|
|
365
|
-
serviceFile.addImportDeclarations(importContainer.getImportDeclarations(true));
|
|
366
|
-
}
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
generateMethod(name, operation, importContainer) {
|
|
370
|
-
var _a, _b;
|
|
371
|
-
const isFunc = operation.type === "Function" /* OperationTypes.Function */;
|
|
372
|
-
const odataType = ((_a = operation.returnType) === null || _a === void 0 ? void 0 : _a.isCollection)
|
|
373
|
-
? RESPONSE_TYPES.collection + this.getVersionSuffix()
|
|
374
|
-
: ((_b = operation.returnType) === null || _b === void 0 ? void 0 : _b.dataType) === "PrimitiveType" /* DataTypes.PrimitiveType */
|
|
375
|
-
? RESPONSE_TYPES.value + this.getVersionSuffix()
|
|
376
|
-
: RESPONSE_TYPES.model + this.getVersionSuffix();
|
|
377
|
-
const returnType = operation.returnType;
|
|
378
|
-
const requestConfigParam = {
|
|
379
|
-
name: "requestConfig",
|
|
380
|
-
hasQuestionToken: true,
|
|
381
|
-
type: "ODataHttpClientConfig<ClientType>",
|
|
382
|
-
};
|
|
383
|
-
const hasParams = operation.parameters.length > 0;
|
|
384
|
-
// importing dependencies
|
|
385
|
-
importContainer.addFromClientApi("ODataHttpClientConfig", "ODataResponse");
|
|
386
|
-
importContainer.addFromCore(odataType);
|
|
387
|
-
if (returnType === null || returnType === void 0 ? void 0 : returnType.type) {
|
|
388
|
-
if (["EnumType" /* DataTypes.EnumType */, "ModelType" /* DataTypes.ModelType */, "ComplexType" /* DataTypes.ComplexType */].includes(returnType.dataType)) {
|
|
389
|
-
importContainer.addGeneratedModel(returnType.type);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
importContainer.addGeneratedQObject(operation.qName);
|
|
393
|
-
if (hasParams) {
|
|
394
|
-
importContainer.addGeneratedModel(operation.paramsModelName);
|
|
395
|
-
}
|
|
396
|
-
const qOpProp = "this." + this.namingHelper.getPrivatePropName(operation.qName);
|
|
397
|
-
return {
|
|
398
|
-
scope: ts_morph_1.Scope.Public,
|
|
399
|
-
isAsync: true,
|
|
400
|
-
name,
|
|
401
|
-
parameters: hasParams
|
|
402
|
-
? [{ name: "params", type: operation.paramsModelName }, requestConfigParam]
|
|
403
|
-
: [requestConfigParam],
|
|
404
|
-
returnType: `ODataResponse<${odataType}<${(returnType === null || returnType === void 0 ? void 0 : returnType.type) || "void"}>>`,
|
|
405
|
-
statements: [
|
|
406
|
-
`if(!${qOpProp}) {`,
|
|
407
|
-
` ${qOpProp} = new ${operation.qName}()`,
|
|
408
|
-
"}",
|
|
409
|
-
`const url = this.addFullPath(${qOpProp}.buildUrl(${isFunc && hasParams ? "params" : ""}));`,
|
|
410
|
-
`${returnType ? "const response = await " : "return"} this.client.${!isFunc
|
|
411
|
-
? // actions: since V4
|
|
412
|
-
`post(url, ${hasParams ? `${qOpProp}.convertUserParams(params)` : "{}"}, ${requestConfigParam.name})`
|
|
413
|
-
: operation.usePost
|
|
414
|
-
? // V2 POST => BUT values are still query params, they are not part of the request body
|
|
415
|
-
`post(url, undefined, ${requestConfigParam.name})`
|
|
416
|
-
: // functions: since V2
|
|
417
|
-
`get(url, ${requestConfigParam.name})`};`,
|
|
418
|
-
returnType ? `return ${qOpProp}.convertResponse(response);` : "",
|
|
419
|
-
],
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
}
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateServices = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const odata_core_1 = require("@odata2ts/odata-core");
|
|
6
|
+
const deepmerge_1 = tslib_1.__importDefault(require("deepmerge"));
|
|
7
|
+
const ts_morph_1 = require("ts-morph");
|
|
8
|
+
const upper_case_first_1 = require("upper-case-first");
|
|
9
|
+
const processors_1 = require("xml2js/lib/processors");
|
|
10
|
+
const ImportContainer_1 = require("./ImportContainer");
|
|
11
|
+
const ROOT_SERVICE = "ODataService";
|
|
12
|
+
const RESPONSE_TYPES = {
|
|
13
|
+
collection: "ODataCollectionResponse",
|
|
14
|
+
model: "ODataModelResponse",
|
|
15
|
+
value: "ODataValueResponse",
|
|
16
|
+
};
|
|
17
|
+
function generateServices(dataModel, project, version, namingHelper) {
|
|
18
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
const generator = new ServiceGenerator(dataModel, project, version, namingHelper);
|
|
20
|
+
return generator.generate();
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
exports.generateServices = generateServices;
|
|
24
|
+
class ServiceGenerator {
|
|
25
|
+
constructor(dataModel, project, version, namingHelper) {
|
|
26
|
+
this.dataModel = dataModel;
|
|
27
|
+
this.project = project;
|
|
28
|
+
this.version = version;
|
|
29
|
+
this.namingHelper = namingHelper;
|
|
30
|
+
this.generateQOperationProp = (operation) => {
|
|
31
|
+
return {
|
|
32
|
+
scope: ts_morph_1.Scope.Private,
|
|
33
|
+
name: this.namingHelper.getPrivatePropName(operation.qName),
|
|
34
|
+
type: operation.qName,
|
|
35
|
+
hasQuestionToken: true,
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
generate() {
|
|
40
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
const sourceFile = yield this.project.createMainServiceFile();
|
|
42
|
+
const serviceName = this.namingHelper.getMainServiceName();
|
|
43
|
+
const container = this.dataModel.getEntityContainer();
|
|
44
|
+
const unboundOperations = [...Object.values(container.functions), ...Object.values(container.actions)];
|
|
45
|
+
yield this.generateModelServices();
|
|
46
|
+
const importContainer = new ImportContainer_1.ImportContainer(this.namingHelper.getFileNames());
|
|
47
|
+
importContainer.addFromClientApi("ODataHttpClient");
|
|
48
|
+
importContainer.addFromService(ROOT_SERVICE);
|
|
49
|
+
const { properties, methods } = (0, deepmerge_1.default)(this.generateMainServiceProperties(container, importContainer), this.generateMainServiceOperations(unboundOperations, importContainer));
|
|
50
|
+
sourceFile.addClass({
|
|
51
|
+
isExported: true,
|
|
52
|
+
name: serviceName,
|
|
53
|
+
typeParameters: ["ClientType extends ODataHttpClient"],
|
|
54
|
+
extends: `${ROOT_SERVICE}<ClientType>`,
|
|
55
|
+
properties /*: [
|
|
56
|
+
{
|
|
57
|
+
scope: Scope.Private,
|
|
58
|
+
name: this.namingHelper.getPrivatePropName("name"),
|
|
59
|
+
type: "string",
|
|
60
|
+
initializer: `"${this.namingHelper.getODataServiceName()}"`,
|
|
61
|
+
},
|
|
62
|
+
]*/,
|
|
63
|
+
methods,
|
|
64
|
+
});
|
|
65
|
+
sourceFile.addImportDeclarations(importContainer.getImportDeclarations(false));
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
generateMainServiceProperties(container, importContainer) {
|
|
69
|
+
const result = { properties: [], methods: [] };
|
|
70
|
+
Object.values(container.entitySets).forEach(({ name, entityType }) => {
|
|
71
|
+
result.methods.push(this.generateRelatedServiceGetter(name, entityType, importContainer));
|
|
72
|
+
});
|
|
73
|
+
Object.values(container.singletons).forEach((singleton) => {
|
|
74
|
+
result.properties.push(this.generateSingletonProp(singleton, importContainer));
|
|
75
|
+
result.methods.push(this.generateSingletonGetter(singleton));
|
|
76
|
+
});
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
generateMainServiceOperations(ops, importContainer) {
|
|
80
|
+
const result = { properties: [], methods: [] };
|
|
81
|
+
ops.forEach(({ operation, name }) => {
|
|
82
|
+
result.properties.push(this.generateQOperationProp(operation));
|
|
83
|
+
result.methods.push(this.generateMethod(name, operation, importContainer));
|
|
84
|
+
});
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
generateRelatedServiceGetter(propName, entityType, importContainer, currentServiceName) {
|
|
88
|
+
const idName = entityType.idModelName;
|
|
89
|
+
const idFunctionName = entityType.qIdFunctionName;
|
|
90
|
+
const serviceName = this.namingHelper.getServiceName(entityType.name);
|
|
91
|
+
const collectionName = this.namingHelper.getCollectionServiceName(entityType.name);
|
|
92
|
+
importContainer.addFromClientApi("ODataHttpClient");
|
|
93
|
+
importContainer.addGeneratedModel(idName);
|
|
94
|
+
importContainer.addGeneratedQObject(idFunctionName);
|
|
95
|
+
// make sure to not falsely import self-referential stuff
|
|
96
|
+
if (!currentServiceName || currentServiceName !== serviceName) {
|
|
97
|
+
importContainer.addGeneratedService(serviceName, collectionName, serviceName);
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
scope: ts_morph_1.Scope.Public,
|
|
101
|
+
name: this.namingHelper.getRelatedServiceGetter(propName),
|
|
102
|
+
parameters: [
|
|
103
|
+
{
|
|
104
|
+
name: "id",
|
|
105
|
+
type: `${idName} | undefined`,
|
|
106
|
+
hasQuestionToken: true,
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
overloads: [
|
|
110
|
+
{
|
|
111
|
+
parameters: [],
|
|
112
|
+
returnType: `${collectionName}<ClientType>`,
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
parameters: [
|
|
116
|
+
{
|
|
117
|
+
name: "id",
|
|
118
|
+
type: idName,
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
returnType: `${serviceName}<ClientType>`,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
statements: [
|
|
125
|
+
`const fieldName = "${propName}";`,
|
|
126
|
+
'return typeof id === "undefined" || id === null',
|
|
127
|
+
`? new ${collectionName}(this.client, this.getPath(), fieldName)`,
|
|
128
|
+
`: new ${serviceName}(this.client, this.getPath(), new ${idFunctionName}(fieldName).buildUrl(id));`,
|
|
129
|
+
],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
generateSingletonProp(singleton, importContainer) {
|
|
133
|
+
const { name, entityType } = singleton;
|
|
134
|
+
const type = this.namingHelper.getServiceName(entityType.name);
|
|
135
|
+
importContainer.addGeneratedService(this.namingHelper.getServiceName(entityType.name), type);
|
|
136
|
+
return {
|
|
137
|
+
scope: ts_morph_1.Scope.Private,
|
|
138
|
+
name: this.namingHelper.getPrivatePropName(name),
|
|
139
|
+
type: `${type}<ClientType>`,
|
|
140
|
+
hasQuestionToken: true,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
generateSingletonGetter(singleton) {
|
|
144
|
+
const { name, odataName, entityType } = singleton;
|
|
145
|
+
const propName = "this." + this.namingHelper.getPrivatePropName(name);
|
|
146
|
+
const serviceType = this.namingHelper.getServiceName(entityType.name);
|
|
147
|
+
return {
|
|
148
|
+
scope: ts_morph_1.Scope.Public,
|
|
149
|
+
name: this.namingHelper.getRelatedServiceGetter(name),
|
|
150
|
+
statements: [
|
|
151
|
+
`if(!${propName}) {`,
|
|
152
|
+
// prettier-ignore
|
|
153
|
+
` ${propName} = new ${serviceType}(this.client, this.getPath(), "${odataName}")`,
|
|
154
|
+
"}",
|
|
155
|
+
`return ${propName}`,
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
getVersionSuffix() {
|
|
160
|
+
return this.version === odata_core_1.ODataVersions.V2 ? "V2" : "V4";
|
|
161
|
+
}
|
|
162
|
+
generateEntityTypeService(model, serviceName, serviceFile, importContainer) {
|
|
163
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
164
|
+
const entityServiceType = "EntityTypeService" + this.getVersionSuffix();
|
|
165
|
+
const editableModelName = model.editableName;
|
|
166
|
+
const qObjectName = (0, processors_1.firstCharLowerCase)(model.qName);
|
|
167
|
+
const operations = this.dataModel.getOperationTypeByBinding(model.name);
|
|
168
|
+
const props = [...model.baseProps, ...model.props];
|
|
169
|
+
importContainer.addFromService(entityServiceType);
|
|
170
|
+
importContainer.addFromClientApi("ODataHttpClient");
|
|
171
|
+
importContainer.addGeneratedModel(model.name, editableModelName);
|
|
172
|
+
importContainer.addGeneratedQObject(model.qName, qObjectName);
|
|
173
|
+
const { properties, methods } = (0, deepmerge_1.default)(this.generateServiceProperties(serviceName, props, importContainer), this.generateServiceOperations(operations, importContainer));
|
|
174
|
+
// generate EntityTypeService
|
|
175
|
+
serviceFile.addClass({
|
|
176
|
+
isExported: true,
|
|
177
|
+
name: serviceName,
|
|
178
|
+
typeParameters: ["ClientType extends ODataHttpClient"],
|
|
179
|
+
extends: entityServiceType + `<ClientType, ${model.name}, ${editableModelName}, ${model.qName}>`,
|
|
180
|
+
ctors: [
|
|
181
|
+
{
|
|
182
|
+
parameters: [
|
|
183
|
+
{ name: "client", type: "ClientType" },
|
|
184
|
+
{ name: "basePath", type: "string" },
|
|
185
|
+
{ name: "name", type: "string" },
|
|
186
|
+
],
|
|
187
|
+
statements: [`super(client, basePath, name, ${qObjectName});`],
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
properties,
|
|
191
|
+
methods,
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
generateServiceProperties(serviceName, props, importContainer) {
|
|
196
|
+
const collectionServiceType = "CollectionService" + this.getVersionSuffix();
|
|
197
|
+
const result = { properties: [], methods: [] };
|
|
198
|
+
props.forEach((prop) => {
|
|
199
|
+
if ((prop.dataType === "ModelType" /* DataTypes.ModelType */ && !prop.isCollection) || prop.dataType === "ComplexType" /* DataTypes.ComplexType */) {
|
|
200
|
+
result.properties.push(this.generateModelProp(prop, collectionServiceType, serviceName, importContainer));
|
|
201
|
+
result.methods.push(this.generateModelPropGetter(prop, collectionServiceType));
|
|
202
|
+
}
|
|
203
|
+
else if (prop.isCollection) {
|
|
204
|
+
// collection of entity types
|
|
205
|
+
if (prop.dataType === "ModelType" /* DataTypes.ModelType */) {
|
|
206
|
+
const entityType = this.dataModel.getModel(prop.type);
|
|
207
|
+
result.methods.push(this.generateRelatedServiceGetter(prop.name, entityType, importContainer, serviceName));
|
|
208
|
+
}
|
|
209
|
+
// collection of primitive or complex types
|
|
210
|
+
else {
|
|
211
|
+
result.properties.push(this.generatePrimitiveCollectionProp(prop, collectionServiceType, importContainer));
|
|
212
|
+
result.methods.push(this.generatePrimitiveCollectionGetter(prop, collectionServiceType));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
generateServiceOperations(operations, importContainer) {
|
|
219
|
+
const result = { properties: [], methods: [] };
|
|
220
|
+
operations.forEach((operation) => {
|
|
221
|
+
result.properties.push(this.generateQOperationProp(operation));
|
|
222
|
+
result.methods.push(this.generateMethod(operation.name, operation, importContainer));
|
|
223
|
+
});
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
generateModelProp(prop, collectionServiceType, serviceName, importContainer) {
|
|
227
|
+
const complexType = this.dataModel.getComplexType(prop.type);
|
|
228
|
+
const key = this.namingHelper.getServiceName(prop.type);
|
|
229
|
+
let propModelType = prop.isCollection ? this.namingHelper.getCollectionServiceName(prop.type) : key;
|
|
230
|
+
if (prop.isCollection && complexType) {
|
|
231
|
+
const editableName = complexType.editableName;
|
|
232
|
+
importContainer.addFromService(collectionServiceType);
|
|
233
|
+
importContainer.addGeneratedModel(complexType.name, editableName);
|
|
234
|
+
importContainer.addGeneratedQObject(complexType.qName, (0, processors_1.firstCharLowerCase)(complexType.qName));
|
|
235
|
+
propModelType = `${collectionServiceType}<ClientType, ${complexType.name}, ${complexType.qName}, ${editableName}>`;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
// don't include imports for this type
|
|
239
|
+
if (serviceName !== key) {
|
|
240
|
+
importContainer.addGeneratedService(key, propModelType);
|
|
241
|
+
}
|
|
242
|
+
propModelType = `${propModelType}<ClientType>`;
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
scope: ts_morph_1.Scope.Private,
|
|
246
|
+
name: this.namingHelper.getPrivatePropName(prop.name),
|
|
247
|
+
type: propModelType,
|
|
248
|
+
hasQuestionToken: true,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
generatePrimitiveCollectionProp(prop, collectionServiceType, importContainer) {
|
|
252
|
+
const isEnum = prop.dataType === "EnumType" /* DataTypes.EnumType */;
|
|
253
|
+
const type = isEnum ? `EnumCollection<${prop.type}>` : `${(0, upper_case_first_1.upperCaseFirst)(prop.type)}Collection`;
|
|
254
|
+
const qType = isEnum ? "QEnumCollection" : `Q${type}`;
|
|
255
|
+
const collectionType = `${collectionServiceType}<ClientType, ${type}, ${qType}>`;
|
|
256
|
+
if (!prop.qObject) {
|
|
257
|
+
throw new Error("Illegal State: [qObject] must be provided for Collection types!");
|
|
258
|
+
}
|
|
259
|
+
importContainer.addFromService(collectionServiceType);
|
|
260
|
+
importContainer.addFromQObject(prop.qObject, (0, processors_1.firstCharLowerCase)(prop.qObject));
|
|
261
|
+
if (isEnum) {
|
|
262
|
+
importContainer.addGeneratedModel(prop.type);
|
|
263
|
+
importContainer.addFromQObject("EnumCollection");
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
importContainer.addFromQObject(type);
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
scope: ts_morph_1.Scope.Private,
|
|
270
|
+
name: this.namingHelper.getPrivatePropName(prop.name),
|
|
271
|
+
type: `${collectionType}`,
|
|
272
|
+
hasQuestionToken: true,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
generateModelPropGetter(prop, collectionServiceType) {
|
|
276
|
+
const complexType = this.dataModel.getComplexType(prop.type);
|
|
277
|
+
const isComplexCollection = prop.isCollection && complexType;
|
|
278
|
+
const type = isComplexCollection
|
|
279
|
+
? collectionServiceType
|
|
280
|
+
: prop.isCollection
|
|
281
|
+
? this.namingHelper.getCollectionServiceName(prop.type)
|
|
282
|
+
: this.namingHelper.getServiceName(prop.type);
|
|
283
|
+
const typeWithGenerics = isComplexCollection
|
|
284
|
+
? `${collectionServiceType}<ClientType, ${complexType.name}, ${complexType.qName}, ${complexType.editableName}>`
|
|
285
|
+
: `${type}<ClientType>`;
|
|
286
|
+
const privateSrvProp = "this." + this.namingHelper.getPrivatePropName(prop.name);
|
|
287
|
+
return {
|
|
288
|
+
scope: ts_morph_1.Scope.Public,
|
|
289
|
+
name: this.namingHelper.getRelatedServiceGetter(prop.name),
|
|
290
|
+
returnType: typeWithGenerics,
|
|
291
|
+
statements: [
|
|
292
|
+
`if(!${privateSrvProp}) {`,
|
|
293
|
+
// prettier-ignore
|
|
294
|
+
` ${privateSrvProp} = new ${type}(this.client, this.getPath(), "${prop.odataName}"${isComplexCollection ? `, ${(0, processors_1.firstCharLowerCase)(complexType.qName)}` : ""})`,
|
|
295
|
+
"}",
|
|
296
|
+
`return ${privateSrvProp}`,
|
|
297
|
+
],
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
generatePrimitiveCollectionGetter(prop, collectionServiceType) {
|
|
301
|
+
const propName = "this." + this.namingHelper.getPrivatePropName(prop.name);
|
|
302
|
+
return {
|
|
303
|
+
scope: ts_morph_1.Scope.Public,
|
|
304
|
+
name: this.namingHelper.getRelatedServiceGetter(prop.name),
|
|
305
|
+
statements: [
|
|
306
|
+
`if(!${propName}) {`,
|
|
307
|
+
// prettier-ignore
|
|
308
|
+
` ${propName} = new ${collectionServiceType}(this.client, this.getPath(), "${prop.odataName}", ${(0, processors_1.firstCharLowerCase)(prop.qObject)})`,
|
|
309
|
+
"}",
|
|
310
|
+
`return ${propName}`,
|
|
311
|
+
],
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
generateEntityCollectionService(model, serviceFile, importContainer) {
|
|
315
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
316
|
+
const entitySetServiceType = "EntitySetService" + this.getVersionSuffix();
|
|
317
|
+
const editableModelName = model.editableName;
|
|
318
|
+
const qObjectName = (0, processors_1.firstCharLowerCase)(model.qName);
|
|
319
|
+
importContainer.addFromService(entitySetServiceType);
|
|
320
|
+
importContainer.addGeneratedModel(model.idModelName);
|
|
321
|
+
importContainer.addGeneratedQObject(model.qIdFunctionName);
|
|
322
|
+
const collectionOperations = this.dataModel.getOperationTypeByBinding(`Collection(${model.name})`);
|
|
323
|
+
const { properties, methods } = this.generateServiceOperations(collectionOperations, importContainer);
|
|
324
|
+
serviceFile.addClass({
|
|
325
|
+
isExported: true,
|
|
326
|
+
name: this.namingHelper.getCollectionServiceName(model.name),
|
|
327
|
+
typeParameters: ["ClientType extends ODataHttpClient"],
|
|
328
|
+
extends: entitySetServiceType +
|
|
329
|
+
`<ClientType, ${model.name}, ${editableModelName}, ${model.qName}, ${model.idModelName}>`,
|
|
330
|
+
ctors: [
|
|
331
|
+
{
|
|
332
|
+
parameters: [
|
|
333
|
+
{ name: "client", type: "ClientType" },
|
|
334
|
+
{ name: "basePath", type: "string" },
|
|
335
|
+
{ name: "name", type: "string" },
|
|
336
|
+
],
|
|
337
|
+
statements: [`super(client, basePath, name, ${qObjectName}, new ${model.qIdFunctionName}(name));`],
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
properties,
|
|
341
|
+
methods,
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
generateModelServices() {
|
|
346
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
347
|
+
// build service file for each entity, consisting of EntityTypeService & EntityCollectionService
|
|
348
|
+
for (const model of this.dataModel.getModels()) {
|
|
349
|
+
const serviceName = this.namingHelper.getServiceName(model.name);
|
|
350
|
+
const serviceFile = yield this.project.createServiceFile(serviceName);
|
|
351
|
+
const importContainer = new ImportContainer_1.ImportContainer(this.namingHelper.getFileNames());
|
|
352
|
+
// entity type service
|
|
353
|
+
yield this.generateEntityTypeService(model, serviceName, serviceFile, importContainer);
|
|
354
|
+
// entity collection service
|
|
355
|
+
yield this.generateEntityCollectionService(model, serviceFile, importContainer);
|
|
356
|
+
serviceFile.addImportDeclarations(importContainer.getImportDeclarations(true));
|
|
357
|
+
}
|
|
358
|
+
// build service file for complex types
|
|
359
|
+
for (const model of this.dataModel.getComplexTypes()) {
|
|
360
|
+
const serviceName = this.namingHelper.getServiceName(model.name);
|
|
361
|
+
const serviceFile = yield this.project.createServiceFile(serviceName);
|
|
362
|
+
const importContainer = new ImportContainer_1.ImportContainer(this.namingHelper.getFileNames());
|
|
363
|
+
// entity type service
|
|
364
|
+
yield this.generateEntityTypeService(model, serviceName, serviceFile, importContainer);
|
|
365
|
+
serviceFile.addImportDeclarations(importContainer.getImportDeclarations(true));
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
generateMethod(name, operation, importContainer) {
|
|
370
|
+
var _a, _b;
|
|
371
|
+
const isFunc = operation.type === "Function" /* OperationTypes.Function */;
|
|
372
|
+
const odataType = ((_a = operation.returnType) === null || _a === void 0 ? void 0 : _a.isCollection)
|
|
373
|
+
? RESPONSE_TYPES.collection + this.getVersionSuffix()
|
|
374
|
+
: ((_b = operation.returnType) === null || _b === void 0 ? void 0 : _b.dataType) === "PrimitiveType" /* DataTypes.PrimitiveType */
|
|
375
|
+
? RESPONSE_TYPES.value + this.getVersionSuffix()
|
|
376
|
+
: RESPONSE_TYPES.model + this.getVersionSuffix();
|
|
377
|
+
const returnType = operation.returnType;
|
|
378
|
+
const requestConfigParam = {
|
|
379
|
+
name: "requestConfig",
|
|
380
|
+
hasQuestionToken: true,
|
|
381
|
+
type: "ODataHttpClientConfig<ClientType>",
|
|
382
|
+
};
|
|
383
|
+
const hasParams = operation.parameters.length > 0;
|
|
384
|
+
// importing dependencies
|
|
385
|
+
importContainer.addFromClientApi("ODataHttpClientConfig", "ODataResponse");
|
|
386
|
+
importContainer.addFromCore(odataType);
|
|
387
|
+
if (returnType === null || returnType === void 0 ? void 0 : returnType.type) {
|
|
388
|
+
if (["EnumType" /* DataTypes.EnumType */, "ModelType" /* DataTypes.ModelType */, "ComplexType" /* DataTypes.ComplexType */].includes(returnType.dataType)) {
|
|
389
|
+
importContainer.addGeneratedModel(returnType.type);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
importContainer.addGeneratedQObject(operation.qName);
|
|
393
|
+
if (hasParams) {
|
|
394
|
+
importContainer.addGeneratedModel(operation.paramsModelName);
|
|
395
|
+
}
|
|
396
|
+
const qOpProp = "this." + this.namingHelper.getPrivatePropName(operation.qName);
|
|
397
|
+
return {
|
|
398
|
+
scope: ts_morph_1.Scope.Public,
|
|
399
|
+
isAsync: true,
|
|
400
|
+
name,
|
|
401
|
+
parameters: hasParams
|
|
402
|
+
? [{ name: "params", type: operation.paramsModelName }, requestConfigParam]
|
|
403
|
+
: [requestConfigParam],
|
|
404
|
+
returnType: `ODataResponse<${odataType}<${(returnType === null || returnType === void 0 ? void 0 : returnType.type) || "void"}>>`,
|
|
405
|
+
statements: [
|
|
406
|
+
`if(!${qOpProp}) {`,
|
|
407
|
+
` ${qOpProp} = new ${operation.qName}()`,
|
|
408
|
+
"}",
|
|
409
|
+
`const url = this.addFullPath(${qOpProp}.buildUrl(${isFunc && hasParams ? "params" : ""}));`,
|
|
410
|
+
`${returnType ? "const response = await " : "return"} this.client.${!isFunc
|
|
411
|
+
? // actions: since V4
|
|
412
|
+
`post(url, ${hasParams ? `${qOpProp}.convertUserParams(params)` : "{}"}, ${requestConfigParam.name})`
|
|
413
|
+
: operation.usePost
|
|
414
|
+
? // V2 POST => BUT values are still query params, they are not part of the request body
|
|
415
|
+
`post(url, undefined, ${requestConfigParam.name})`
|
|
416
|
+
: // functions: since V2
|
|
417
|
+
`get(url, ${requestConfigParam.name})`};`,
|
|
418
|
+
returnType ? `return ${qOpProp}.convertResponse(response);` : "",
|
|
419
|
+
],
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
423
|
//# sourceMappingURL=ServiceGenerator.js.map
|