@odata2ts/odata2ts 0.33.1 → 0.34.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/lib/FactoryFunctionModel.d.ts +3 -3
  3. package/lib/FactoryFunctionModel.js.map +1 -1
  4. package/lib/OptionModel.d.ts +9 -0
  5. package/lib/OptionModel.js.map +1 -1
  6. package/lib/app.js +18 -8
  7. package/lib/app.js.map +1 -1
  8. package/lib/data-model/DataModel.d.ts +12 -6
  9. package/lib/data-model/DataModel.js +10 -0
  10. package/lib/data-model/DataModel.js.map +1 -1
  11. package/lib/data-model/DataModelDigestion.js +37 -20
  12. package/lib/data-model/DataModelDigestion.js.map +1 -1
  13. package/lib/data-model/DataModelDigestionV2.js +1 -1
  14. package/lib/data-model/DataModelDigestionV2.js.map +1 -1
  15. package/lib/data-model/DataModelDigestionV4.js +1 -10
  16. package/lib/data-model/DataModelDigestionV4.js.map +1 -1
  17. package/lib/data-model/DataTypeModel.d.ts +17 -7
  18. package/lib/data-model/DataTypeModel.js.map +1 -1
  19. package/lib/data-model/NamingHelper.d.ts +1 -0
  20. package/lib/data-model/NamingHelper.js +4 -1
  21. package/lib/data-model/NamingHelper.js.map +1 -1
  22. package/lib/data-model/ServiceConfigHelper.js +2 -2
  23. package/lib/data-model/ServiceConfigHelper.js.map +1 -1
  24. package/lib/data-model/validation/NameClashValidator.d.ts +23 -0
  25. package/lib/data-model/validation/NameClashValidator.js +89 -0
  26. package/lib/data-model/validation/NameClashValidator.js.map +1 -0
  27. package/lib/data-model/validation/NameValidator.d.ts +6 -17
  28. package/lib/data-model/validation/NameValidator.js +0 -77
  29. package/lib/data-model/validation/NameValidator.js.map +1 -1
  30. package/lib/data-model/validation/NoopValidator.d.ts +12 -0
  31. package/lib/data-model/validation/NoopValidator.js +34 -0
  32. package/lib/data-model/validation/NoopValidator.js.map +1 -0
  33. package/lib/defaultConfig.js +1 -0
  34. package/lib/defaultConfig.js.map +1 -1
  35. package/lib/generator/ImportContainer.d.ts +44 -11
  36. package/lib/generator/ImportContainer.js +150 -47
  37. package/lib/generator/ImportContainer.js.map +1 -1
  38. package/lib/generator/ImportedNameValidator.d.ts +5 -0
  39. package/lib/generator/ImportedNameValidator.js +26 -0
  40. package/lib/generator/ImportedNameValidator.js.map +1 -0
  41. package/lib/generator/ModelGenerator.js +113 -72
  42. package/lib/generator/ModelGenerator.js.map +1 -1
  43. package/lib/generator/QueryObjectGenerator.js +134 -107
  44. package/lib/generator/QueryObjectGenerator.js.map +1 -1
  45. package/lib/generator/ServiceGenerator.d.ts +1 -1
  46. package/lib/generator/ServiceGenerator.js +160 -161
  47. package/lib/generator/ServiceGenerator.js.map +1 -1
  48. package/lib/generator/import/ImportObjects.d.ts +66 -0
  49. package/lib/generator/import/ImportObjects.js +83 -0
  50. package/lib/generator/import/ImportObjects.js.map +1 -0
  51. package/lib/project/FileHandler.d.ts +28 -0
  52. package/lib/project/FileHandler.js +66 -0
  53. package/lib/project/FileHandler.js.map +1 -0
  54. package/lib/project/ProjectManager.d.ts +44 -18
  55. package/lib/project/ProjectManager.js +156 -111
  56. package/lib/project/ProjectManager.js.map +1 -1
  57. package/lib/project/TsMorphHelper.d.ts +11 -0
  58. package/lib/project/TsMorphHelper.js +66 -0
  59. package/lib/project/TsMorphHelper.js.map +1 -0
  60. package/package.json +10 -8
@@ -7,24 +7,18 @@ const deepmerge_1 = tslib_1.__importDefault(require("deepmerge"));
7
7
  const ts_morph_1 = require("ts-morph");
8
8
  const upper_case_first_1 = require("upper-case-first");
