GithubHelp home page GithubHelp logo

janhommes / o.js Goto Github PK

View Code? Open in Web Editor NEW
233.0 12.0 56.0 1.16 MB

o.js - client side oData lib.

Home Page: https://janhommes.github.io/o.js/example/

License: MIT License

CSS 1.79% JavaScript 60.40% HTML 4.56% TypeScript 33.25%
odata javascript

o.js's People

Contributors

bprucha avatar ciprian-dragomir avatar dependabot[bot] avatar heinzchr avatar iceonfire avatar janhommes avatar many20 avatar melgish avatar offbeatful avatar phmasek avatar steinerj avatar winfried-van-loon avatar xel1045 avatar zhevron 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

o.js's Issues

Add string.format() to routes like filter

Example:

//get a product list on product click
o("ProductGroup/Group").filter("Group/Parent_fk eq {0} {1} {0} {2}").route("Group?",function(data) {
            console.log(data);
            self.route("Group");
            self.groups(data);
});

If the route is Group/1/Test/x the query should return a filter like this: $filter=Group/Parent_fk eq 1 Test 1 x.

How to run example app

I'm not sure if the example app has a bug or if I'm not running it correctly. What are the instructions for getting the example up and running?
I tried running 'node app.js' in the node js console window and I get

ko.applyBindings(new ViewModel());
^
ReferenceError: ko is not defined
at Object. (E:\Playground\OData\o.js-master\example\app.js:78:1)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module._load (module.js:497:3)
at Function.Module.runMain (module.js:693:10)
at startup (bootstrap_node.js:188:16)
at bootstrap_node.js:609:3

I tried just opening up the index.html app in my browser and when it runs the query to the service I get an error:

oException
message : "Request to http://services.odata.org/V4/%28S%28wptr35qf3bz4kb5oatn432ul%29%29/TripPinServiceRW/People?$format=json&$top=3 failed with HTTP status 404."
name : "o.js exception"

I used the Chrome debugging tool to trace the operation and it's happening at o.js:1413 and the ajaxRequest.status is 0. If I copy the uri and paste it into chrome as-is then I get the data I'm looking for without issues.

Perhaps I didn't set it up right. I downloaded the zip file and extracted it into a local playtime folder... E:\Playground\OData\o.js-master\example and I'm trying to run it from there. Am I running the example incorrectly? Is it supposed to be running through a server environment via localhost such as node? How should that be invoked?

TIA - mike

$select parameter

how do I add a $select clause to the query? I don't see any part of the API that supports that.

Batch multi-part response parsing (regex) issue

Hello again,

Maybe i'm misunderstanding something but the regex used in the startAjaxReq function to parse $batch results didn't work for me. It was:

