{"_id":"@aimtune/jinqu-odata","_rev":"1-61b25db4d4486a6cefd9d679aecac197","name":"@aimtune/jinqu-odata","dist-tags":{"latest":"1.1.4"},"versions":{"1.1.3":{"name":"@aimtune/jinqu-odata","version":"1.1.3","description":"Jinqu OData implementation","main":"dist/index.js","types":"dist/index.d.ts","keywords":["linq","jinqu","odata","query","ajax","typescript"],"repository":{"type":"git","url":"git+https://github.com/jin-qu/jinqu-odata.git"},"scripts":{"test":"mocha --reporter spec","cover":"nyc --reporter text-summary mocha --reporter spec","coveralls":"nyc mocha && nyc report --reporter=text-lcov | coveralls","karma":"karma start karma.conf.js","build":"rimraf dist | tsc","prepare":"npm run build"},"author":{"name":"Umut Özel"},"license":"MIT","devDependencies":{"@types/chai":"^4.2.12","@types/chai-as-promised":"^7.1.3","@types/fetch-mock":"^7.3.2","@types/mocha":"^8.0.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","coveralls":"^3.1.0","fetch-mock":"^9.10.6","jinqu-array-extensions":"^1.1.1","karma":"^6.3.14","karma-chai":"^0.1.0","karma-chai-as-promised":"^0.1.2","karma-chrome-launcher":"^3.1.0","karma-cli":"^2.0.0","karma-firefox-launcher":"^1.3.0","karma-ie-launcher":"^1.0.0","karma-mocha":"^2.0.1","karma-typescript":"^5.0.3","mocha":"^10.2.0","mocha-junit-reporter":"^2.0.0","node-fetch":"^2.6.0","nyc":"^15.1.0","rimraf":"^3.0.2","ts-node":"^8.10.2","tslint":"^6.1.3","typescript":"^3.9.7","whatwg-fetch":"^3.4.0"},"dependencies":{"jinqu":"^1.1.3","jinqu-fetch":"^1.1.1","jokenizer":"^0.4.5"},"gitHead":"d38e75ca135d525c6ede7d8b13c8398c4c10aab7","bugs":{"url":"https://github.com/jin-qu/jinqu-odata/issues"},"homepage":"https://github.com/jin-qu/jinqu-odata#readme","_id":"@aimtune/jinqu-odata@1.1.3","_nodeVersion":"18.15.0","_npmVersion":"9.5.0","dist":{"integrity":"sha512-LuF8yd2fF8/kdQr0BLnk0JLHP5Nes87nsVPlIl9E5aXty8M8Fik/6LG3lmZvUPC98NT8DrWwJ+R7eYYbz8Lmgg==","shasum":"4df3b702f50963c9b42afbdd7f768178e470be39","tarball":"https://registry.npmjs.org/@aimtune/jinqu-odata/-/jinqu-odata-1.1.3.tgz","fileCount":22,"unpackedSize":81526,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHjgXNed/TsBIJBUWtPKg/a/hcaqodtq4BScOUOlbsiPAiEAmlpdvMp12tO94mIqoFWP6sJ8YwvTLFTYlSSqlru0e2Q="}]},"_npmUser":{"name":"aimtune","email":"hamzaagareng@gmail.com"},"directories":{},"maintainers":[{"name":"aimtune","email":"hamzaagareng@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/jinqu-odata_1.1.3_1710863906493_0.337168123938834"},"_hasShrinkwrap":false},"1.1.4":{"name":"@aimtune/jinqu-odata","version":"1.1.4","description":"Jinqu OData implementation","main":"dist/index.js","types":"dist/index.d.ts","keywords":["linq","jinqu","odata","query","ajax","typescript"],"repository":{"type":"git","url":"git+https://github.com/jin-qu/jinqu-odata.git"},"scripts":{"test":"mocha --reporter spec","cover":"nyc --reporter text-summary mocha --reporter spec","coveralls":"nyc mocha && nyc report --reporter=text-lcov | coveralls","karma":"karma start karma.conf.js","build":"rimraf dist | tsc","prepare":"npm run build"},"author":{"name":"Umut Özel"},"license":"MIT","devDependencies":{"@types/chai":"^4.2.12","@types/chai-as-promised":"^7.1.3","@types/fetch-mock":"^7.3.2","@types/mocha":"^8.0.1","chai":"^4.2.0","chai-as-promised":"^7.1.1","coveralls":"^3.1.0","fetch-mock":"^9.10.6","jinqu-array-extensions":"^1.1.1","karma":"^6.3.14","karma-chai":"^0.1.0","karma-chai-as-promised":"^0.1.2","karma-chrome-launcher":"^3.1.0","karma-cli":"^2.0.0","karma-firefox-launcher":"^1.3.0","karma-ie-launcher":"^1.0.0","karma-mocha":"^2.0.1","karma-typescript":"^5.0.3","mocha":"^10.2.0","mocha-junit-reporter":"^2.0.0","node-fetch":"^2.6.0","nyc":"^15.1.0","rimraf":"^3.0.2","ts-node":"^8.10.2","tslint":"^6.1.3","typescript":"^3.9.7","whatwg-fetch":"^3.4.0"},"dependencies":{"jinqu":"^1.1.3","jinqu-fetch":"^1.1.1","jokenizer":"^0.4.5"},"_id":"@aimtune/jinqu-odata@1.1.4","gitHead":"c6eeef69baa4f906aa9162d6346d46918a1c8410","bugs":{"url":"https://github.com/jin-qu/jinqu-odata/issues"},"homepage":"https://github.com/jin-qu/jinqu-odata#readme","_nodeVersion":"18.19.1","_npmVersion":"10.2.4","dist":{"integrity":"sha512-IF+HlioPttIuJX3SU7e5f8AKiNEPSpi5sxFk/h67jw+3IgYqnzu08U9cupU7AMO3LTvHRxJbM4WCoPYRaR5dDw==","shasum":"cee553c50bee22af682b8d9e142ff709cdf5b7d1","tarball":"https://registry.npmjs.org/@aimtune/jinqu-odata/-/jinqu-odata-1.1.4.tgz","fileCount":27,"unpackedSize":114336,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFU0exUxUSD9K+Kc3K/MOXHB2//UZ6yZ0pz+lOigTvk0AiEAltKSWwo3ghxyjxUU1pjWwWYQzeRLIffwJojJ0Kd66s8="}]},"_npmUser":{"name":"aimtune","email":"hamzaagareng@gmail.com"},"directories":{},"maintainers":[{"name":"aimtune","email":"hamzaagareng@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/jinqu-odata_1.1.4_1710865217784_0.28099031294736876"},"_hasShrinkwrap":false}},"time":{"created":"2024-03-19T15:58:26.355Z","1.1.3":"2024-03-19T15:58:26.709Z","modified":"2024-03-19T16:20:18.356Z","1.1.4":"2024-03-19T16:20:17.946Z"},"maintainers":[{"name":"aimtune","email":"hamzaagareng@gmail.com"}],"description":"Jinqu OData implementation","homepage":"https://github.com/jin-qu/jinqu-odata#readme","keywords":["linq","jinqu","odata","query","ajax","typescript"],"repository":{"type":"git","url":"git+https://github.com/jin-qu/jinqu-odata.git"},"author":{"name":"Umut Özel"},"bugs":{"url":"https://github.com/jin-qu/jinqu-odata/issues"},"license":"MIT","readme":"# jinqu-odata - Javascript-Linq to Odata\n\n[![Build Status](https://travis-ci.org/jin-qu/jinqu-odata.svg?branch=master)](https://travis-ci.org/jin-qu/jinqu-odata)\n[![Coverage Status](https://coveralls.io/repos/github/jin-qu/jinqu-odata/badge.svg?branch=master)](https://coveralls.io/github/jin-qu/jinqu-odata?branch=master)\n[![npm version](https://badge.fury.io/js/jinqu-odata.svg)](https://badge.fury.io/js/jinqu-odata)\n<a href=\"https://snyk.io/test/npm/jinqu-odata\"><img src=\"https://snyk.io/test/npm/jinqu-odata/badge.svg\" alt=\"Known Vulnerabilities\" data-canonical-src=\"https://snyk.io/test/npm/jinqu-odata\" style=\"max-width:100%;\"></a>\n[![GitHub issues](https://img.shields.io/github/issues/jin-qu/jinqu-odata.svg)](https://github.com/jin-qu/jinqu-odata/issues)\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/jin-qu/jinqu-odata/master/LICENSE)\n\n[![GitHub stars](https://img.shields.io/github/stars/jin-qu/jinqu-odata.svg?style=social&label=Star)](https://github.com/jin-qu/jinqu-odata)\n[![GitHub forks](https://img.shields.io/github/forks/jin-qu/jinqu-odata.svg?style=social&label=Fork)](https://github.com/jin-qu/jinqu-odata)\n\nJinqu-odata lets you write LINQ queries against an odata source. For those who don't know LINQ, the benefits are:\n\n* A unified query language, whether querying local arrays, odata sources, or any other remote data source\n* Static typing where Typescript can verify your query is sound\n\njinqu-odata is dependent on the [jinqu](https://github.com/jin-qu/jinqu) package.\n\n## Installation\n\n```shell\nnpm install jinqu-odata\n```\n\n## Usage\n\nFirst, we need classes that map to our odata resources. For example:\n\n```typescript\n@oDataResource('Books')\nexport class Book {\n    Id: number\n    Title: string\n}\n```\n\nWe can now query filtered books as follows:\n\n```typescript\nconst service = new ODataService (\"https://www.solenya.org/odata\")\n\nconst books = await service\n    .createQuery(Book)\n    .where(b => b.Price > 60)\n    .toArrayAsync()\n\nfor (var b of books)\n    console.log (b)\n```\n\nYou can play with the live sample [here](https://stackblitz.com/edit/jinqu)\n\nThe query is translated to the following odata url:\n\n```shell\nhttps://www.solenya.org/odata/Books?$filter=Price gt 60\n```\n\n## Inheriting from ODataService\n\nA common pattern is to inherit from `ODataService` to provide stubs for your odata resources as follows:\n\n```typescript\nexport class CompanyService extends ODataService {\n\n    constructor (provider?: IAjaxProvider) {\n        super('odata')\n    }\n\n    companies() {\n        return this.createQuery(Company)\n    }\n}\n```\n\n## Code Generation\n\nCurrently we don't have code generators for jinqu-odata. However, we're actively considering this feature and it's tracked by this github issue:\n\n[https://github.com/jin-qu/jinqu-odata/issues/5](https://github.com/jin-qu/jinqu-odata/issues/5)\n\n## LINQ to OData Translation\n\njinqu-odata translates LINQ queries to OData Version 4 query strings. In the quries that follow, translations are shown as comments. You can check the unit tests for more thorough coverage of the translations.\n\n### Where\n\nTo filter results we use the `where` operator:\n\n```typescript\nconst result = await query\n    .where(c => c.name.startsWith('Net'))\n    .toArrayAsync()\n\n// odata/Companies?$filter=startsWith(name, \"Net\")\n```\n\n#### Supported Operators\n\n| Name | TypeScript/JavaScript | OData |\n| ---- | --------------------- | ----- |\n| Equals | ==, === | eq |\n| Not Equals | !=, !== | ne |\n| Greater Than | > | gt |\n| Greater Than or Equal | >= | ge |\n| Less Than | < | lt |\n| Less Than or Equal | <= | le |\n| Logical And | && | and |\n| Logical Or | \\|\\| | or |\n| Logical Not | ! | not |\n| Arithmetic Add | + | add |\n| Arithmetic Subtraction | - | sub |\n| Arithmetic Multiplication | * | mul |\n| Arithmetic Division | / | div |\n| Arithmetic Modulo | % | mod |\n| Arithmetic Negation | - | - |\n\n#### Supported Inline Functions\n\n| TypeScript/JavaScript | OData |\n| --------------------- | ----- |\n| includes | substringof |\n| endsWith | endswith |\n| startsWith | startswith |\n| length | length |\n| indexOf | indexof |\n| replace | replace |\n| substring | substring |\n| toLowerCase | tolower |\n| toUpperCase | toupper |\n| trim | trim |\n| concat | concat |\n| getMonth | month |\n| getDate | day |\n| getHours | hour |\n| getMinutes | minute |\n| getSeconds | second |\n| Math.round | round |\n| Math.floor | floor |\n| Math.ceiling | ceiling |\n\n### Select\n\nThe `select` operator lets us select only a subset of the fields of a type. It can only occur as the last operator in a query, so must be awaited:\n\n```typescript\nconst result = await query.select(\"name\")\n\n// $select=name\n```\n\n### OrderBy\n\nThe `orderBy` operator, optionally followed by some `thenBy` operators, specifies result order:\n\n```typescript\nconst result = await query\n    .orderBy(c => c.category)\n    .thenByDescending(c => c.created).toArrayAsync()\n\n// $orderby=category,created desc\n```\n\n### Count\n\nTo get the count of a resource:\n\n```typescript\nconst count = await query.count()\n\n// Companies/$count will be executed\n```\n\n### Skip and Take\n\nWe can skip a number of items, or limit the number of items, by calling `skip` and `take`. Here we query for the 3rd page in a result, by skipping the first 20 results, and then returning the top 10 of the remaining results:\n\n```typescript\nconst result = await query.skip(20).take(10).toArrayAsync()\n\n// $skip=20&$top=10\n```\n\n### InlineCount\n\nWe can use the `inlineCount` operator to include the `inlineCount` property on the results. This will cause query to wrap result.\n\n```typescript\nconst result = await query.inlineCount().toArrayAsync()\nconst value = result.value\nconst inlineCount = result.inlineCount // only populated if inlineCount operator was called\n```\n\nThis is useful in the preceding `skip/take` scenario, where to implement paging, we'd like the result to include a total non-paged count, without having to write a separate query. Just add the `inlineCount` operator before calling `skip/take`.\n\n### Expand\n\njinqu-odata supports expand, which enables you to pull in related entities. In this example, we don't merely want to return books; we also want to return the press associated with each book. We can do this as follows:\n\n```typescript\nconst companies = await service\n    .createQuery(Book)\n    .expand(\"Press\")\n    .toArrayAsync()\n\n// books$expand=Press\n```\n\n### Nested Expand\n\nSometimes we want to drill down more than one level. In this example, our odata source has `books`, where we want to return all the authors for some books. However, since books can have multiple authors, there's a join table between Authors and Books. Our model will mirror the odata metadata as follows:\n\n```typescript\n@oDataResource('Books')\nexport class Book {\n    Title: string\n    @Type(() => AuthorBook) AuthorBooks: AuthorBook[]\n}\n\nexport class AuthorBook {\n    @Type(() => Author) Author: Author\n}\n\nexport class Author {\n    Name: string\n}\n```\n\nTo query, we first `expand` the `AuthorBooks` property, and `thenExpand` the `Book` property, as follows:\n\n```typescript\nconst books = await service\n    .createQuery(Book)\n    .expand(\"AuthorBooks\")\n    .thenExpand(\"Author\")\n    .toArrayAsync()\n\n// books?$expand=AuthorBooks($expand=Author)\n```\n\n#### Filtering Expand by Rows and Columns\n\nFor efficiency, we can **filter by rows** an `expand`/`thenExpand` query by providing a predicate:\n\n```typescript\n.thenExpand(\"Author\") // no filter\n.thenExpand(\"Author\", a => a.endsWith (\"Albahari\")) // filtered\n\n// books?$expand=AuthorBooks($expand=Author($filter=endswith(Name,'Albahari')))\n```\n\nSimilarly, for efficiency, we can **filter by columns** an `expand`/`thenExpand` query by providing an array of column names:\n\n```typescript\n.thenExpand(\"Author\") // no filter\n.thenExpand(\"Author\", [\"Name\"]) // filtered columns\n\n// books?$expand=AuthorBooks($expand=Author($select=Name))\n```\n\n#### Deserialization\n\nThe `@Type` decorators belong to the `class-transformer` library that handles deserialization. We need those annotations since the typescript types aren't actually available at runtime. The `class-transformer` library imposes the small design restriction on us that any constructor arguments to our classes are optional.\n\n### GroupBy\n\n`groupBy` lets you group results by a particular property. Like `select`, it can only be used as the last operator in a query, and must therefore be awaited:\n\n```typescript\n// we group resources by \"deleted\" field\n// and select the count of each group with \"deleted\" field\nconst promise = await query.groupBy(\n    c => ({ deleted: c.deleted }),\n    g => ({ deleted: g.deleted, count: g.count() })\n)\n\n// $apply=groupby((deleted),aggregate(deleted,$count as count))\n```\n\nAs you can see in the translation, jinqu-odata supports `groupBy` with the `$apply` convention.\n\n## Old Browsers\n\njinqu-odata uses jinqu as a querying platform, if you want to use jinqu features with old browsers, please refer to [jinqu documentation](https://github.com/jin-qu/jinqu#readme).\n\n## License\n\njinqu-odata is licensed under the [MIT License](LICENSE).\n","readmeFilename":"README.md"}