@jin-qu/jinqu 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +212 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/ajax.d.ts +26 -0
- package/dist/lib/ajax.js +23 -0
- package/dist/lib/ajax.js.map +1 -0
- package/dist/lib/array-query-provider.d.ts +11 -0
- package/dist/lib/array-query-provider.js +1532 -0
- package/dist/lib/array-query-provider.js.map +1 -0
- package/dist/lib/query-part.d.ts +120 -0
- package/dist/lib/query-part.js +349 -0
- package/dist/lib/query-part.js.map +1 -0
- package/dist/lib/query.d.ts +73 -0
- package/dist/lib/query.js +455 -0
- package/dist/lib/query.js.map +1 -0
- package/dist/lib/shared.d.ts +114 -0
- package/dist/lib/shared.js +3 -0
- package/dist/lib/shared.js.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Umut Özel
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
# Jinqu - LINQ for Javascript
|
2
|
+
|
3
|
+
[](https://github.com/jin-qu/jinqu/actions/workflows/build.yml)
|
4
|
+
[](https://codecov.io/gh/jin-qu/jinqu)
|
5
|
+
[](https://www.codacy.com/gh/jin-qu/jinqu/dashboard?utm_source=github.com&utm_medium=referral&utm_content=jin-qu/jinqu&utm_campaign=Badge_Grade)
|
6
|
+
<a href="https://snyk.io/test/npm/jinqu"><img src="https://snyk.io/test/npm/jinqu/badge.svg" alt="Known Vulnerabilities" data-canonical-src="https://snyk.io/test/npm/jinqu" style="max-width:100%;"></a>
|
7
|
+
|
8
|
+
[](https://www.npmjs.com/package/jinqu)
|
9
|
+
[](https://www.npmjs.com/package/jinqu)
|
10
|
+
|
11
|
+
[](https://github.com/jin-qu/jinqu/issues)
|
12
|
+
[](https://raw.githubusercontent.com/jin-qu/jinqu/main/LICENSE)
|
13
|
+
[](https://github.com/jin-qu/jinqu)
|
14
|
+
[](https://github.com/jin-qu/jinqu)
|
15
|
+
|
16
|
+
Jinqu, based on the LINQ design, is the ultimate querying API for Javscript & Typescript. It provides:
|
17
|
+
|
18
|
+
* LINQ syntax
|
19
|
+
* Lazy (i.e. deferred) Evaluation
|
20
|
+
* Local and Remote Evaluation w/ provider model for libraries implementing remote evaluation (e.g. `jinqu-odata`)
|
21
|
+
* Static Typing (in Typescript)
|
22
|
+
* Dynamic queries (in strings)
|
23
|
+
* Even works on IE 11 (with transpilation)
|
24
|
+
|
25
|
+
Jinqu works perfectly in both Javascript and Typescript, but is optimized for Typescript. Jinqu is itself written in Typescript.
|
26
|
+
|
27
|
+
## Installation
|
28
|
+
|
29
|
+
> npm install jinqu
|
30
|
+
|
31
|
+
## Code Examples
|
32
|
+
|
33
|
+
First, make sure you've imported jinqu. This will add **asQueryable** method to Array Prototype.
|
34
|
+
|
35
|
+
```typescript
|
36
|
+
import 'jinqu'
|
37
|
+
```
|
38
|
+
|
39
|
+
We need to call **asQueryable** to create a query for an Array.
|
40
|
+
|
41
|
+
```typescript
|
42
|
+
const array = [1,2,3,4,5]
|
43
|
+
const query = array.asQueryable().where(c => n % 2 == 0).toArray()
|
44
|
+
for (var n of query)
|
45
|
+
console.log (n) // outputs 2,4
|
46
|
+
```
|
47
|
+
|
48
|
+
If you want to use query methods directly, you need to install and import **jinqu-array-extensions** package.
|
49
|
+
|
50
|
+
> npm i jinqu-array-extensions
|
51
|
+
|
52
|
+
```typescript
|
53
|
+
import 'jinqu-array-extensions'
|
54
|
+
```
|
55
|
+
|
56
|
+
You actually only need to do this once, such as in the entry point for your application, to ensure the Array prototype extensions are set up.
|
57
|
+
|
58
|
+
Now let's filter an array:
|
59
|
+
|
60
|
+
```typescript
|
61
|
+
const array = [1,2,3,4,5]
|
62
|
+
const query = array.where(c => n % 2 == 0).toArray()
|
63
|
+
for (var n of query)
|
64
|
+
console.log (n) // outputs 2,4
|
65
|
+
```
|
66
|
+
|
67
|
+
We can *chain* query operators:
|
68
|
+
|
69
|
+
```typescript
|
70
|
+
const array = [1,2,3,4,5]
|
71
|
+
const query = array
|
72
|
+
.where(c => n % 2 == 0)
|
73
|
+
.orderByDescending (n => n)
|
74
|
+
.toArray()
|
75
|
+
for (var n of query)
|
76
|
+
console.log (n) // outputs 4,2
|
77
|
+
```
|
78
|
+
|
79
|
+
Importantly, results aren't evaluated until `toArray` is called.
|
80
|
+
|
81
|
+
## Dynamic Expressions
|
82
|
+
|
83
|
+
```JavaScript
|
84
|
+
const filtered = orders.where('c => c.id > value', { value: 3 })
|
85
|
+
```
|
86
|
+
|
87
|
+
The additional argument is a *variable scope* that lets you pass in variables dynamically.
|
88
|
+
|
89
|
+
## Supported Query Operators
|
90
|
+
|
91
|
+
The full range of LINQ operators are supported:
|
92
|
+
|
93
|
+
```typescript
|
94
|
+
where
|
95
|
+
ofType
|
96
|
+
cast
|
97
|
+
select
|
98
|
+
selectMany
|
99
|
+
join
|
100
|
+
groupJoin
|
101
|
+
orderBy
|
102
|
+
orderByDescending
|
103
|
+
thenBy
|
104
|
+
thenByDescending
|
105
|
+
take
|
106
|
+
takeWhile
|
107
|
+
skip
|
108
|
+
skipWhile
|
109
|
+
groupBy
|
110
|
+
distinct
|
111
|
+
concat
|
112
|
+
zip
|
113
|
+
union
|
114
|
+
intersect
|
115
|
+
except
|
116
|
+
defaultIfEmpty
|
117
|
+
reverse
|
118
|
+
first
|
119
|
+
firstOrDefault
|
120
|
+
last
|
121
|
+
lastOrDefault
|
122
|
+
single
|
123
|
+
singleOrDefault
|
124
|
+
elementAt
|
125
|
+
elementAtOrDefault
|
126
|
+
contains
|
127
|
+
sequenceEqual
|
128
|
+
any
|
129
|
+
all
|
130
|
+
count
|
131
|
+
min
|
132
|
+
max
|
133
|
+
sum
|
134
|
+
average
|
135
|
+
aggregate
|
136
|
+
toArray
|
137
|
+
```
|
138
|
+
|
139
|
+
As well as:
|
140
|
+
|
141
|
+
```typescript
|
142
|
+
ofGuardedType
|
143
|
+
```
|
144
|
+
|
145
|
+
And also:
|
146
|
+
|
147
|
+
```typescript
|
148
|
+
range
|
149
|
+
repeat
|
150
|
+
```
|
151
|
+
|
152
|
+
## Remote Query Providers
|
153
|
+
|
154
|
+
Jinqu has the following remote providers:
|
155
|
+
|
156
|
+
* [Jinqu-OData](https://github.com/jin-qu/jinqu-odata) - Query OData endpoints
|
157
|
+
* [Linquest](https://github.com/jin-qu/linquest) - Query Remote LINQ endpoints
|
158
|
+
|
159
|
+
Remote queries always return promises so are awaited. So rather than `toArray` to obtain the results of the query, you'll call `toArrayAsync`:
|
160
|
+
|
161
|
+
```typescript
|
162
|
+
const result = await remoteQuery.toArrayAsync()
|
163
|
+
for (var item of result) {
|
164
|
+
// do stuff
|
165
|
+
}
|
166
|
+
```
|
167
|
+
|
168
|
+
## Array Prototype Extensions
|
169
|
+
|
170
|
+
Jinqu query operators build queries with a simple model: they take a query type as an input, transform it, and output another query type. However, the very first operator in a query needs to take an array type as the original source for the query. To make this work, jinqu extends the Array prototype.
|
171
|
+
|
172
|
+
Extending the array prototype is very convenient, but occasionally has conflict issues with Array's built-in prototype or other 3rd party prototype extensions.
|
173
|
+
|
174
|
+
To overcome this, you can call `asQueryable` or the convenience `q` for short, to ensure you're working with an `IQuery<T>` type:
|
175
|
+
|
176
|
+
```typescript
|
177
|
+
[1,2,3].asQueryable().reverse()
|
178
|
+
[1,2,3].q().reverse() // same as above
|
179
|
+
```
|
180
|
+
|
181
|
+
In addition, the `concat`, `join`, and `reverse` methdos (which are built into the Array prototype), have special support: call `concatWith`, `joinWith`, and `reverseTo`, to start a query with these operators on the array type.
|
182
|
+
|
183
|
+
## ofType and ofGuardedType
|
184
|
+
|
185
|
+
`ofType` and `ofGuardedType` filter elements of a specified type. The type arguments you must supply are a little different to what you might expect if you come from a C# background, but will make sense to you when you get a feel for the Typescript type system.
|
186
|
+
|
187
|
+
* `ofType` takes either a:
|
188
|
+
* constructor to filter class instances
|
189
|
+
* default value to filter primitive types
|
190
|
+
* `ofGuardedType` takes a:
|
191
|
+
* Typescript type guard (See [Typescript Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)) to filter values by a condition indicative of type
|
192
|
+
|
193
|
+
Their usage is as follows:
|
194
|
+
|
195
|
+
```typescript
|
196
|
+
class Panda {
|
197
|
+
constructor (public id: number) {}
|
198
|
+
}
|
199
|
+
|
200
|
+
function isNumber(x: any): x is number {
|
201
|
+
return typeof x === "number"
|
202
|
+
}
|
203
|
+
|
204
|
+
const array = ["1", 2, new Panda(3), "4", 5, new Panda(6)]
|
205
|
+
const justPandas = array.ofType(Panda) // panda 3, panda 6 - using constructor type filter
|
206
|
+
const justStrings = array.ofType("") // "1", "4" - using default value type filter
|
207
|
+
const justNumbers = array.ofGuardedType(isNumber) // 2, 5 - using type guard filter
|
208
|
+
```
|
209
|
+
|
210
|
+
## License
|
211
|
+
|
212
|
+
jinqu is licensed with the [MIT License](LICENSE).
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
import { Ctor, IQuery } from "./lib/shared";
|
2
|
+
declare global {
|
3
|
+
interface Array<T> {
|
4
|
+
asQueryable(ctor?: Ctor<T>): IQuery<T>;
|
5
|
+
}
|
6
|
+
}
|
7
|
+
export * from "./lib/ajax";
|
8
|
+
export * from "./lib/array-query-provider";
|
9
|
+
export * from "./lib/query-part";
|
10
|
+
export * from "./lib/query";
|
11
|
+
export * from "./lib/shared";
|
package/dist/index.js
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
+
if (k2 === undefined) k2 = k;
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
+
}
|
8
|
+
Object.defineProperty(o, k2, desc);
|
9
|
+
}) : (function(o, m, k, k2) {
|
10
|
+
if (k2 === undefined) k2 = k;
|
11
|
+
o[k2] = m[k];
|
12
|
+
}));
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
|
+
};
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
17
|
+
var array_query_provider_1 = require("./lib/array-query-provider");
|
18
|
+
Array.prototype.asQueryable = function (ctor) {
|
19
|
+
var query = new array_query_provider_1.ArrayQueryProvider(this).createQuery();
|
20
|
+
return ctor ? query.cast(ctor) : query;
|
21
|
+
};
|
22
|
+
__exportStar(require("./lib/ajax"), exports);
|
23
|
+
__exportStar(require("./lib/array-query-provider"), exports);
|
24
|
+
__exportStar(require("./lib/query-part"), exports);
|
25
|
+
__exportStar(require("./lib/query"), exports);
|
26
|
+
__exportStar(require("./lib/shared"), exports);
|
27
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,mEAAgE;AAShE,KAAK,CAAC,SAAS,CAAC,WAAW,GAAG,UAAS,IAAmB;IACtD,IAAM,KAAK,GAAG,IAAI,yCAAkB,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACzD,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC3C,CAAC,CAAC;AAEF,6CAA2B;AAC3B,6DAA2C;AAC3C,mDAAiC;AACjC,8CAA4B;AAC5B,+CAA6B"}
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import { Value } from "./shared";
|
2
|
+
export interface QueryParameter {
|
3
|
+
key: string;
|
4
|
+
value: string;
|
5
|
+
}
|
6
|
+
export declare const AjaxFuncs: {
|
7
|
+
includeResponse: string;
|
8
|
+
options: string;
|
9
|
+
};
|
10
|
+
export interface AjaxOptions {
|
11
|
+
$url?: string;
|
12
|
+
$method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
13
|
+
$params?: QueryParameter[];
|
14
|
+
$data?: unknown;
|
15
|
+
$timeout?: number;
|
16
|
+
$headers?: {
|
17
|
+
[key: string]: string;
|
18
|
+
};
|
19
|
+
}
|
20
|
+
export interface AjaxResponse<TResponse> {
|
21
|
+
response: TResponse;
|
22
|
+
}
|
23
|
+
export interface IAjaxProvider<TResponse, TOptions extends AjaxOptions = AjaxOptions> {
|
24
|
+
ajax<T>(options: TOptions): PromiseLike<Value<T> & AjaxResponse<TResponse>>;
|
25
|
+
}
|
26
|
+
export declare function mergeAjaxOptions(o1?: AjaxOptions | null, o2?: AjaxOptions | null): AjaxOptions;
|
package/dist/lib/ajax.js
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.AjaxFuncs = void 0;
|
4
|
+
exports.mergeAjaxOptions = mergeAjaxOptions;
|
5
|
+
exports.AjaxFuncs = {
|
6
|
+
includeResponse: "includeResponse",
|
7
|
+
options: "options",
|
8
|
+
};
|
9
|
+
function mergeAjaxOptions(o1, o2) {
|
10
|
+
if (o1 == null)
|
11
|
+
return o2;
|
12
|
+
if (o2 == null)
|
13
|
+
return o1;
|
14
|
+
return {
|
15
|
+
$data: Object.assign({}, o1.$data, o2.$data),
|
16
|
+
$headers: Object.assign({}, o1.$headers, o2.$headers),
|
17
|
+
$method: o2.$method || o1.$method,
|
18
|
+
$params: (o1.$params || []).concat(o2.$params || []),
|
19
|
+
$timeout: o2.$timeout || o1.$timeout,
|
20
|
+
$url: o2.$url != null ? o2.$url : o1.$url,
|
21
|
+
};
|
22
|
+
}
|
23
|
+
//# sourceMappingURL=ajax.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ajax.js","sourceRoot":"","sources":["../../lib/ajax.ts"],"names":[],"mappings":";;;AA4BA,4CAYC;AAlCY,QAAA,SAAS,GAAG;IACrB,eAAe,EAAE,iBAAiB;IAClC,OAAO,EAAE,SAAS;CACrB,CAAC;AAmBF,SAAgB,gBAAgB,CAAC,EAAuB,EAAE,EAAuB;IAC7E,IAAI,EAAE,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAC1B,IAAI,EAAE,IAAI,IAAI;QAAE,OAAO,EAAE,CAAC;IAE1B,OAAO;QACH,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC;QAC5C,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC;QACrD,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO;QACjC,OAAO,EAAE,CAAC,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,IAAI,EAAE,CAAC;QACpD,QAAQ,EAAE,EAAE,CAAC,QAAQ,IAAI,EAAE,CAAC,QAAQ;QACpC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI;KAC5C,CAAC;AACN,CAAC"}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { Query } from "./query";
|
2
|
+
import { Ctor, IQueryPart, IQueryProvider } from "./shared";
|
3
|
+
export declare class ArrayQueryProvider implements IQueryProvider {
|
4
|
+
private readonly items?;
|
5
|
+
constructor(items?: unknown[] | IterableIterator<unknown> | null);
|
6
|
+
createQuery<T>(parts?: IQueryPart[], ctor?: Ctor<T>): Query<T>;
|
7
|
+
execute<TResult = unknown>(parts?: IQueryPart[] | null): TResult;
|
8
|
+
executeAsync<TResult = unknown>(parts: IQueryPart[]): PromiseLike<TResult>;
|
9
|
+
handlePart(items: IterableIterator<unknown>, part: IQueryPart): any;
|
10
|
+
multiOrderBy(items: IterableIterator<unknown>, keySelectors: IQueryPart[]): ArrayIterator<unknown>;
|
11
|
+
}
|