SAP / cloud-sdk-js

Use the SAP Cloud SDK for JavaScript / TypeScript to reduce development effort when building applications on SAP Business Technology Platform that communicate with SAP solutions and services such as SAP S/4HANA Cloud, SAP SuccessFactors, and many others.
Apache License 2.0
162 stars 56 forks source link

How to get properties & their datatype of properties of any API class (VDM api class) #1509

Closed h2plucifer closed 3 years ago

h2plucifer commented 3 years ago

Hi ,

I need to know how can I get json structure (fieldname: type) for all the properties available for specific api class Ex. For BusinessPartner class i.e. @sap/cloud-sdk-vdm-business-partner-service['BusinessPartner'] I want to get all the properties with theirs datatypes.

{ ACADEMIC_TITLE : string, FIRST_NAME: string, BUSINESS_PARTNER_CATEGORY :string ............ ............ }

Let me know if there is any way to get this kind of structure using vdm/SAP cloud sdk.

Thanks

jjtang1985 commented 3 years ago

Hi @h2plucifer ,

thanks for approaching us.

I guess you can use the interface BusinessPartnerType, where the "property to data type" mapping is available. However, please be aware, the naming pattern in the interface is camel case.

The API doc of the VDM can be found here. In addition to the data type, there might be additional information like the length to a string.

I hope this answers your question.

Let me know if it does not help.

Best regards, Junjie

h2plucifer commented 3 years ago

Hi @jjtang1985 ,

Thanks for the information, I will check those mentioned suggestions & will update if there's any further input needed.

Regards

h2plucifer commented 3 years ago

Hi @jjtang1985

Current implementation/evaluation has been done with Javascript only & trying to utilize VDM module functionalities directly importing as npm package.

Following is the brief implementation apprach:

