UNPKG

odata-client

Version:
270 lines (173 loc) 8.93 kB
# odata-client A client library for accessing odata resources using node. HTTP queries return a promise. ## Installation `npm install odata-client` ## Usage ``` const odata = require('odata-client'); var q = odata({service: 'https://example.com', resources: 'Customers'}); q.top(5).skip(10).filter('Balance gt 5000').and('CreditLimit', '<', 10000).get() .then(function(response) { ... }); ``` ## ** Note on the [request](https://npmjs.com/package/request) library ** As the [request](http://npmjs.com/package/request) library is now deprecated, this project has switched to using [got](https://npmjs.com/package/got). However, request is listed as a peer dependency and `odata-client` will use request in preference to got if it's found. ## odata object * `odata(config)` The `odata(config)` function produces a query object for the construction of queries. `config` is an object with the following options: 1. `service` - the base URL of the service 1. `resources` - the resource part of the URL for the query, e.g. `Customers` or `Customers('ACME01')/Orders`. You can also add resource parts using the `resource` method of the query function 1. `custom` - optional object containing addition query parameters, e.g. `{access_token:'123456'}` will append `?access_token=123456` to the query URL. 1. `version` - set `OData-Version` HTTP header 1. `maxVersion` - set `OData-MaxVersion` HTTP header 1. `format` - specify response format (e.g. `json`) * `expression(left, op, right)` Used to produce subexpressions in a filter. For example, `q.filter('CreditBalance', '>', odata.expression('OrderValue', '+', 100))` produces `$filter=CreditBalance gt (OrderValue add 100)`. The arguments are the same as for `q.filter`, see below. Expressions can be chained, eg ``` expression('Balance', '>', 500').and('CreditLimit', '=', 0) // (Balance gt 500) and (CreditLimit eq 0) expression('Balance', '+', 1000).lt('CreditLimit') // (Balance add 1000) lt (CreditLimit) ``` * `identifier(string)` * `literal(string)` * `exact(string)` In a filter expression part, the left argument is normally treated as an identifier (i.e., if it's a string it isn't surrounded by quotes) whereas the right argument is assumed to be a literal (strings are surrounded by quotes). These methods allow you to override this. e.g. ``` q.filter(odata.literal('Customer'), '=', odata.identifer('Type')) // $filter='Customer' eq Type ``` `exact` allows you to place the string in the query exactly as intended. * `type(type, value)` Allows prefixing the value with a type name, such as an enum. e.g. ``` q.filter('DurationValue', odata.type('duration', 'P10D')) // $filter=DurationValue eq duration'P10D' ``` * `fn(name, args)` A `fn` method produces a function for use in a filter or expression. `name` is the name of the function while `args` is an object with the objwct keys being the parameter names. e.g. ``` q.filter(odata.fn('SalesRegion', { City: odata.identifier('$it/City') }), '=', 'West'); // $filter=SalesRegion(City=$it/City) eq 'West' ``` ## query object The query object has the following methods: * `resource(resource, value)` Adds a new part to the resource section. e.g. ``` odata({service: 'https://example.com'}).resource('Customers').resource('Orders'); // https://example.com/Customers/Orders odata({service: 'https://example.com'}).resource('Customers', 'ACME01').resource('Orders'); // https://example.com/Customers('ACME01')/Orders odata({service: 'https://example.com'}).resource('Customers', {account:'ACME01'}).resource('Orders'); // https://example.com/Customers(account='ACME01')/Orders ``` * `fn(name, args)` Add a function component to the resource section. `name` is the name of the function whereas `args` is an object with the keys being the parameter names. e.g. ``` odata({service: 'https://example.com'}).fn('Customer', { Account: 'ACME01' }); // https://example.com/Customer(Account='ACME01') ``` * `top(n)` Adds a `$top=n` query parameter. * `skip(n)` Adds a `$skip=n` query parameter. * `filter(left, op, right)` Used for constructing `$filter` requests. There are several ways to call this method: 1. If called with a string as the sole argument, the string is used as a literal filter, e.g. `q.filter("Account eq 'ACME01'")` 1. If all three arguments are specified, `op` should be one of the usual odata operations such as `eq` or `add`, or the symbolic equivalents such as `=` or `+`. e.g. `q.filter('Account', '=', 'ACME01')`. The `left` and `right` arguments can be `odata.expression`s for building nested queries. 1. If called with two arguments, the operator is assumed to be `eq`, e.g. `q.filter('Account', 'ACME01')` 1. If called with an array of expressions as the first argument, `and` the expressions together. e.g. ``` q.filter([ Odata.expression('key1', 'abc'), Odata.expression('key2', 'def') ]) ``` or, as a shortcut, ``` q.filter([['key1', 'abc'], ['key2', 'def']]) ``` The `left` argument is assumed to be an identifier while `right` is assumed to be a literal, which affects the quoting of strings. You can override this behaviour with the `odata.literal` and `odata.identifier` functions, see above. If two or more filters are chained, they are `and`ed together. `q.filter('Balance gt 1000').filter('Status', 'stop')` profduces `$filter=(Balance gt 1000) and (Status eq 'stop')`. * `and(left, op, right)` Synonym for `filter`. * `or(left, op, right)` Adds an `or` clause to the filter being built. If called with an array of expressions, `or` the expressions together. For example ``` q.or([ Odata.expression('key1', 'abc'), Odata.expression('key2', 'def') ]) ``` or, as a shortcut, ``` q.or([['key1', 'abc'], ['key2', 'def']]) ``` You can also pass an array of objects: ``` q.or([{ key1: 'abc', key2: '123' }, { key1: 'def', key2: '456' }]) // (key1 eq 'abc' and key2 eq '123') or (key1 eq 'def' and key2 eq 456) ``` * `not(left, op, right)` Adds a `not` clause to the filter * `all(field, property, op, value)` Adds an `all` filter, e.g. ``` q.all('Orders', 'Value', '<', 50) // ?$filter=Orders/all(p0:p0/Value lt 50) ``` * `any(field, property, op, value)` Adds an `any` filter, e.g. ``` q.any('Orders', 'Lines/$count', '>=', 10) // ?$filter=Orders/any(p0:p0/Lines/$count ge 10) ``` * `select(items)` Adds a `$select` clause to the filter, e.g. `q.select('Account', 'Status')` produces `$select=Account,Status`. * `expand(item)` Adds an item to `$expand` * `search(term)` Sets the term for `$search`. * `count(param)` Adds a `$count` clause to the query. If `param` is true, adds the count clause as a query parameter instead of a pth component (#14) * `orderby(item, dir)` Adds an `$orderby` clause to the query. There are several ways to call this function: 1. `q.orderby('Account')` produces `$orderby=Account` 1. `q.orderby('Account', 'desc')` produces `$orderby=Account desc` 1. `q.orderby(['Status', 'desc'], ['Account'])` produces `$orderby=Status desc,Account` * `custom(name, value)` Adds custom query prameters to the query using either a pair of parameters or an object, e.q. ``` q.custom('access_token', '123456') // ?access_token=123456 q.custom({access_token: '123456', version: '1.2'}) // ?access_token=123456&version=1.2 ``` * `query` Produces the query string, e.g. ``` odata({service: 'https://example.com/Customers'}).top(5).query() // 'https://example.com/Customers?$top=5' ``` * `get(options)` * `post(body, options)` * `put(body, options)` * `patch(body, options)` * `merge(body, options)` * `delete(options)` Perform an HTTP operation. For non-batched queries, these will return a promise which resolves to an HTTP response. The `options` argument is passed to the underlying [got](https://npmjs.com/package/got) (or [request](https://www.npmjs.com/package/request)) library. For batched queries, requests are accumulated into a single document which is sent with the `send` function. As a convenience when using batch functions, the `content_id` property of `options` is copied to the `Content-ID` header, e.g. ``` q.batch()...get({content_id: 1}) ``` * `batch` Sets up [batch processing](http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part1-protocol/odata-v4.0-errata03-os-part1-protocol-complete.html#_Toc453752313). When batch processing is enabled and an HTTP request function is called, instead of being sent immediately the request is held in a queue. When the `send` function is called, all the requests are sent in one document. The code ``` q.resource('Customers', 'ACME01').batch(); q.resource('Orders', 1).get(); q.resource('Orders', 2).get(); q.send(); ``` will batch the queries `/Customers('ACME01')/Orders(1)` and `/Customers('ACME01')/Orders(2)` into one and send them as one document. * `send` Will send a batched query, returning a promise that resolves to an HTTP response.