Code Monkey home page Code Monkey logo

odata-library's Introduction

OData library

REUSE status

A NodeJS library to access OData services provided by the Netweaver server.

Prerequisites

NodeJS is installed. Minimum version of NodeJS is 18.

Installation

$ npm  install @sap_oss/odata-library

Getting Started

const Service = require("@sap_oss/odata-library").Service;

let service = new Service(
  "https://username:password@localhost/path/to/service/"
);

service.init
  .then(() => {
    return service.Entity_Set_Name.get(1);
  })
  .then((result) => {
    console.log(result);
  });

Upgrade to version 1.x from 0.x

"ca" parameter is not supported (due to use fetch instead of superagent). Use environment variable NODE_EXTRA_CA_CERTS to define custom certificate authority.

export NODE_EXTRA_CA_CERTS=[your CA certificate file path]

Documentations

Contact Us

Jakub Vaclavik <[email protected]>
Michal Nezerka <[email protected]>
Norbert Volf <[email protected]>

License

Copyright (c) 2020-2021 SAP SE or an SAP affiliate company and odata-library contributors. Please see our LICENSE for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available via the REUSE tool.

odata-library's People

Contributors

ajinkyapatil8190 avatar dependabot[bot] avatar difsrip avatar jakub-vaclavik-sap avatar kozubikmichal avatar michalkopulety avatar mnezerka avatar norbertvolf avatar phanak-sap avatar scharf avatar sebastianwolf-sap avatar sreelalmec avatar szalayak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

odata-library's Issues

Simultaneous requests share the same state

Hello everyone,

when I was trying to use the library in Node.js 14.16.1, I have found out that somewhere deep in the library, the shared object is used. This doesn't allow me to send simultaneous requests properly. It seems that the state is shared by subsequent requests, and when the async request is processed by node, my web service always gets the same payload. Here is an example:

const Service = require("@sap_oss/odata-library").Service;
const SERVICE_URL = "https://services.odata.org/V4/OData/OData.svc/";

(async () => {
    const sample = new Service(SERVICE_URL);
    await sample.init;

    console.log(`${SERVICE_URL} initialized successfully`);

    const results = await Promise.all([
        sample.Products.select(["ID", "Name"]).get(0),
        sample.Products.select(["ID", "Name"]).get(1)
    ]);

    console.log(`Results ¯\\_(ツ)_/¯ ${JSON.stringify(results)}`);
})();

Here is my result:

Results ¯\_(ツ)_/¯ [[{"ID":0,"Name":"Bread"}],[{"ID":0,"Name":"Bread"}]]

Honestly, I have expected two different Products.

When I debugged your code, I have found out that the issue is caused by the library design. Somewhere in QueryableResource.js, the object defaultRequest is shared.

I can use await, it will make my code sequential, this is not what I want. Or, I can initialize a service asynchronously per each task/request, but this is also clumsy, because every init call reads $metadata.

None of the provided examples demonstrate my case, that is why I had to improvise. I hope this bug report will be helpful for other users, if they have similar issues.

p.s. it was difficult to find, why my code didn't work.

Invalid response on count() from Northwind

The count() method doesn't return valid response (the number). The speculation is - it doesn't properly handle returned content type (text/plain) and tries to parse it as json.

Use following code to reproduce the issue:

const Service = require("@sap_oss/odata-library").Service;

const logger = {
    "trace": console.log,
     "debug": console.log,
     "info": console.log,
     "warn": console.warn,
     "error": console.error
};

let service = new Service({
    url: "https://services.odata.org/V2/OData/OData.svc/",
    strict: false, // ignore non critical errors, e.g. orphaned annotations
    logger: logger
});

service.init.then(()=> {
    return service.Products.count();
}).then((result) => {
    console.log(`EntitySet contains ${result} entities.`);
}).catch(err =>  console.error(err.message))

Exception is thrown, but expected is value 9 (try to copy the request url to your browser):

Request:
  GET https://services.odata.org//V2/OData/OData.svc/Products/$count
  Request Payload: Empty
Request headers : {
  "User-Agent": "node-superagent/3.8.3"
}
Response Status Code : 200
Response Headers : {
  "cache-control": "no-cache",
  "content-length": "120",
  "content-type": "text/plain;charset=utf-8",
  "content-encoding": "gzip",
  "vary": "Accept-Encoding",
  "server": "Microsoft-IIS/10.0",
  "dataserviceversion": "2.0;",
  "x-aspnet-version": "4.0.30319",
  "x-powered-by": "ASP.NET",
  "date": "Fri, 05 Mar 2021 16:42:43 GMT",
  "connection": "close"
}
Cookies : ""
Response : {}
Backend returns invalid count value.