9
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, options) {
10
+ const ImportObjects_1 = require("./import/ImportObjects");
11
+ function generateServices(project, dataModel, version, namingHelper, options) {
18
12
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
19
- const generator = new ServiceGenerator(dataModel, project, version, namingHelper, options);
13
+ const generator = new ServiceGenerator(project, dataModel, version, namingHelper, options);
20
14
  return generator.generate();
21
15
  });
22
16
  }
23
17
  exports.generateServices = generateServices;
24
18
  class ServiceGenerator {
25
- constructor(dataModel, project, version, namingHelper, options = {}) {
26
- this.dataModel = dataModel;
19
+ constructor(project, dataModel, version, namingHelper, options = {}) {
27
20
  this.project = project;
21
+ this.dataModel = dataModel;
28
22
  this.version = version;
29
23
  this.namingHelper = namingHelper;
30
24
  this.options = options;
@@ -42,19 +36,30 @@ class ServiceGenerator {
42
36
  }
43
37
  generate() {
44
38
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
45
- const sourceFile = yield this.project.createMainServiceFile();
46
- const serviceName = this.namingHelper.getMainServiceName();
39
+ const mainServiceName = this.namingHelper.getMainServiceName();
40
+ this.project.initServices();
41
+ yield Promise.all([
42
+ this.generateMainService(mainServiceName),
43
+ ...this.generateEntityTypeServices(),
44
+ ...this.generateComplexTypeServices(),
45
+ ]);
46
+ return this.project.finalizeServices();
47
+ });
48
+ }
49
+ generateMainService(mainServiceName) {
50
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
51
+ const mainServiceFile = this.project.getMainServiceFile();
52
+ const importContainer = mainServiceFile.getImports();
47
53
  const container = this.dataModel.getEntityContainer();
48
54
  const unboundOperations = [...Object.values(container.functions), ...Object.values(container.actions)];
49
- const importContainer = new ImportContainer_1.ImportContainer(this.namingHelper.getFileNames());
50
- importContainer.addFromClientApi("ODataHttpClient");
51
- importContainer.addFromService(ROOT_SERVICE);
55
+ const [httpClient] = importContainer.addClientApi(ImportObjects_1.ClientApiImports.ODataHttpClient);
56
+ const [rootService] = importContainer.addServiceObject(this.version, ImportObjects_1.ServiceImports.ODataService);
52
57
  const { properties, methods } = (0, deepmerge_1.default)(this.generateMainServiceProperties(container, importContainer), this.generateMainServiceOperations(unboundOperations, importContainer));
53
- sourceFile.addClass({
58
+ mainServiceFile.getFile().addClass({
54
59
  isExported: true,
55
- name: serviceName,
56
- typeParameters: ["ClientType extends ODataHttpClient"],
57
- extends: `${ROOT_SERVICE}<ClientType>`,
60
+ name: mainServiceName,
61
+ typeParameters: [`ClientType extends ${httpClient}`],
62
+ extends: `${rootService}<ClientType>`,
58
63
  ctors: this.isV4BigNumber()
59
64
  ? [
60
65
  {
@@ -69,8 +74,6 @@ class ServiceGenerator {
69
74
  properties,
70
75
  methods,
71
76
  });
72
- yield this.generateModelServices(sourceFile, importContainer);
73
- sourceFile.addImportDeclarations(importContainer.getImportDeclarations(false));
74
77
  });
75
78
  }
76
79
  generateMainServiceProperties(container, importContainer) {
@@ -79,7 +82,7 @@ class ServiceGenerator {
79
82
  result.methods.push(this.generateRelatedServiceGetter(name, odataName, entityType, importContainer));
80
83
  });
81
84
  Object.values(container.singletons).forEach((singleton) => {
82
- result.properties.push(this.generateSingletonProp(singleton, importContainer));
85
+ result.properties.push(this.generateSingletonProp(importContainer, singleton));
83
86
  result.methods.push(this.generateSingletonGetter(singleton));
84
87
  });
85
88
  return result;
@@ -92,18 +95,15 @@ class ServiceGenerator {
92
95
  throw new Error(`Operation "${operation}" not found!`);
93
96
  }
94
97
  result.properties.push(this.generateQOperationProp(op));
95
- result.methods.push(this.generateMethod(name, op, importContainer));
98
+ result.methods.push(this.generateMethod(name, op, importContainer, ""));
96
99
  });
97
100
  return result;
98
101
  }
99
- generateRelatedServiceGetter(propName, odataPropName, entityType, importContainer) {
100
- const idName = entityType.idModelName;
101
- const idFunctionName = entityType.qIdFunctionName;
102
- const serviceName = this.namingHelper.getServiceName(entityType.name);
103
- const collectionName = this.namingHelper.getCollectionServiceName(entityType.name);
104
- importContainer.addFromClientApi("ODataHttpClient");
105
- importContainer.addGeneratedModel(idName);
106
- importContainer.addGeneratedQObject(idFunctionName);
102
+ generateRelatedServiceGetter(propName, odataPropName, entityType, imports) {
103
+ const idName = imports.addGeneratedModel(entityType.id.fqName, entityType.id.modelName);
104
+ const idFunctionName = imports.addGeneratedQObject(entityType.id.fqName, entityType.id.qName);
105
+ const serviceName = imports.addGeneratedService(entityType.fqName, entityType.serviceName);
106
+ const collectionName = imports.addGeneratedService(entityType.fqName, entityType.serviceCollectionName);
107
107
  return {
108
108
  scope: ts_morph_1.Scope.Public,
109
109
  name: this.namingHelper.getRelatedServiceGetter(propName),
@@ -138,9 +138,9 @@ class ServiceGenerator {
138
138
  ],
139
139
  };
140
140
  }
141
- generateSingletonProp(singleton, importContainer) {
141
+ generateSingletonProp(importContainer, singleton) {
142
142
  const { name, entityType } = singleton;
143
- const type = this.namingHelper.getServiceName(entityType.name);
143
+ const type = entityType.serviceName;
144
144
  return {
145
145
  scope: ts_morph_1.Scope.Private,
146
146
  name: this.namingHelper.getPrivatePropName(name),
@@ -151,7 +151,7 @@ class ServiceGenerator {
151
151
  generateSingletonGetter(singleton) {
152
152
  const { name, odataName, entityType } = singleton;
153
153
  const propName = "this." + this.namingHelper.getPrivatePropName(name);
154
- const serviceType = this.namingHelper.getServiceName(entityType.name);
154
+ const serviceType = entityType.serviceName;
155
155
  return {
156
156
  scope: ts_morph_1.Scope.Public,
157
157
  name: this.namingHelper.getRelatedServiceGetter(name),
@@ -165,26 +165,24 @@ class ServiceGenerator {
165
165
  ],
166
166
  };
167
167
  }
168
- getVersionSuffix() {
169
- return this.version === odata_core_1.ODataVersions.V2 ? "V2" : "V4";
170
- }
171
- generateEntityTypeService(model, serviceName, serviceFile, importContainer) {
172
- const entityServiceType = "EntityTypeService" + this.getVersionSuffix();
173
- const editableModelName = model.editableName;
174
- const qObjectName = (0, processors_1.firstCharLowerCase)(model.qName);
168
+ generateEntityTypeService(file, model) {
169
+ const importContainer = file.getImports();
175
170
  const operations = this.dataModel.getEntityTypeOperations(model.fqName);
176
171
  const props = [...model.baseProps, ...model.props];
177
- importContainer.addFromService(entityServiceType);
178
- importContainer.addFromClientApi("ODataHttpClient");
179
- importContainer.addGeneratedModel(model.name, editableModelName);
180
- importContainer.addGeneratedQObject(model.qName, qObjectName);
181
- const { properties, methods } = (0, deepmerge_1.default)(this.generateServiceProperties(serviceName, props, importContainer), this.generateServiceOperations(operations, importContainer));
172
+ const [entityServiceType] = importContainer.addServiceObject(this.version, ImportObjects_1.ServiceImports.EntityTypeService);
173
+ const [httpClient] = importContainer.addClientApi(ImportObjects_1.ClientApiImports.ODataHttpClient);
174
+ // note: predictable first imports => no need to take renaming into account
175
+ const modelName = importContainer.addGeneratedModel(model.fqName, model.modelName);
176
+ const editableModelName = importContainer.addGeneratedModel(model.fqName, model.editableName);
177
+ const qName = importContainer.addGeneratedQObject(model.fqName, model.qName);
178
+ const qObjectName = importContainer.addGeneratedQObject(model.fqName, (0, processors_1.firstCharLowerCase)(model.qName));
179
+ const { properties, methods } = (0, deepmerge_1.default)(this.generateServiceProperties(importContainer, model.serviceName, props), this.generateServiceOperations(importContainer, model, operations));
182
180
  // generate EntityTypeService
183
- serviceFile.addClass({
181
+ file.getFile().addClass({
184
182
  isExported: true,
185
- name: serviceName,
186
- typeParameters: ["ClientType extends ODataHttpClient"],
187
- extends: entityServiceType + `<ClientType, ${model.name}, ${editableModelName}, ${model.qName}>`,
183
+ name: model.serviceName,
184
+ typeParameters: [`ClientType extends ${httpClient}`],
185
+ extends: entityServiceType + `<ClientType, ${modelName}, ${editableModelName}, ${qName}>`,
188
186
  ctors: [
189
187
  {
190
188
  parameters: [
@@ -199,16 +197,13 @@ class ServiceGenerator {
199
197
  methods,
200
198
  });
201
199
  }
202
- getPrimitiveServiceType() {
203
- return "PrimitiveTypeService" + this.getVersionSuffix();
204
- }
205
- generateServiceProperties(serviceName, props, importContainer) {
206
- const collectionServiceType = "CollectionService" + this.getVersionSuffix();
200
+ generateServiceProperties(importContainer, serviceName, props) {
207
201
  const result = { properties: [], methods: [] };
208
202
  props.forEach((prop) => {
203
+ // complex types, collection of complex types or entityTypes
209
204
  if ((prop.dataType === "ModelType" /* DataTypes.ModelType */ && !prop.isCollection) || prop.dataType === "ComplexType" /* DataTypes.ComplexType */) {
210
- result.properties.push(this.generateModelProp(prop, collectionServiceType, serviceName, importContainer));
211
- result.methods.push(this.generateModelPropGetter(prop, collectionServiceType));
205
+ result.properties.push(this.generateModelProp(importContainer, prop));
206
+ result.methods.push(this.generateModelPropGetter(importContainer, prop));
212
207
  }
213
208
  else if (prop.isCollection) {
214
209
  // collection of entity types
@@ -219,40 +214,41 @@ class ServiceGenerator {
219
214
  }
220
215
  result.methods.push(this.generateRelatedServiceGetter(prop.name, prop.odataName, entityType, importContainer));
221
216
  }
222
- // collection of primitive or complex types
217
+ // collection of primitive or enum types
223
218
  else {
224
- result.properties.push(this.generatePrimitiveCollectionProp(prop, collectionServiceType, importContainer));
225
- result.methods.push(this.generatePrimitiveCollectionGetter(prop, collectionServiceType));
219
+ result.properties.push(this.generatePrimitiveCollectionProp(importContainer, prop));
220
+ result.methods.push(this.generatePrimitiveCollectionGetter(importContainer, prop));
226
221
  }
227
222
  }
223
+ // generation of services for each primitive property: turned off by default
228
224
  else if (this.options.enablePrimitivePropertyServices && prop.dataType === "PrimitiveType" /* DataTypes.PrimitiveType */) {
229
- result.properties.push(this.generatePrimitiveTypeProp(prop, importContainer));
230
- result.methods.push(this.generatePrimitiveTypeGetter(prop));
225
+ result.properties.push(this.generatePrimitiveTypeProp(importContainer, prop));
226
+ result.methods.push(this.generatePrimitiveTypeGetter(importContainer, prop));
231
227
  }
232
228
  });
233
229
  return result;
234
230
  }
235
- generateServiceOperations(operations, importContainer) {
231
+ generateServiceOperations(importContainer, model, operations) {
236
232
  const result = { properties: [], methods: [] };
237
233
  operations.forEach((operation) => {
238
234
  result.properties.push(this.generateQOperationProp(operation));
239
- result.methods.push(this.generateMethod(operation.name, operation, importContainer));
235
+ result.methods.push(this.generateMethod(operation.name, operation, importContainer, model.fqName));
240
236
  });
241
237
  return result;
242
238
  }
243
- generateModelProp(prop, collectionServiceType, serviceName, importContainer) {
244
- const complexType = this.dataModel.getComplexType(prop.fqType);
245
- const key = this.namingHelper.getServiceName(prop.type);
246
- let propModelType = prop.isCollection ? this.namingHelper.getCollectionServiceName(prop.type) : key;
247
- if (prop.isCollection && complexType) {
248
- const editableName = complexType.editableName;
249
- importContainer.addFromService(collectionServiceType);
250
- importContainer.addGeneratedModel(complexType.name, editableName);
251
- importContainer.addGeneratedQObject(complexType.qName, (0, processors_1.firstCharLowerCase)(complexType.qName));
252
- propModelType = `${collectionServiceType}<ClientType, ${complexType.name}, ${complexType.qName}, ${editableName}>`;
239
+ generateModelProp(imports, prop) {
240
+ const propModel = this.dataModel.getModel(prop.fqType);
241
+ let propModelType;
242
+ if (prop.isCollection) {
243
+ const modelName = imports.addGeneratedModel(propModel.fqName, propModel.modelName);
244
+ const editableModelName = imports.addGeneratedModel(propModel.fqName, propModel.editableName);
245
+ const qModelName = imports.addGeneratedQObject(propModel.fqName, propModel.qName);
246
+ const [collectionServiceType] = imports.addServiceObject(this.version, ImportObjects_1.ServiceImports.CollectionService);
247
+ propModelType = `${collectionServiceType}<ClientType, ${modelName}, ${qModelName}, ${editableModelName}>`;
253
248
  }
254
249
  else {
255
- propModelType = `${propModelType}<ClientType>`;
250
+ const serviceName = imports.addGeneratedService(propModel.fqName, propModel.serviceName);
251
+ propModelType = `${serviceName}<ClientType>`;
256
252
  }
257
253
  return {
258
254
  scope: ts_morph_1.Scope.Private,
@@ -261,23 +257,25 @@ class ServiceGenerator {
261
257
  hasQuestionToken: true,
262
258
  };
263
259
  }
264
- generatePrimitiveCollectionProp(prop, collectionServiceType, importContainer) {
265
- const isEnum = prop.dataType === "EnumType" /* DataTypes.EnumType */;
266
- const type = isEnum ? `EnumCollection<${prop.type}>` : `${(0, upper_case_first_1.upperCaseFirst)(prop.type)}Collection`;
267
- const qType = isEnum ? "QEnumCollection" : prop.qObject;
268
- const collectionType = `${collectionServiceType}<ClientType, ${type}, ${qType}>`;
260
+ generatePrimitiveCollectionProp(imports, prop) {
269
261
  if (!prop.qObject) {
270
262
  throw new Error("Illegal State: [qObject] must be provided for Collection types!");
271
263
  }
272
- importContainer.addFromService(collectionServiceType);
273
- importContainer.addFromQObject(prop.qObject, (0, processors_1.firstCharLowerCase)(prop.qObject));
274
- if (isEnum) {
275
- importContainer.addGeneratedModel(prop.type);
276
- importContainer.addFromQObject("EnumCollection");
264
+ const [collectionServiceType] = imports.addServiceObject(this.version, ImportObjects_1.ServiceImports.CollectionService);
265
+ const isEnum = prop.dataType === "EnumType" /* DataTypes.EnumType */;
266
+ let qType;
267
+ let type;
268
+ if (!isEnum) {
269
+ // TODO move string concat (StringCollection, GuidCollection...) to better place
270
+ [type, qType] = imports.addFromQObject(`${(0, upper_case_first_1.upperCaseFirst)(prop.type)}Collection`, prop.qObject);
277
271
  }
278
272
  else {
279
- importContainer.addFromQObject(type);
273
+ const propEnum = this.dataModel.getModel(prop.fqType);
274
+ const propTypeModel = imports.addGeneratedModel(propEnum.fqName, propEnum.modelName);
275
+ [type, qType] = imports.addQObject(ImportObjects_1.QueryObjectImports.EnumCollection, ImportObjects_1.QueryObjectImports.QEnumCollection);
276
+ type = `${type}<${propTypeModel}>`;
280
277
  }
278
+ const collectionType = `${collectionServiceType}<ClientType, ${type}, ${qType}>`;
281
279
  return {
282
280
  scope: ts_morph_1.Scope.Private,
283
281
  name: this.namingHelper.getPrivatePropName(prop.name),
@@ -285,29 +283,26 @@ class ServiceGenerator {
285
283
  hasQuestionToken: true,
286
284
  };
287
285
  }
288
- generatePrimitiveTypeProp(prop, importContainer) {
289
- const serviceType = this.getPrimitiveServiceType();
290
- importContainer.addFromService(serviceType);
291
- if (prop.typeModule) {
292
- importContainer.addCustomType(prop.typeModule, prop.type);
293
- }
286
+ generatePrimitiveTypeProp(imports, prop) {
287
+ const [serviceType] = imports.addServiceObject(this.version, ImportObjects_1.ServiceImports.PrimitiveTypeService);
288
+ const type = prop.typeModule ? imports.addCustomType(prop.typeModule, prop.type) : prop.type;
294
289
  return {
295
290
  scope: ts_morph_1.Scope.Private,
296
291
  name: this.namingHelper.getPrivatePropName(prop.name),
297
- type: `${serviceType}<ClientType, ${prop.type}>`,
292
+ type: `${serviceType}<ClientType, ${type}>`,
298
293
  hasQuestionToken: true,
299
294
  };
300
295
  }
301
- generateModelPropGetter(prop, collectionServiceType) {
302
- const complexType = this.dataModel.getComplexType(prop.fqType);
303
- const isComplexCollection = prop.isCollection && complexType;
296
+ generateModelPropGetter(imports, prop) {
297
+ const model = this.dataModel.getModel(prop.fqType);
298
+ const isComplexCollection = prop.isCollection && model.dataType === "ComplexType" /* DataTypes.ComplexType */;
304
299
  const type = isComplexCollection
305
- ? collectionServiceType
300
+ ? imports.addServiceObject(this.version, ImportObjects_1.ServiceImports.CollectionService)[0]
306
301
  : prop.isCollection
307
- ? this.namingHelper.getCollectionServiceName(prop.type)
308
- : this.namingHelper.getServiceName(prop.type);
302
+ ? model.serviceCollectionName
303
+ : model.serviceName;
309
304
  const typeWithGenerics = isComplexCollection
310
- ? `${collectionServiceType}<ClientType, ${complexType.name}, ${complexType.qName}, ${complexType.editableName}>`
305
+ ? `${type}<ClientType, ${imports.addGeneratedModel(model.fqName, model.modelName)}, ${imports.addGeneratedQObject(model.fqName, model.qName)}, ${imports.addGeneratedModel(model.fqName, model.editableName)}>`
311
306
  : `${type}<ClientType>`;
312
307
  const privateSrvProp = "this." + this.namingHelper.getPrivatePropName(prop.name);
313
308
  return {
@@ -318,13 +313,16 @@ class ServiceGenerator {
318
313
  `if(!${privateSrvProp}) {`,
319
314
  ` const { client, path } = this.__base;`,
320
315
  // prettier-ignore
321
- ` ${privateSrvProp} = new ${type}(client, path, "${prop.odataName}"${isComplexCollection ? `, ${(0, processors_1.firstCharLowerCase)(complexType.qName)}` : ""})`,
316
+ ` ${privateSrvProp} = new ${type}(client, path, "${prop.odataName}"${isComplexCollection ? `, ${imports.addGeneratedQObject(model.fqName, (0, processors_1.firstCharLowerCase)(model.qName))}` : ""})`,
322
317
  "}",
323
318
  `return ${privateSrvProp}`,
324
319
  ],
325
320
  };
326
321
  }
327
- generatePrimitiveCollectionGetter(prop, collectionServiceType) {
322
+ generatePrimitiveCollectionGetter(imports, prop) {
323
+ const [collectionServiceType] = imports.addServiceObject(this.version, ImportObjects_1.ServiceImports.CollectionService);
324
+ const instanceName = (0, processors_1.firstCharLowerCase)(prop.qObject);
325
+ const [qInstanceName] = imports.addFromQObject(instanceName);
328
326
  const propName = "this." + this.namingHelper.getPrivatePropName(prop.name);
329
327
  return {
330
328
  scope: ts_morph_1.Scope.Public,
@@ -333,14 +331,14 @@ class ServiceGenerator {
333
331
  `if(!${propName}) {`,
334
332
  ` const { client, path } = this.__base;`,
335
333
  // prettier-ignore
336
- ` ${propName} = new ${collectionServiceType}(client, path, "${prop.odataName}", ${(0, processors_1.firstCharLowerCase)(prop.qObject)}${this.isV4BigNumber() ? ", true" : ""})`,
334
+ ` ${propName} = new ${collectionServiceType}(client, path, "${prop.odataName}", ${qInstanceName}${this.isV4BigNumber() ? ", true" : ""})`,
337
335
  "}",
338
336
  `return ${propName}`,
339
337
  ],
340
338
  };
341
339
  }
342
- generatePrimitiveTypeGetter(prop) {
343
- const serviceType = this.getPrimitiveServiceType();
340
+ generatePrimitiveTypeGetter(imports, prop) {
341
+ const [serviceType] = imports.addServiceObject(this.version, ImportObjects_1.ServiceImports.PrimitiveTypeService);
344
342
  const propName = "this." + this.namingHelper.getPrivatePropName(prop.name);
345
343
  // for V2: mapped name must be specified
346
344
  const useMappedName = this.version === odata_core_1.ODataVersions.V2 && prop.name !== prop.odataName;
@@ -359,21 +357,21 @@ class ServiceGenerator {
359
357
  ],
360
358
  };
361
359
  }
362
- generateEntityCollectionService(model, serviceFile, importContainer) {
363
- const entitySetServiceType = "EntitySetService" + this.getVersionSuffix();
360
+ generateEntityCollectionService(file, model) {
361
+ const importContainer = file.getImports();
364
362
  const editableModelName = model.editableName;
365
363
  const qObjectName = (0, processors_1.firstCharLowerCase)(model.qName);
366
- importContainer.addFromService(entitySetServiceType);
367
- importContainer.addGeneratedModel(model.idModelName);
368
- importContainer.addGeneratedQObject(model.qIdFunctionName);
364
+ const [entitySetServiceType] = importContainer.addServiceObject(this.version, ImportObjects_1.ServiceImports.EntitySetService);
365
+ const paramsModelName = importContainer.addGeneratedModel(model.id.fqName, model.id.modelName);
366
+ const qIdFunctionName = importContainer.addGeneratedQObject(model.id.fqName, model.id.qName);
369
367
  const collectionOperations = this.dataModel.getEntitySetOperations(model.fqName);
370
- const { properties, methods } = this.generateServiceOperations(collectionOperations, importContainer);
371
- serviceFile.addClass({
368
+ const { properties, methods } = this.generateServiceOperations(importContainer, model, collectionOperations);
369
+ file.getFile().addClass({
372
370
  isExported: true,
373
- name: this.namingHelper.getCollectionServiceName(model.name),
371
+ name: model.serviceCollectionName,
374
372
  typeParameters: ["ClientType extends ODataHttpClient"],
375
373
  extends: entitySetServiceType +
376
- `<ClientType, ${model.name}, ${editableModelName}, ${model.qName}, ${model.idModelName}>`,
374
+ `<ClientType, ${model.modelName}, ${editableModelName}, ${model.qName}, ${paramsModelName}>`,
377
375
  ctors: [
378
376
  {
379
377
  parameters: [
@@ -382,7 +380,7 @@ class ServiceGenerator {
382
380
  { name: "name", type: "string" },
383
381
  ],
384
382
  statements: [
385
- `super(client, basePath, name, ${qObjectName}, new ${model.qIdFunctionName}(name)${this.isV4BigNumber() ? ", true" : ""});`,
383
+ `super(client, basePath, name, ${qObjectName}, new ${qIdFunctionName}(name)${this.isV4BigNumber() ? ", true" : ""});`,
386
384
  ],
387
385
  },
388
386
  ],
@@ -390,67 +388,60 @@ class ServiceGenerator {
390
388
  methods,
391
389
  });
392
390
  }
393
- generateModelServices(serviceFile, importContainer) {
394
- return tslib_1.__awaiter(this, void 0, void 0, function* () {
395
- // build service file for each entity, consisting of EntityTypeService & EntityCollectionService
396
- const entities = this.dataModel.getEntityTypes().filter((et) => !et.abstract);
397
- for (const model of entities) {
398
- const serviceName = this.namingHelper.getServiceName(model.name);
399
- // entity type service
400
- this.generateEntityTypeService(model, serviceName, serviceFile, importContainer);
401
- // entity collection service if this entity specified keys at all
402
- if (model.keyNames.length) {
403
- this.generateEntityCollectionService(model, serviceFile, importContainer);
404
- }
405
- }
406
- // build service file for complex types
407
- const complexTypes = this.dataModel.getComplexTypes().filter((ct) => !ct.abstract);
408
- for (const model of complexTypes) {
409
- const serviceName = this.namingHelper.getServiceName(model.name);
410
- // entity type service
411
- this.generateEntityTypeService(model, serviceName, serviceFile, importContainer);
391
+ generateEntityTypeServices() {
392
+ // build service file for each entity, consisting of EntityTypeService & EntityCollectionService
393
+ return this.dataModel.getEntityTypes().map((model) => {
394
+ const file = this.project.createOrGetServiceFile(model.folderPath, model.serviceName, [
395
+ model.serviceName,
396
+ model.serviceCollectionName,
397
+ ]);
398
+ // entity type service
399
+ this.generateEntityTypeService(file, model);
400
+ // entity collection service if this entity specified keys at all
401
+ if (model.keyNames.length) {
402
+ this.generateEntityCollectionService(file, model);
412
403
  }
404
+ return this.project.finalizeFile(file);
413
405
  });
414
406
  }
415
- generateMethod(name, operation, importContainer) {
416
- var _a, _b;
407
+ generateComplexTypeServices() {
408
+ // build service file for complex types
409
+ return this.dataModel.getComplexTypes().map((model) => {
410
+ const file = this.project.createOrGetServiceFile(model.folderPath, model.serviceName, [model.serviceName]);
411
+ // entity type service
412
+ this.generateEntityTypeService(file, model);
413
+ return this.project.finalizeFile(file);
414
+ });
415
+ }
416
+ generateMethod(name, operation, importContainer, baseFqName) {
417
417
  const isFunc = operation.type === "Function" /* OperationTypes.Function */;
418
- const odataType = ((_a = operation.returnType) === null || _a === void 0 ? void 0 : _a.isCollection)
419
- ? RESPONSE_TYPES.collection + this.getVersionSuffix()
420
- : ((_b = operation.returnType) === null || _b === void 0 ? void 0 : _b.dataType) === "PrimitiveType" /* DataTypes.PrimitiveType */
421
- ? RESPONSE_TYPES.value + this.getVersionSuffix()
422
- : RESPONSE_TYPES.model + this.getVersionSuffix();
423
418
  const returnType = operation.returnType;
419
+ const hasParams = operation.parameters.length > 0;
420
+ // importing dependencies
421
+ const [httpClientConfigModel, odataResponse] = importContainer.addClientApi(ImportObjects_1.ClientApiImports.ODataHttpClientConfig, ImportObjects_1.ClientApiImports.HttpResponseModel);
422
+ const responseStructure = this.importReturnType(importContainer, returnType);
423
+ const qOperationName = importContainer.addGeneratedQObject(baseFqName, operation.qName);
424
+ const rtType = (returnType === null || returnType === void 0 ? void 0 : returnType.type) && returnType.dataType !== "PrimitiveType" /* DataTypes.PrimitiveType */
425
+ ? importContainer.addGeneratedModel(returnType.fqType, returnType.type)
426
+ : returnType === null || returnType === void 0 ? void 0 : returnType.type;
427
+ const paramsModelName = hasParams
428
+ ? importContainer.addGeneratedModel(baseFqName, operation.paramsModelName)
429
+ : undefined;
424
430
  const requestConfigParam = {
425
431
  name: "requestConfig",
426
432
  hasQuestionToken: true,
427
- type: "ODataHttpClientConfig<ClientType>",
433
+ type: `${httpClientConfigModel}<ClientType>`,
428
434
  };
429
- const hasParams = operation.parameters.length > 0;
430
- // importing dependencies
431
- importContainer.addFromClientApi("ODataHttpClientConfig", "ODataResponse");
432
- importContainer.addFromCore(odataType);
433
- if (returnType === null || returnType === void 0 ? void 0 : returnType.type) {
434
- if (["EnumType" /* DataTypes.EnumType */, "ModelType" /* DataTypes.ModelType */, "ComplexType" /* DataTypes.ComplexType */].includes(returnType.dataType)) {
435
- importContainer.addGeneratedModel(returnType.type);
436
- }
437
- }
438
- importContainer.addGeneratedQObject(operation.qName);
439
- if (hasParams) {
440
- importContainer.addGeneratedModel(operation.paramsModelName);
441
- }
442
435
  const qOpProp = "this." + this.namingHelper.getPrivatePropName(operation.qName);
443
436
  return {
444
437
  scope: ts_morph_1.Scope.Public,
445
438
  isAsync: true,
446
439
  name,
447
- parameters: hasParams
448
- ? [{ name: "params", type: operation.paramsModelName }, requestConfigParam]
449
- : [requestConfigParam],
450
- returnType: `ODataResponse<${odataType}<${(returnType === null || returnType === void 0 ? void 0 : returnType.type) || "void"}>>`,
440
+ parameters: hasParams ? [{ name: "params", type: paramsModelName }, requestConfigParam] : [requestConfigParam],
441
+ returnType: `Promise<${odataResponse}<${responseStructure}<${rtType || "void"}>>>`,
451
442
  statements: [
452
443
  `if(!${qOpProp}) {`,
453
- ` ${qOpProp} = new ${operation.qName}()`,
444
+ ` ${qOpProp} = new ${qOperationName}()`,
454
445
  "}",
455
446
  `const { addFullPath, client, getDefaultHeaders } = this.__base;`,
456
447
  `const url = addFullPath(${qOpProp}.buildUrl(${isFunc && hasParams ? "params" : ""}));`,
@@ -466,5 +457,13 @@ class ServiceGenerator {
466
457
  ],
467
458
  };
468
459
  }
460
+ importReturnType(imports, returnType) {
461
+ const typeToImport = (returnType === null || returnType === void 0 ? void 0 : returnType.isCollection)
462
+ ? ImportObjects_1.CoreImports.ODataCollectionResponse
463
+ : (returnType === null || returnType === void 0 ? void 0 : returnType.dataType) === "PrimitiveType" /* DataTypes.PrimitiveType */
464
+ ? ImportObjects_1.CoreImports.ODataValueResponse
465
+ : ImportObjects_1.CoreImports.ODataModelResponse;
466
+ return imports.addCoreLib(this.version, typeToImport)[0];
467
+ }
469
468
  }
470
469
  //# sourceMappingURL=ServiceGenerator.js.map