Currently trying to expose entity data structure (property & its datatype // ex json format ) to user so that they would be able to see which all properties are available for a particular API class (ex. BusinessPartner) & can provide needed values for those properties.

Tried accessing field values through _allFields , _keyFields (ex. BusinessPartner._keyFields )but it returns complex structure.

<ref *62> Link { _fieldName: 'to_BusinessPartnerBank', _entityConstructor: [Function: BusinessPartner] { builder: [Function (anonymous)], requestBuilder: [Function (anonymous)], customField: [Function (anonymous)], _entityName: 'A_BusinessPartner', _defaultServicePath: '/sap/opu/odata/sap/API_BUSINESS_PARTNER', BUSINESS_PARTNER: [StringField], CUSTOMER: [StringField], SUPPLIER: [StringField], ACADEMIC_TITLE: [StringField], AUTHORIZATION_GROUP: [StringField],

Let me know if getting properties & datatypes in this way is correct or there is another approach I can look into.(At present scenario using typescript file won't work (Implementaton based on JS only ) ) .

Thanks

jjtang1985 commented 3 years ago

Hi @h2plucifer ,

I guess the _allFields is not designed in the way for your use case. Of course, this direction is still possible, but you need a mapping from StringField to string. Also, you need to handle all the edge cases like collection/enum/complex type/nullable properties. Therefore, I would NOT recommend this way.

Have you tried the options I provided? Please correct me, you might need the json as a documentation for the user?

Best regards, Junjie

h2plucifer commented 3 years ago

Hi @jjtang1985 ,

I checked the input you provided earlier (BusinessPartner.d.ts) , it does have the required properties & datatypes (along with the expected camelCase naming : as this format is used in entity builder().fromJson({firstName:""}) )

But the issue is currently using typescript files of npm package in our current POC , thats not supported at this moment.

I also checked VDM doc but still not understanding how can those datatypes be directly utilized inside our implementation by importing @sap/cloud-sdk-vdm-business-partner-service in our module.

Also there will be usage of other VDMs as well in the implementation (ex. CostCenter etc) so checking for a generic way of getting properties & datatype.

Main objective is to get properties & datatype/datastructure of a particular API class of any vdm service.

Sorry if my understanding is lacking with your suggestions, but if possible to provide suggestive pseudo code for how can I achieve the result let me know.

Thanks

h2plucifer commented 3 years ago

Currently also working into some utility functionality that will read respective typescript files (BusinessPartner.d.ts, CostCenter.d.ts.... etc )& will create required structure.

But do let me know if there could be any other possibility directly through npm VDM.

jjtang1985 commented 3 years ago

Hi @h2plucifer ,

I know your goal is to generate some json like the example provided:

{
ACADEMIC_TITLE : string,
...
}

Currently trying to expose entity data structure (property & its datatype // ex json format ) to user so that they would be able to see which all properties are available for a particular API class

If I understood correctly, the reason why you wanted to have this json was just for documentation purposes.

Therefore, my previous suggestions went to the same direction.

As I mentioned, using _allFields might also be possible, but it's cumbersome. I think your current work about some utility functionality makes senses, which might be easiest solution.

I'm afraid the current SDK does not really support your feature. If you like, I can convert this to a feature request, but it might not have high priority. @artemkovalyov

Best regards, Junjie

h2plucifer commented 3 years ago

Hi @jjtang1985 , @artemkovalyov

The main reason to get simple data structure was to create annotation (not only for documentation purpose but the schema is used to generate the actual UI data field of same properties & type in the application as shown below, thus making it easier to create object(entity data) using that field & pass it to the backed execution (example : for creating a new BusinessPartner entity ) ):

dataField

Following datatype annotation (supposed to be created dynamically reading data properties) is used to get schema & to have the required data fields in UI (as image attached above):

`/**

Currently trying to read the typescript files & create annotation & json schema from it but due to dependencies & reference properties getting issues in making it work in this use case.

You did mentioned about VDM documentation with properties & its datatype but we are actually trying to provide the placeholder datastructure in application itself .

Thanks

artemkovalyov commented 3 years ago

Hi @h2plucifer,

I skimmed through the issue and seems like you simply want to have all the available Entity fields with available data types to build your data schema programmatically.

In what format do you plan to have your schema for the frontend? We can discuss the format and see if your generator can be used to provide it as a by-product.

Please, provide an example how your code and schema will look like.

@jjtang1985, let's discuss it between us tomorrow.

jjtang1985 commented 3 years ago

Hi @h2plucifer,

I created a backlog item, and will discuss with the team this week. It would be help accelerate the refinement, if you can provide your timeline about it. Are you working on a life system or maybe a PoC project?

By the way, the current scope of this ticket is about the json output:

{
ACADEMIC_TITLE : string,
............
}

where the "maximal length limit" is not covered.

h2plucifer commented 3 years ago

Hi @jjtang1985 , @artemkovalyov ,

Currently this has been under evaluation for possibility of its integration with the product & its usability for performing all the OData operations of different VDM services . And since it already provide all the service properties through VDM we are checking the possible way of exposing those to the end user in UI itself (as shown in shared image with some sample properties).

image

Please let me update you with some more input regarding the handling of this use case , currently having discussion within the team .

Thanks

marikaner commented 3 years ago

Hey @h2plucifer,

I am not exactly sure, what your requirements are, but maybe as a hint take a look at this:

const BusinessPartner =
  require('@sap/cloud-sdk-vdm-business-partner-service').BusinessPartner;

const fields = BusinessPartner._allFields.reduce(
  (json, field) => ({
    ...json,
    [field._fieldName]: field.edmType ?? field._linkedEntity?._entityName
  }),
  {}
);

This would result in something like this:

{
  "BusinessPartner": "Edm.String",
  "FirstName": "Edm.String",
  "IsFemale": "Edm.Boolean",
  "IsMale": "Edm.Boolean",
 ...
  "to_BusinessPartnerAddress": "A_BusinessPartnerAddress",
  "to_Customer": "A_Customer",
  "to_Supplier": "A_Supplier"
}

This isn't exactly what you asked for, but it might already provide all the information you need at runtime and maybe it is a good start. You would have to ensure that navigation properties, complex types and collection types are handled accordingly.

If you want to adjust the names to have the uppercase snake case format, you could use this. If you want to have actual JavaScript type information, you would probably need some kind of mapping between the EDM types and the JS type (e. g. "Edm.String" -> string).

Let me know if this goes in the right direction or if you're looking for something substantially different.

h2plucifer commented 3 years ago

Hi @marikaner ,

Thanks for this suggestion.

I tried similar approach & using this pattern currently I am able to utilize all the properties & able to create required annotations as well that's needed in our use case .

Hi @jjtang1985 , @artemkovalyov , Current approach works well with our use case , so will update you if any further information needed on this.

Thank you

artemkovalyov commented 3 years ago

Hey @h2plucifer,

I'm happy the solution worked for you! I think your use case is interesting.

Can you share a bit more information about you project?

I'd also appreciate if you share the way you generate your schemas. I think it might be valuable for other SDK users and we can share it in documentation or even productize if you don't mind.

Thanks 🙏

h2plucifer commented 3 years ago

Hi @artemkovalyov ,

Sorry for the delayed response.

Its actually a functionality of company's product itself & VDM functionalities are being evaluated to provide OData operations as added functionalities .

Regards

artemkovalyov commented 3 years ago

Thanks for the valuable details @h2plucifer. I'll be closing this for now. We're happy to continue the discussion based on the results of your PoC. Looking forward to hearing from you hear of via internal channels.

h2plucifer commented 3 years ago

Hi,

Regrading the previous discussion & POC, I tried following approach but still having some challenges (converting properties into format accepted in VDM create() method ), please provide some inputs:

Using following logic (suggested by @marikaner ) to get the list of properties & converting its type to required js datatypes:

//Getting all the fields


<BusinessPartner>._allFields.reduce(
            (json, field) => ({
                ...json,
                [field._fieldName]: field.edmType ?? field._linkedEntity?._entityName
            }),
            {}
        );
        ... .....

// Converting to required datatype

             switch(property){
             case "Edm.String":  <service>[property] = "string"; break;
            case "Edm.Boolean": <service>[property] = "boolean"; break;
            default: <service>[property] = fieldMapping(<service>[property]); break;   // ex. converting  A_AddressEmailAddress ==> AddressEmailAddress  
            }
        }

// Following files for individual service are generated with the required properties (Jsdoc representations)

image

// Each generated datatype files contains following kind of annotations for properties:

image

Due to above mentioned challenges facing issues in using all the properties of service for creating datatype in generic way

Following is the snippet how it has been designed to handle Odata operations (ex create()) image

EntityData in above workflow (for create() operation ) will be provided from this input parameter image

Getting the property list using vdm npm packages in the similar way as available in documentation portal could help resolving most of the challenges: image

Please let me know if you could provide any suggestions regarding this , I can try & check if it helps in our current use case.

Regards