var regex = /({[\s\S]*?--batchresponse_)/g;
...
parseResponse(result[0].substring(0, result[0].length - 16), tempBase);

which I replaced with:

var regex = /({[\s\S]*?})/g;
...
parseResponse(result[0], tempBase);

The original regex and substring handling looks very intentional but clearly wasn't working for me. Am I missing something?

Thanks,

Chris

.count does not prepend with /

I tried using this library but when doing the following:

o().config(myConfig);
o('appointments').count().get();

I get a 404 because the url is /products$count instead of /products/$count.

And the following works:

o().config(myConfig);
o('appointments/').count().get();

I am new with OData so I am not sure I am using the library well.

If this is not a bug, can you correct me with how to use the .count() method?

Q dependence is missing in bower.json

I have a project set up using Bower: "o.js": "0.2.2"
While executing examples i get an error because defer dependency is not defined:


o('http://services.odata.org/V4/OData/OData.svc/Products').find(':0').route('Product/Detail/:0/:1',function(data) {
  console.log('Route Product/Detail/'+this.param[0]+'/'+this.param[1]+' triggered. Result:');
  console.log(data);
});
t {data: Array[0], inlinecount: null, param: Object, oConfig: Object}any: (e,n)arguments: nullcaller: nulllength: 2name: ""prototype: Object__proto__: ()<function scope>batch: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>beforeRouting: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>count: ()data: Array[0]length: 0__proto__: Array[0]delete: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>deleteRef: (e,n)arguments: nullcaller: nulllength: 2name: ""prototype: Object__proto__: ()<function scope>exclude: (e,n)arguments: nullcaller: nulllength: 2name: ""prototype: Object__proto__: ()<function scope>expand: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>filter: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>filterByList: (e,n)find: (e)first: ()get: (e,n)include: (e,n)inlineCount: (e)inlinecount: nullisEndpoint: ()link: (e,n)loading: (e,n)oConfig: Objectappending: ""endpoint: nullerror: nullformat: "json"headers: Array[0]isAsync: trueisCors: trueisHashRoute: trueopenAjaxRequests: 0password: nullready: nullstart: nullstrictMode: trueusername: nullversion: 4__proto__: ObjectorderBy: (e,n)arguments: nullcaller: nulllength: 2name: ""prototype: Object__proto__: ()<function scope>orderByDesc: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>param: Object__proto__: Objectpatch: (e,n)arguments: nullcaller: nulllength: 2name: ""prototype: Object__proto__: ()<function scope>post: (e,n)progress: (e)put: (e,n)query: (e)arguments: nullcaller: nulllength: 1name: ""prototype: Object__proto__: ()<function scope>ref: (e,n)remove: (e)removeRef: (e,n)route: (e,n)routes: (e,n)save: (e,n)search: (e,n,t,r)select: (e)skip: (e)take: (e)top: (e)triggerRoute: (e)where: (e)__proto__: Object
var oHandler = o('http://services.odata.org/V4/OData/OData.svc/Products');
undefined
oHandler.find(1);
t {data: Array[0], inlinecount: null, param: Object, oConfig: Object}any: (e,n)batch: (e)beforeRouting: (e)count: ()data: Array[0]delete: (e)deleteRef: (e,n)exclude: (e,n)expand: (e)filter: (e)filterByList: (e,n)find: (e)first: ()get: (e,n)include: (e,n)inlineCount: (e)inlinecount: nullisEndpoint: ()link: (e,n)loading: (e,n)oConfig: ObjectorderBy: (e,n)orderByDesc: (e)param: Objectpatch: (e,n)post: (e,n)progress: (e)put: (e,n)query: (e)ref: (e,n)remove: (e)removeRef: (e,n)route: (e,n)routes: (e,n)save: (e,n)search: (e,n,t,r)select: (e)skip: (e)take: (e)top: (e)triggerRoute: (e)where: (e)__proto__: Object
oHandler.get(function(data) {
  console.log(data);
  //or the saved var also contains the data:
  console.log(oHandler.data);
});
o.min.js:1 Uncaught TypeError: Cannot read property 'defer' of null(…)G.get @ o.min.js:1(anonymous function) @ VM5133:1

NPM package

Stumbled upon this library - and it looks awesome.

If you create a release (see #11 ) - would it be possible to submit this to npm?
I can wrap it in a package myself, but it'd be awesome if you'd add the required bits (a suitable package.json, mostly?) for npm to be happy. Would you accept a PR for that?

Adding a timeout

Hello,
I would like to add a timeout of 2 seconds to all my requests (using NodeJS). I tried modifying the o.js file at line 1450 like this:

var Xhr2 = require('xhr2');
xhr = new Xhr2();
xhr.timeout = 2000;

to no avail. Is there some way I can remedy this issue?
Thank you.

Not working on NativeScript

throws n.on is not a function error.

i dont know if this plugin is wired only to work on browsers or if it has such dependencies . or should i use Nodify

Extracting raw url

Is there a way that I can just get the generated URL and handle the actual HTTP request manually?

opertionMapping is dangerous

Operation mapping is a nice feature, but can be dangerous in some contexts: I had to disable it when dealing with dates, since they contain dashes ('-'). This results in a date like '2016-03-01' being processed as '2016sub03sub01'.

Maybe we need a smarter jsToOdata function, or remove operation mapping support completely for arithmetic operations.

Antony

Refused to set unsafe header "Accept-Charset" and CORS is false

When I tried to set this header for my OData request, using:

o().config({headers:[{name:'Accept-Charset',value:'application/json'}]});
o(MYURL).get();

Here is the error back in my response ( and note I turned off CORS):

Refused to set unsafe header "Accept-Charset" <--- how to get past this error?

oData {
data:
[ { name: 'Photos', kind: 'EntitySet', url: 'Photos' },
{ name: 'People', kind: 'EntitySet', url: 'People' },
{ name: 'Airlines', kind: 'EntitySet', url: 'Airlines' },
{ name: 'Airports', kind: 'EntitySet', url: 'Airports' },
{ name: 'Me', kind: 'Singleton', url: 'Me' },
{ name: 'GetNearestAirport',
kind: 'FunctionImport',
url: 'GetNearestAirport' } ],
inlinecount: null,
param: {},
oConfig:
{ endpoint: 'http:///mgmt/odata',
format: 'json',
autoFormat: true,
version: 4,
strictMode: true,
start: null,
ready: null,
error: null,
headers: [ [Object] ],
username: null,
password: null,
isAsync: true,
isCors: false, <--- set to false
openAjaxRequests: 0,
isHashRoute: true,
appending: '' },
raw:
{ '@odata.context': 'http://services.odata.org/V4/TripPinService/$metadata'
...etc...

Any idea how to get o.js to set/use my headers I specified in my request?

typescript definitions for es2015 modules

I'm running with the @types/odata typings from npm, but as far as I can tell they've been set up in a way that doesn't support imports for es2015 modules, without an export of the interfaces in a way that I can reference in my code.

How to auth NTLM

Hey,

I have an OData Endopoint that I need to auth against w/ NTLM. Dont seem to work.
Any ideas?
Tx,Gabor

Need to update "npm install odata" with fix from this repo

Hi,

You made a fix for $count, to make it "/$count."

So, you may need to do this fix for $ref too, since it needs to be: /$ref at the end of URL, per OData v4 specs.

And yes, still need to get your fixes into "npm install odata," since your last fix is only in this Git Repo.

And can you update your this README page of the supported query commands vs what is listed inside the top of the o.js lib file?

ie8 xhr patch method not support

Hi @janhommes

We use o.js in our intranet, all the pc are xp with ie8. And we found a problem, ie8 XMLHttpRequest not support patch method. Maybe, it should check the browser, if it is ie8, xhr should be activexhttprequest instead of xmlhttprequest.

Thanks

function createCORSRequest(method, url) {
1446 var xhr = null;
1447

1448 //if no window assume node.js
1449 if (typeof window === 'undefined') {
1450 var Xhr2 = require('xhr2');
1451 xhr = new Xhr2();
1452 }
1453 else {
1454 xhr = new XMLHttpRequest();
1455 }

o().conf({version: 2}) not working?

Hi,

So I have OData service that supports version "4.0" string exactly, and if I use OData-Version header directly in o.js config or using curl, it works as I would expect.

But if I set this o() config to the above and use any value, like 2, or 5, etc... my OData service seems to ignore that value and continues to return all my data. I expected my service to reject me with an error, like "version 2 not supported."

Is this version field working correctly?

Library builds bad urls for olingo v4

Hello,

I'm using this library to request data from a java server with olingo v4

o().config({
  endpoint: '/api'
})

o('ShopWebsites').get(function (data) {
  console.log(`Data is {data}`)
})

I get this

o.js:1384 GET http://localhost:3000/api/ShopWebsites/?$format=json 400 (Bad Request)

The request is bad because it adds the last slash after ShopWebsites . If I make the request like: /api/ShopWebsites?$format=json it works.

How to use .batch()?

I need to make multiple PATCH requests for different entities in single $batch, how to do that?

Option to remove $format parameter

Is there a way to omit the $format=json part from the generated query string? I would love to use this library for my extension libraries for MS Dynamics CRM but all the requests fail with the following resonse:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code></code>
  <message xml:lang="de-DE">The query parameter '$format' begins with a system-reserved '$' character but is not recognized.</message>
</error>

OData V4 Url convention (section 5.1) doesn't imply that this query option in mandatory anyways (just like any other queryoption, really) so maybe this should just be present when the format-option is beeing set?

About Set Custom header in instance when get

I need set custom header in my project when executing some special request. eg:

Accept : "application/vnd.ms-excel"

but I only found the global setting method .

o().config({ headers:[{
name: "Accept",
value: "application/vnd.ms-excel"
}]});

Can you provide an interface to do this , like changing "get()" method to add an extra prarameter named "headers" ?

Need support for $skiptoken and $id system query options

For $skiptoken, OData 4.0 spec states:

11.2.5.7 Server-Driven Paging
Responses that include only a partial set of the items identified by the request URL MUST contain a link
that allows retrieving the next partial set of items. This link is called a next link; its representation is
format-specific. The final partial set of items MUST NOT contain a next link.
The client can request a maximum page size through the odata.maxpagesize preference. The service
may apply this requested page size or implement a page size different than, or in the absence of, this
preference.
OData clients MUST treat the URL of the next link as opaque, and MUST NOT append system query
options to the URL of a next link. Services may not allow a change of format on requests for subsequent
pages using the next link. Clients therefore SHOULD request the same format on subsequent page
requests using a compatible Accept header. OData services may use the reserved system query option
$skiptoken when building next links. Its content is opaque, service-specific, and must only follow the
rules for URL query parts.
OData clients MUST NOT use the system query option $skiptoken when constructing requests.

And for $id in GET request, it states:

11.2.8 Resolving an Entity-Id
To resolve an entity-id, e.g. obtained in an entity reference, into a representation of the identified entity,
the client issues a GET request to the $entity resource which located at the URL $entity relative to
the service root. The entity-id MUST be specified using the system query option $id.
Example 62: return the entity representation for a given entity-id
http://host/service/$entity?$id=http://host/service/Products(0)
A type segment following the $entity resource casts the resource to the specified type. If the identified
entity is not of the specified type, or a type derived from the specified type, the service returns 404 Not
Found.
After applying a type-cast segment to cast to a specific type, the system query options $select and
$expand can be specified in GET requests to the $entity resource.
Example 63: return the entity representation for a given entity-id and specify properties to return
http://host/service/$entity/Model.Customer?
$id=http://host/service/Customers('ALFKI')
&$select=CompanyName,ContactName&$expand=Orders

I would like O.js to support these query options. I think there is $id support when DELETing... but not for GET.

@odata.nextLink support

Hi @janhommes,

I'm not sure of what I'm about to say here, but when I perform a request to an OData service without specifying any page size I get an additional field in the response that tells me what to do next:

http://services.odata.org/V4/Northwind/Northwind.svc/Orders

{
  ...
  "@odata.nextLink": "Orders?$skiptoken=10447"
}

Is there a way already to get this info inside the oHandler? How could we add it in case? Thanks in advance,

Antony

UMD

IMHO the best way to support globals, Node, and AMD is by conforming to the UMD API (https://github.com/umdjs/umd).

I tried wrapping your library in this IIFE

;(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(['q'], factory);
  } else if (typeof exports === 'object') {
    module.exports = factory(require('q'));
  } else {
    root.o = factory(root.Q);
  }
}(this, function(Q) {
  function o(res) {
  ...
  }

  return o;
}));

and it works like a charm. What do you think?

Antony

If-Match header on non-CORS requests

Hi Jan,

First of all thank you for this amazing library, I was just looking for a clean way to perform OData operations and yours is just what I needed: simple, elegant, intuitive.

However I had to adapt it to my needs,and would like to share some suggestions in the following issues.

First of all, the "If-Match" header: I had to remove it otherwise it triggers CORS on calls to http://services.odata.org/V4/Northwind/Northwind.svc/. Is it necessary for other purposes? I would make it totally optional.

Keep up the good work!

Antony

o.js returns just the "value" portion of the response payload? missing response headers too

In the example code , it talks about the response payload in result variable, like so:

console.log(result);

However, when I make a curl call directly, I get items outside of "value," as shown:
...

{
"@odata.context": "https://localhost//odata/$metadata#tm/something/",
"@odata.nextLink": "https://localhost/odata/tm/something/?$skip=50&$top=50",
"value": [
{
"@odata.etag": "1",
"@odata.id": "https://localhost/odata/tm/something('ABC1)",
"description_field1": true,
... etc...

Basically o.js returns me the "value" portion of the payload, but I need to get the items outside of that "value" portion as well (eg, the context and nextLink fields)... How can I get those back from o.js?

Also, how can I get the RESPONSE HEADERs back from o.js get() call too?

Changeset body missing newline

buildBatchBody method, changeset body string concatenation:

body += 'Content-Type: application/json\n';
//body += 'Content-Length:' + stringData.length + '\n\n';

should be:

body += 'Content-Type: application/json\n\n';
//body += 'Content-Length:' + stringData.length + '\n\n';

as long as second line is commented out. I believe the second newline is necessary for the changeset to be parsed properly (it was for me).

Cookies are not send even is CORS is enabled

When a CORS request is made, currently, no cookies are sent to the odata server, even if isCors is enabled.

There seems to be a missing line of code right before opening the XHR, the withCredential XHR field is not set, but it is mandatory to do CORS requests (at least into Chrome). I have made a simple pull request ( #53 ) to correct this but there are evidences in the code that the withCredential field has been taken into account (at least partially), so I don't know if I am not missing something by just setting it to true.

Support advanced queries

Currently I'm using ODataAngularResources which has support for some very advanced queries. Any thoughts about bringing this type of api/functionality over to o.js?

Also, their transformUrl function is very handy as well to add support for anything missing, such as aggregates. For exaxmple, I have the following which produces a group by count summary based on some filtered columns

odataQuery.transformUrl(url => url + `&$apply=groupby((${columns.join(',')}),aggregate(Id with countdistinct as Total))`);

Q.JS dependency

Hi
could you double check if q.js dependency was fixed in V-0.3.1? I am still seeing the 'defer' undefined error once I remove Q.js link from my markup.

I am also seeing unless I configure "content-type: application/json" in the header, SharePoint REST service returns xml payload instead of json, so the code bombs out at the first character of JSON.parse(response) . I am not sure if this is a particular issue with Microsoft SharePoint service.

The .js suffix in the module name is not... isomorphic

Hi Jan,

I'm trying to integrate o.js inside an isomorphic app, which in my case means loading the same library on Node with

var o = require('o.js')

and at the same time on the browser (through RequireJS) with

define(['o.js'], function(o) {})

Unluckily, since o.js has the '.js' extension in its name, RequireJS seems to resolve the dependency as http://localhost:3000/o.js. As you may know, RequireJS can be configured with aliases, so you can e.g. require 'jquery' instead of 'bower_components/jquery/dist/jquery.min', but this mechanism does not work when modules have the suffix '.js' in their name.

So in short the question is: is there a way to rename this package or add an alias on NPM so it can be easily loaded in every environment? I saw that there are already packages named o-js, o, o-, ojs, etc. so it may not be a simple task... What do you think?

Antony

isCors not included in Readme and in @types/o.js

Hi,

I just wanted to submit a small issue. The Readme file and typescript declaration files are not up to date with the latest released version. At least "isCors" option is not documented, which can be important for some projects (it was a prerequisite in my case). I am making 2 pull requests atm for each modification.

Unit tests rely on a third-party service to work

Currently, the unit tests rely on the "Trippin" example service. Which means that the unit tests actually rely on this API to work. I've seen multiple examples where the library produces the correct request, but the API fails with HTTP status code 500, causing the tests to fail anyway.

IMO, it would be better to simply test the request object before it goes out to any server. Since the project currently uses Jasmine for testing, one possibility is to use jasmine-ajax to intercept the requests and run tests on them.

This way, the URL, method, data, etc can be tested without actually relying on a real API to respond. This also allows tests to be run in a offline-only scenario when developing.

Thoughts? As long as the tests enforce the OData protocol spec, it should be a better approach and allow for corner case testing without the Trippin service implementing that endpoint.

patch usage

I use patch/put like the document mentioned:

o('http://services.odata.org/V4/OData/OData.svc/Products(1)').patch({Name:'NewName'}).save(function(data) {
    console.log("Product Name changed"); 
});

but a exception throw:
Bulk updates are not supported. You need to query a unique resource with find() to patch/put it.

so, how can I use it correct?

thx

o.js autoFormat setting to false not working

When I define this:

o().config({autoFormat: false}); <-- so I don't want o.js to attach ?$format=json at end of my URL

And make my OData GET call, it returns with a 406 HTTP error:

o.js exception: Request to https://MY_URL/mgmt/odata/tm/ltm/pool failed with HTTP status 406.

Yet when I make a curl call to my URL (as shown above), it works fine to return my resources, such as:

curl -s -k -u user:password -H 'Content-Type: application/json' -X GET https://MY_URL/mgmt/odata/tm/ltm/pool

Can someone confirm setting that field to false works or fails. If I set it to true, then it does attach the "$format" at the end of my URL and my o.js call works.

How do I build a query to get related entities?

So I don't want to use $expand. I want to run a query that returns only the related entity or related entities of something. I think this is part of the OData 4 spec...

So I want to run something like this -
http://services.odata.org/V4/OData/OData.svc/Products(4)/People

Where People would be all the people who bought Product with the ID 4.

Is this possible with the o.js api?

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.