Gathering detailed insights and metrics for @jin-qu/odata
Gathering detailed insights and metrics for @jin-qu/odata
Gathering detailed insights and metrics for @jin-qu/odata
Gathering detailed insights and metrics for @jin-qu/odata
npm install @jin-qu/odata
Typescript
Module System
Node Version
NPM Version
TypeScript (98.79%)
JavaScript (1.21%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
31 Stars
204 Commits
4 Forks
8 Watchers
2 Branches
4 Contributors
Updated on Feb 24, 2025
Latest Version
2.0.0
Package Id
@jin-qu/odata@2.0.0
Unpacked Size
99.07 kB
Size
21.89 kB
File Count
21
NPM Version
10.8.2
Node Version
20.18.2
Published on
Feb 24, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
Jinqu-odata lets you write LINQ queries against an odata source. For those who don't know LINQ, the benefits are:
jinqu-odata is dependent on the jinqu package.
1npm install jinqu-odata
First, we need classes that map to our odata resources. For example:
1@oDataResource('Books') 2export class Book { 3 Id: number 4 Title: string 5}
We can now query filtered books as follows:
1const service = new ODataService ("https://www.solenya.org/odata") 2 3const books = await service 4 .createQuery(Book) 5 .where(b => b.Price > 60) 6 .toArrayAsync() 7 8for (var b of books) 9 console.log (b)
You can play with the live sample here
The query is translated to the following odata url:
1https://www.solenya.org/odata/Books?$filter=Price gt 60
A common pattern is to inherit from ODataService
to provide stubs for your odata resources as follows:
1export class CompanyService extends ODataService { 2 3 constructor (provider?: IAjaxProvider) { 4 super('odata') 5 } 6 7 companies() { 8 return this.createQuery(Company) 9 } 10}
Currently we don't have code generators for jinqu-odata. However, we're actively considering this feature and it's tracked by this github issue:
https://github.com/jin-qu/jinqu-odata/issues/5
jinqu-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.
To filter results we use the where
operator:
1const result = await query 2 .where(c => c.name.startsWith('Net')) 3 .toArrayAsync() 4 5// odata/Companies?$filter=startsWith(name, "Net")
Name | TypeScript/JavaScript | OData |
---|---|---|
Equals | ==, === | eq |
Not Equals | !=, !== | ne |
Greater Than | > | gt |
Greater Than or Equal | >= | ge |
Less Than | < | lt |
Less Than or Equal | <= | le |
Logical And | && | and |
Logical Or | || | or |
Logical Not | ! | not |
Arithmetic Add | + | add |
Arithmetic Subtraction | - | sub |
Arithmetic Multiplication | * | mul |
Arithmetic Division | / | div |
Arithmetic Modulo | % | mod |
Arithmetic Negation | - | - |
TypeScript/JavaScript | OData |
---|---|
includes | substringof |
endsWith | endswith |
startsWith | startswith |
length | length |
indexOf | indexof |
replace | replace |
substring | substring |
toLowerCase | tolower |
toUpperCase | toupper |
trim | trim |
concat | concat |
getMonth | month |
getDate | day |
getHours | hour |
getMinutes | minute |
getSeconds | second |
Math.round | round |
Math.floor | floor |
Math.ceiling | ceiling |
The 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:
1const result = await query.select("name") 2 3// $select=name
The orderBy
operator, optionally followed by some thenBy
operators, specifies result order:
1const result = await query 2 .orderBy(c => c.category) 3 .thenByDescending(c => c.created).toArrayAsync() 4 5// $orderby=category,created desc
To get the count of a resource:
1const count = await query.count() 2 3// Companies/$count will be executed
We 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:
1const result = await query.skip(20).take(10).toArrayAsync() 2 3// $skip=20&$top=10
We can use the inlineCount
operator to include the inlineCount
property on the results. This will cause query to wrap result.
1const result = await query.inlineCount().toArrayAsync() 2const value = result.value 3const inlineCount = result.inlineCount // only populated if inlineCount operator was called
This 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
.
jinqu-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:
1const companies = await service 2 .createQuery(Book) 3 .expand("Press") 4 .toArrayAsync() 5 6// books$expand=Press
Sometimes 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:
1@oDataResource('Books') 2export class Book { 3 Title: string 4 @Type(() => AuthorBook) AuthorBooks: AuthorBook[] 5} 6 7export class AuthorBook { 8 @Type(() => Author) Author: Author 9} 10 11export class Author { 12 Name: string 13}
To query, we first expand
the AuthorBooks
property, and thenExpand
the Book
property, as follows:
1const books = await service 2 .createQuery(Book) 3 .expand("AuthorBooks") 4 .thenExpand("Author") 5 .toArrayAsync() 6 7// books?$expand=AuthorBooks($expand=Author)
For efficiency, we can filter by rows an expand
/thenExpand
query by providing a predicate:
.thenExpand("Author") // no filter
.thenExpand("Author", a => a.endsWith("Albahari")) // filtered
// books?$expand=AuthorBooks($expand=Author($filter=endswith(Name,'Albahari')))
Similarly, for efficiency, we can filter by columns an expand
/thenExpand
query by providing an array of column names:
.thenExpand("Author") // no filter
.thenExpand("Author", ["Name"]) // filtered columns
// books?$expand=AuthorBooks($expand=Author($select=Name))
The @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.
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:
1// we group resources by "deleted" field 2// and select the count of each group with "deleted" field 3const promise = await query.groupBy( 4 c => ({ deleted: c.deleted }), 5 g => ({ deleted: g.deleted, count: g.count() }) 6) 7 8// $apply=groupby((deleted),aggregate(deleted,$count as count))
As you can see in the translation, jinqu-odata supports groupBy
with the $apply
convention.
jinqu-odata uses jinqu as a querying platform, if you want to use jinqu features with old browsers, please refer to jinqu documentation.
jinqu-odata is licensed under the MIT License.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
no dangerous workflow patterns detected
Reason
license file detected
Details
Reason
2 existing vulnerabilities detected
Details
Reason
SAST tool is not run on all commits -- score normalized to 2
Details
Reason
Found 2/13 approved changesets -- score normalized to 1
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More