Support OAuth / Custom Headers

I have an OData service that is made available via SAP CPI and uses OAuth (Bearer token). Not sure how to access this API because it seems like you cannot pass custom headers to the Service constructors. Enabling OAuth would just require passing the header param Authorization with a value of Bearer <your_token>.

SELECT statement on parametrized entity set

SELECT statement on parametrized entity set (sap extension) validates columns against ...Parameters entity type. This entity type contains only parameters and Results/Set navigation property that provides data for the parametrized entity set query. SELECT statement should be validated against the Results/Set entity type.

Service initialization with communication user fails

A user created with "Maintain Communication User" can access an odata service with basic authentication but cannot login through SAML.
This odata service tries SAML, and then basic authentication.

For a communication user SAML login fails. The login page is returned with the error message and this service keeps retrying SAML login indefinitely.

To make this service work with communication users, the code should switch to and try basic authentication, if login credentials don't work for SAML, i.e. after a few retries with SAML login.

Parse PropertyPath with NavigationProperty definition

SideEffects annotation can define property as PropertyPath. The PropertyPath can contains path to path to property which exists in the NavigationProperty where property of navigation property is divided by "/".

Parsing of metadata currently failed for the situation.

<Annotation Term="Common.SideEffects" Qualifier="ProfitCenterCocdAssignment">
  <Record>
    <PropertyValue Property="SourceProperties">
      <Collection>
        <PropertyPath>ControllingAreaForEdit</PropertyPath>
      </Collection>
    </PropertyValue>
    <PropertyValue Property="TargetProperties">
      <Collection>
        <PropertyPath>to_CompanyCodeAssignment/ControllingArea</PropertyPath>
        <PropertyPath>to_CompanyCodeAssignment/CompanyCode</PropertyPath>
        <PropertyPath>to_CompanyCodeAssignment/CompanyCodeName</PropertyPath>
        <PropertyPath>to_CompanyCodeAssignment/PrftCtrIsAssignedToCompCode</PropertyPath>
      </Collection>
    </PropertyValue>
    <PropertyValue Property="EffectTypes" EnumMember="ValueChange ValidationMessage"/>
  </Record>
</Annotation>

PATCH request support for ODATA

Hello Colleagues,

We are using Vyper for ODATA automation. For automating the script, in some payloads we use PATCH request. Could it be possible to support PATCH request.

Regards,
Dinesh

Correctly process the Unauthorized page on SAML request

If server does not support SAML authentication and returns on request to SAML authorization "Unauthorized" HTTP response. odata-library recognize it as fatal error, but authentication process can continue by basic authentication.

Requested by Dinesh Bhandarkar

Add getting raw value by $value suffix

When the given URL contains an additional suffix (e.g. https://.../Some_Entity/$value, in this case the "/$value" suffix), I can make the call "service.Some_Entity.post()", however, it is not possible to add the desired "$value" property to the call.

Invalid response from FunctionImport

FunctionImport GET call does not correctly parse response

service.GetCombinations({
Param : 1,
Param: 2
})

If FucntionImport is defined in metadata to call GET method. Does not correctly parse JSON data

Additional question mark

OData-library now generates post requests with a redundant question mark. The question mark is used even though no URL parameter is used.

URL looks like this:

/sap/opu/odata/sap/FAC_CURRENCY_EXCHANGE_RATE_SRV/C_CurrencyExchangeRate?

The path is generated in QueryableResource.js L 178

Batch/changeset request

Hello Colleagues,

Is it possible to trigger a batch (changeset) request using this library? My aim would be to create multiple entities in one request, but I don't find such information in the documentation.

Thanks,
Daniel

Failsafe 1:n navigation property target typing

1:n navigation property can declare target property type as collection type (typical v4) or as complex/entity type (typical v2). Currently odata lib assumes CollectionType and it leads to following error for v2 1:n navigation properties (since recent changes):
TypeError: Cannot read properties of undefined (reading 'hasStream')
at NavigationProperty.determineRequestHeaders (.../@sap_oss/odata-library/lib/engine/QueryableResource.js:595:55)
at NavigationProperty._handleAgentCall (.../@sap_oss/odata-library/lib/engine/QueryableResource.js:580:10)
at NavigationProperty.executeGet (.../@sap_oss/odata-library/lib/engine/QueryableResource.js:349:14)
at RequestDefinition.get (.../@sap_oss/odata-library/lib/engine/RequestDefinition.js:103:27)
at NavigationProperty.get (.../@sap_oss/odata-library/lib/engine/QueryableResource.js:115:32)

nested navigationProperty not resolved

Hi guys,

we currently facing an issue where we can't post against an entity when the payload contains a nested navigationProperty which points to an entity and not to an entitySet.

Due to authorization issue we need to have a seperate navigationProperty pointing to an entity.

Web Version of this library?

Hey colleagues,

we received a feature request in UI5 Web Components for React (SAP/ui5-webcomponents-react#2054) which is asking for an oData v2 Client.
As our library is only taking care of the rendering part, it would be a great fit to use the odata-library for making the odata calls.
If I have understood it correctly, this library is currently only supporting node environments. Are there any plans to release a "web" version that runs on the clients? Maybe this would go hand in hand with #25 if you go for the fetch library anyways.

Thanks!

Deep Create support for OData V4

Hello,

When I try to use POST with Deep Insert I encounter the below error.

entityTypeModelStart.navigationPropertyAssociationTo is not a function
at EntitySet.processNavigationPropertyItems (C:\Users<>\AppData\Roaming\npm\node_modules\qmate\node_modules@sap_oss\odata-library\lib\engine\QueryableResource.js:547:48)

Could you confirm if this is a supported feature currently?

Function Import error 'rawResponse.headers.get is not a function'

In some cases, calling function import v2 leads to following error while parsing response:

Uncaught Error Error: rawResponse.headers.get is not a function
    at <anonymous> (.../@sap_oss/odata-library/lib/engine/FunctionImport.js:145:18)

Here is sample code to reproduce:

const Service = require('@sap_oss/odata-library').Service;

function edmToDate(str){
  return new Date(parseInt(str.replace('/Date(', '')));
}

const service = new Service({
  url: "...",
  auth: {
    username: "...",
    password: "...",
  },
  parameters: {
    "sap-client": "710",
    "sap-language": "EN",
  },
  strict: false, // ignore non critical errors, e.g. orphaned annotations
});


service.init.then(async () => {
  const PCID = Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5).toUpperCase();
  let draft = await service.C_ProfitCenterTP.post();

  let draftKey = {
    ControllingArea: draft.ControllingArea,
    ProfitCenter: draft.ProfitCenter,
    ValidityEndDate: edmToDate(draft.ValidityEndDate),
    DraftUUID: draft.DraftUUID,
    IsActiveEntity: false
  }

  // set mandatory draft attributes
  await service.C_ProfitCenterTP
    .merge(draftKey,
      {
        ProfitCenterForEdit: `${PCID}PCNTR`,
        ProfitCenterName: `${PCID}Name`,
        ProfitCtrResponsiblePersonName: `${PCID}Person`,
        ProfitCenterStandardHierarchy: "YBH110",
        Segment: "1000_A"
      });

  //// Draft Preparation & Activation ////
  service.createBatch();

  // Draft Preparation
  service.createChangeSet();
  service.C_ProfitCenterTPPreparation(draftKey);
  service.commitChangeSet();

  // Draft Activation
  service.createChangeSet();
  service.C_ProfitCenterTPActivation(draftKey);
  service.commitChangeSet();

  let batchResp = await service.sendBatch();

  console.warn(batchResp);
});

Log also failed requests

Currently, OData-library logs only responses without error. When there is an error, the logger is not notified and it causes that network log is not very useful in case of error.

Agent.js L396

      this.headersToRequest(headers, requestMethod)
        .then((res) => {
          this.logResponse(res);
          resolve(res);
        })
        .catch((err) => {
          reject(Agent.formatResponseError(err));
        });

Success is logged, error only throws an error.

Missing support to create entity with complex type

Can't create new entity via POST

service.entitySet.post({
  prop1 : "value",
  prop2 : "value",
  complexProp : {
    prop3: "value",
    prop4 : "value"
  }
})

Where complexProp property is defined in metadata as ComplexType

Client certificate authentication

Hello Norbert,

As we discussed via email, could you please check, if you can implement client certificate authentication?

Thanks,
Daniel

Internal Server Error from FunctionImport Edit

Getting Error: Internal Server Error - In the context of Data Services an unknown internal server error occurred after trying to call function import to edit Entity Set in OData v2.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.