querier-ts 0.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 +234 -0
- package/lib/base-object.d.ts +6 -0
- package/lib/base-object.js +15 -0
- package/lib/errors/index.d.ts +2 -0
- package/lib/errors/index.js +5 -0
- package/lib/errors/invalid-argument-error.d.ts +10 -0
- package/lib/errors/invalid-argument-error.js +11 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +5 -0
- package/lib/query-conditions-group-nullable.d.ts +4 -0
- package/lib/query-conditions-group-nullable.js +2 -0
- package/lib/query-conditions-group.d.ts +4 -0
- package/lib/query-conditions-group.js +2 -0
- package/lib/query-row-validator.d.ts +72 -0
- package/lib/query-row-validator.js +85 -0
- package/lib/query.d.ts +215 -0
- package/lib/query.js +331 -0
- package/lib/utils/decorators/number-validaton.d.ts +36 -0
- package/lib/utils/decorators/number-validaton.js +124 -0
- package/lib/utils/functions/generic/compare-arrays.d.ts +9 -0
- package/lib/utils/functions/generic/compare-arrays.js +13 -0
- package/lib/utils/functions/generic/get-entries.d.ts +8 -0
- package/lib/utils/functions/generic/get-entries.js +12 -0
- package/lib/utils/functions/generic/index.d.ts +3 -0
- package/lib/utils/functions/generic/index.js +7 -0
- package/lib/utils/functions/sort/index.d.ts +3 -0
- package/lib/utils/functions/sort/index.js +7 -0
- package/lib/utils/functions/sort/sort-by-properties.d.ts +2 -0
- package/lib/utils/functions/sort/sort-by-properties.js +17 -0
- package/lib/utils/functions/sort/sort-by-property.d.ts +2 -0
- package/lib/utils/functions/sort/sort-by-property.js +15 -0
- package/lib/utils/functions/type-guards/index.d.ts +4 -0
- package/lib/utils/functions/type-guards/index.js +9 -0
- package/lib/utils/functions/type-guards/is-function.d.ts +8 -0
- package/lib/utils/functions/type-guards/is-function.js +12 -0
- package/lib/utils/functions/type-guards/is-number.d.ts +8 -0
- package/lib/utils/functions/type-guards/is-number.js +12 -0
- package/lib/utils/functions/type-guards/is-object.d.ts +8 -0
- package/lib/utils/functions/type-guards/is-object.js +12 -0
- package/lib/utils/types/add-prefix-to-object.d.ts +3 -0
- package/lib/utils/types/add-prefix-to-object.js +2 -0
- package/lib/utils/types/allowed-names.d.ts +5 -0
- package/lib/utils/types/allowed-names.js +2 -0
- package/lib/utils/types/flag-excluded-type.d.ts +6 -0
- package/lib/utils/types/flag-excluded-type.js +2 -0
- package/lib/utils/types/generic-object.d.ts +3 -0
- package/lib/utils/types/generic-object.js +3 -0
- package/lib/utils/types/index.d.ts +10 -0
- package/lib/utils/types/index.js +2 -0
- package/lib/utils/types/omit-type.d.ts +5 -0
- package/lib/utils/types/omit-type.js +2 -0
- package/lib/utils/types/partial-of-properties.d.ts +2 -0
- package/lib/utils/types/partial-of-properties.js +2 -0
- package/lib/utils/types/prop-of.d.ts +5 -0
- package/lib/utils/types/prop-of.js +2 -0
- package/lib/utils/types/property-only.d.ts +4 -0
- package/lib/utils/types/property-only.js +2 -0
- package/lib/utils/types/recursive-partial.d.ts +3 -0
- package/lib/utils/types/recursive-partial.js +2 -0
- package/lib/utils/types/type.d.ts +4 -0
- package/lib/utils/types/type.js +2 -0
- package/package.json +52 -0
package/lib/query.d.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { addPrefixToObject, PropertyOnly, PropOf } from './utils/types';
|
|
2
|
+
import { QueryConditionsGroup } from './query-conditions-group';
|
|
3
|
+
import { QueryConditionsGroupNullable } from './query-conditions-group-nullable';
|
|
4
|
+
/**
|
|
5
|
+
* Allows filtering data from an array of objects.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* interface User {
|
|
10
|
+
* id: string;
|
|
11
|
+
* email: string;
|
|
12
|
+
* isActive: boolean;
|
|
13
|
+
* createdAt: string;
|
|
14
|
+
* updatedAt: string;
|
|
15
|
+
* }
|
|
16
|
+
*
|
|
17
|
+
* const users: User[] = [];
|
|
18
|
+
*
|
|
19
|
+
* // Filtering objects
|
|
20
|
+
*
|
|
21
|
+
* const activeGmailUsers = Query.from(users)
|
|
22
|
+
* .where({
|
|
23
|
+
* isActive: true,
|
|
24
|
+
* email: (email) => email.endsWith('@gmail.com'),
|
|
25
|
+
* })
|
|
26
|
+
* .all();
|
|
27
|
+
*
|
|
28
|
+
* // Selecting specific data
|
|
29
|
+
*
|
|
30
|
+
* const userEmails = Query.from(users)
|
|
31
|
+
* .select('email')
|
|
32
|
+
* .column();
|
|
33
|
+
*
|
|
34
|
+
* const lastUserId = Query.from(users)
|
|
35
|
+
* .select('id')
|
|
36
|
+
* .orderBy('-createdAt')
|
|
37
|
+
* .scalar();
|
|
38
|
+
*
|
|
39
|
+
* // Checking information
|
|
40
|
+
*
|
|
41
|
+
* const userExists = Query.from(users)
|
|
42
|
+
* .where({
|
|
43
|
+
* id: 'some-id',
|
|
44
|
+
* })
|
|
45
|
+
* .exists();
|
|
46
|
+
*
|
|
47
|
+
* const numberOfUsers = Query.from(users).count();
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare class Query<T extends object> {
|
|
51
|
+
#private;
|
|
52
|
+
/**
|
|
53
|
+
* Indicates whether conditions with `null` and `undefined` values should be
|
|
54
|
+
* skipped.
|
|
55
|
+
*/
|
|
56
|
+
private ignoreNullValues;
|
|
57
|
+
/**
|
|
58
|
+
* Initializes the query.
|
|
59
|
+
*
|
|
60
|
+
* @param {T[]} rows Rows to be queried.
|
|
61
|
+
*/
|
|
62
|
+
private constructor();
|
|
63
|
+
/**
|
|
64
|
+
* Creates a new query based on the given data.
|
|
65
|
+
*
|
|
66
|
+
* @param {T[]} rows Rows to be queried.
|
|
67
|
+
*
|
|
68
|
+
* @returns {Query<T>} Query to the given rows.
|
|
69
|
+
*/
|
|
70
|
+
static from<T extends object>(rows: T[]): Query<T>;
|
|
71
|
+
/**
|
|
72
|
+
* Defines specific columns to be returned on the final results.
|
|
73
|
+
*
|
|
74
|
+
* @param {PropOf<T> | PropOf<T>[]} columns Selected columns.
|
|
75
|
+
*
|
|
76
|
+
* @returns {this} Current query.
|
|
77
|
+
*/
|
|
78
|
+
select(columns: PropOf<T> | PropOf<T>[]): this;
|
|
79
|
+
/**
|
|
80
|
+
* Applies conditions to the query.
|
|
81
|
+
*
|
|
82
|
+
* @param {QueryConditionsGroup<T> | ((obj: T) => boolean)} condition Filter to
|
|
83
|
+
* be applied to the query.
|
|
84
|
+
*
|
|
85
|
+
* If a callback function is provided, it must return a boolean value.
|
|
86
|
+
*
|
|
87
|
+
* If an object is provided, its properties must be attributes of `T` and their
|
|
88
|
+
* corresponding values must be the expected values for the attributes or a
|
|
89
|
+
* callback functions that return boolean values.
|
|
90
|
+
*
|
|
91
|
+
* @returns {this} Current query.
|
|
92
|
+
*/
|
|
93
|
+
where(condition: QueryConditionsGroup<T> | ((obj: T) => boolean)): this;
|
|
94
|
+
/**
|
|
95
|
+
* Applies a set of conditions to the query ignoring `null` and `undefined`
|
|
96
|
+
* values as conditions.
|
|
97
|
+
*
|
|
98
|
+
* @param {QueryConditionsGroupNullable<T>} condition An object where each
|
|
99
|
+
* property represents an attribute to be validated. The values can be
|
|
100
|
+
* literal or callback functions that return a boolean. If `null` or `undefined`
|
|
101
|
+
* is passed, that condition will be skipped.
|
|
102
|
+
*
|
|
103
|
+
* @returns {this} Current query.
|
|
104
|
+
*/
|
|
105
|
+
filterWhere(condition: QueryConditionsGroupNullable<T>): this;
|
|
106
|
+
/**
|
|
107
|
+
* Adds ordering to the results.
|
|
108
|
+
*
|
|
109
|
+
* @param {(PropOf<T> | keyof addPrefixToObject<PropertyOnly<T>, '-'>)[]} columns
|
|
110
|
+
* Ascending or descending columns. To mark a field as descending, use `-` before
|
|
111
|
+
* its name.
|
|
112
|
+
*
|
|
113
|
+
* @returns {this} Current query.
|
|
114
|
+
*/
|
|
115
|
+
orderBy(...columns: (PropOf<T> | keyof addPrefixToObject<PropertyOnly<T>, '-'>)[]): this;
|
|
116
|
+
/**
|
|
117
|
+
* Returns the current number of rows.
|
|
118
|
+
*
|
|
119
|
+
* @return {number}
|
|
120
|
+
*/
|
|
121
|
+
count(): number;
|
|
122
|
+
/**
|
|
123
|
+
* Checks if there is at least one row compatible with the query.
|
|
124
|
+
*
|
|
125
|
+
* @returns {boolean} Boolean indicating whether any row exists.
|
|
126
|
+
*/
|
|
127
|
+
exists(): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Returns the first result.
|
|
130
|
+
*
|
|
131
|
+
* @returns {T}
|
|
132
|
+
*/
|
|
133
|
+
first(): T | null;
|
|
134
|
+
/**
|
|
135
|
+
* Returns the last result.
|
|
136
|
+
*
|
|
137
|
+
* @returns {T}
|
|
138
|
+
*/
|
|
139
|
+
last(): T | null;
|
|
140
|
+
/**
|
|
141
|
+
* Returns all results.
|
|
142
|
+
*
|
|
143
|
+
* @returns {T[]}
|
|
144
|
+
*/
|
|
145
|
+
all(): T[];
|
|
146
|
+
/**
|
|
147
|
+
* Returns the value of the first (selected) column of the first row.
|
|
148
|
+
*
|
|
149
|
+
* @returns {T[Promise<T>]|false} First value or `false`, if none row exists.
|
|
150
|
+
*/
|
|
151
|
+
scalar(): T[PropOf<T>] | false;
|
|
152
|
+
/**
|
|
153
|
+
* Returns the values of the first (selected) column of all rows.
|
|
154
|
+
*
|
|
155
|
+
* @returns {T[Promise<T>][]} Values from the first (selected) column.
|
|
156
|
+
*/
|
|
157
|
+
column(): T[PropOf<T>][];
|
|
158
|
+
/**
|
|
159
|
+
* Returns the values of the rows. If there are selected columns, only their
|
|
160
|
+
* values will be returned.
|
|
161
|
+
*
|
|
162
|
+
* @returns {T[PropOf<T>][][]} Array with the values of all rows.
|
|
163
|
+
*/
|
|
164
|
+
values(): T[PropOf<T>][][];
|
|
165
|
+
/**
|
|
166
|
+
* Defines the number of rows to skip.
|
|
167
|
+
*
|
|
168
|
+
* @param {number} numberOfRows Numbers of rows to skip. Only non negative integer numbers
|
|
169
|
+
* are allowed.
|
|
170
|
+
*
|
|
171
|
+
* @returns {this} Current query.
|
|
172
|
+
*
|
|
173
|
+
* @throws {InvalidArgumentError} If the given number is less than 0.
|
|
174
|
+
*/
|
|
175
|
+
skip(numberOfRows: number): this;
|
|
176
|
+
/**
|
|
177
|
+
* Defines a limit for the number of results.
|
|
178
|
+
*
|
|
179
|
+
* @param {number} limit Limit of results. Only non negative integer numbers are allowed.
|
|
180
|
+
*
|
|
181
|
+
* @returns {this} Current query.
|
|
182
|
+
*
|
|
183
|
+
* @throws {InvalidArgumentError} If the given limit is less than 0.
|
|
184
|
+
*/
|
|
185
|
+
limit(limit: number): this;
|
|
186
|
+
/**
|
|
187
|
+
* Returns the rows that should be used in the final results.
|
|
188
|
+
*
|
|
189
|
+
* @returns {T[]} Rows within the specified limit.
|
|
190
|
+
*/
|
|
191
|
+
private getLimitedRows;
|
|
192
|
+
/**
|
|
193
|
+
* Returns the first selected column or the first key of some row.
|
|
194
|
+
*
|
|
195
|
+
* @returns {Promise<T>|null} The first column or `null`, if none is selected
|
|
196
|
+
* or there is no row.
|
|
197
|
+
*/
|
|
198
|
+
private getFirstColumn;
|
|
199
|
+
/**
|
|
200
|
+
* Filters the rows according to the given conditions.
|
|
201
|
+
*
|
|
202
|
+
* @param {QueryConditionsGroupNullable<T> | ((obj: T) => boolean)} condition
|
|
203
|
+
* Object or callback function.
|
|
204
|
+
*/
|
|
205
|
+
private filterRows;
|
|
206
|
+
/**
|
|
207
|
+
* Validates a row based on the given conditions object.
|
|
208
|
+
*
|
|
209
|
+
* @param {T} row Row to validate.
|
|
210
|
+
* @param {QueryConditionsGroupNullable<T>} condition Conditions object.
|
|
211
|
+
*
|
|
212
|
+
* @returns {boolean} Validation result.
|
|
213
|
+
*/
|
|
214
|
+
private validateRow;
|
|
215
|
+
}
|
package/lib/query.js
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
9
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
10
|
+
};
|
|
11
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
12
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
13
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
14
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
15
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
16
|
+
};
|
|
17
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
18
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
19
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
20
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
21
|
+
};
|
|
22
|
+
var _Query_rows, _Query_columns, _Query_startAt, _Query_limit;
|
|
23
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
+
exports.Query = void 0;
|
|
25
|
+
const sort_1 = require("./utils/functions/sort");
|
|
26
|
+
const type_guards_1 = require("./utils/functions/type-guards");
|
|
27
|
+
const query_row_validator_1 = require("./query-row-validator");
|
|
28
|
+
const number_validaton_1 = require("./utils/decorators/number-validaton");
|
|
29
|
+
/**
|
|
30
|
+
* Allows filtering data from an array of objects.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* interface User {
|
|
35
|
+
* id: string;
|
|
36
|
+
* email: string;
|
|
37
|
+
* isActive: boolean;
|
|
38
|
+
* createdAt: string;
|
|
39
|
+
* updatedAt: string;
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* const users: User[] = [];
|
|
43
|
+
*
|
|
44
|
+
* // Filtering objects
|
|
45
|
+
*
|
|
46
|
+
* const activeGmailUsers = Query.from(users)
|
|
47
|
+
* .where({
|
|
48
|
+
* isActive: true,
|
|
49
|
+
* email: (email) => email.endsWith('@gmail.com'),
|
|
50
|
+
* })
|
|
51
|
+
* .all();
|
|
52
|
+
*
|
|
53
|
+
* // Selecting specific data
|
|
54
|
+
*
|
|
55
|
+
* const userEmails = Query.from(users)
|
|
56
|
+
* .select('email')
|
|
57
|
+
* .column();
|
|
58
|
+
*
|
|
59
|
+
* const lastUserId = Query.from(users)
|
|
60
|
+
* .select('id')
|
|
61
|
+
* .orderBy('-createdAt')
|
|
62
|
+
* .scalar();
|
|
63
|
+
*
|
|
64
|
+
* // Checking information
|
|
65
|
+
*
|
|
66
|
+
* const userExists = Query.from(users)
|
|
67
|
+
* .where({
|
|
68
|
+
* id: 'some-id',
|
|
69
|
+
* })
|
|
70
|
+
* .exists();
|
|
71
|
+
*
|
|
72
|
+
* const numberOfUsers = Query.from(users).count();
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
class Query {
|
|
76
|
+
/**
|
|
77
|
+
* Initializes the query.
|
|
78
|
+
*
|
|
79
|
+
* @param {T[]} rows Rows to be queried.
|
|
80
|
+
*/
|
|
81
|
+
constructor(rows) {
|
|
82
|
+
/**
|
|
83
|
+
* Rows to be queried.
|
|
84
|
+
*/
|
|
85
|
+
_Query_rows.set(this, []);
|
|
86
|
+
/**
|
|
87
|
+
* Selected columns.
|
|
88
|
+
*/
|
|
89
|
+
_Query_columns.set(this, []);
|
|
90
|
+
/**
|
|
91
|
+
* Number of results to skip.
|
|
92
|
+
*/
|
|
93
|
+
_Query_startAt.set(this, 0);
|
|
94
|
+
/**
|
|
95
|
+
* Limit of results.
|
|
96
|
+
*/
|
|
97
|
+
_Query_limit.set(this, void 0);
|
|
98
|
+
/**
|
|
99
|
+
* Indicates whether conditions with `null` and `undefined` values should be
|
|
100
|
+
* skipped.
|
|
101
|
+
*/
|
|
102
|
+
this.ignoreNullValues = false;
|
|
103
|
+
__classPrivateFieldSet(this, _Query_rows, [...rows], "f");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Creates a new query based on the given data.
|
|
107
|
+
*
|
|
108
|
+
* @param {T[]} rows Rows to be queried.
|
|
109
|
+
*
|
|
110
|
+
* @returns {Query<T>} Query to the given rows.
|
|
111
|
+
*/
|
|
112
|
+
static from(rows) {
|
|
113
|
+
return new Query(rows);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Defines specific columns to be returned on the final results.
|
|
117
|
+
*
|
|
118
|
+
* @param {PropOf<T> | PropOf<T>[]} columns Selected columns.
|
|
119
|
+
*
|
|
120
|
+
* @returns {this} Current query.
|
|
121
|
+
*/
|
|
122
|
+
select(columns) {
|
|
123
|
+
__classPrivateFieldSet(this, _Query_columns, Array.isArray(columns) ? columns : [columns], "f");
|
|
124
|
+
return this;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Applies conditions to the query.
|
|
128
|
+
*
|
|
129
|
+
* @param {QueryConditionsGroup<T> | ((obj: T) => boolean)} condition Filter to
|
|
130
|
+
* be applied to the query.
|
|
131
|
+
*
|
|
132
|
+
* If a callback function is provided, it must return a boolean value.
|
|
133
|
+
*
|
|
134
|
+
* If an object is provided, its properties must be attributes of `T` and their
|
|
135
|
+
* corresponding values must be the expected values for the attributes or a
|
|
136
|
+
* callback functions that return boolean values.
|
|
137
|
+
*
|
|
138
|
+
* @returns {this} Current query.
|
|
139
|
+
*/
|
|
140
|
+
where(condition) {
|
|
141
|
+
this.filterRows(condition);
|
|
142
|
+
return this;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Applies a set of conditions to the query ignoring `null` and `undefined`
|
|
146
|
+
* values as conditions.
|
|
147
|
+
*
|
|
148
|
+
* @param {QueryConditionsGroupNullable<T>} condition An object where each
|
|
149
|
+
* property represents an attribute to be validated. The values can be
|
|
150
|
+
* literal or callback functions that return a boolean. If `null` or `undefined`
|
|
151
|
+
* is passed, that condition will be skipped.
|
|
152
|
+
*
|
|
153
|
+
* @returns {this} Current query.
|
|
154
|
+
*/
|
|
155
|
+
filterWhere(condition) {
|
|
156
|
+
this.ignoreNullValues = true;
|
|
157
|
+
this.filterRows(condition);
|
|
158
|
+
this.ignoreNullValues = false;
|
|
159
|
+
return this;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Adds ordering to the results.
|
|
163
|
+
*
|
|
164
|
+
* @param {(PropOf<T> | keyof addPrefixToObject<PropertyOnly<T>, '-'>)[]} columns
|
|
165
|
+
* Ascending or descending columns. To mark a field as descending, use `-` before
|
|
166
|
+
* its name.
|
|
167
|
+
*
|
|
168
|
+
* @returns {this} Current query.
|
|
169
|
+
*/
|
|
170
|
+
orderBy(...columns) {
|
|
171
|
+
__classPrivateFieldGet(this, _Query_rows, "f").sort((0, sort_1.sortByProperties)(...columns));
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Returns the current number of rows.
|
|
176
|
+
*
|
|
177
|
+
* @return {number}
|
|
178
|
+
*/
|
|
179
|
+
count() {
|
|
180
|
+
return this.getLimitedRows().length;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Checks if there is at least one row compatible with the query.
|
|
184
|
+
*
|
|
185
|
+
* @returns {boolean} Boolean indicating whether any row exists.
|
|
186
|
+
*/
|
|
187
|
+
exists() {
|
|
188
|
+
return this.count() > 0;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Returns the first result.
|
|
192
|
+
*
|
|
193
|
+
* @returns {T}
|
|
194
|
+
*/
|
|
195
|
+
first() {
|
|
196
|
+
const rows = this.getLimitedRows();
|
|
197
|
+
return rows.length ? rows[0] : null;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Returns the last result.
|
|
201
|
+
*
|
|
202
|
+
* @returns {T}
|
|
203
|
+
*/
|
|
204
|
+
last() {
|
|
205
|
+
const rows = this.getLimitedRows();
|
|
206
|
+
return rows[this.count() - 1] ?? null;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Returns all results.
|
|
210
|
+
*
|
|
211
|
+
* @returns {T[]}
|
|
212
|
+
*/
|
|
213
|
+
all() {
|
|
214
|
+
return this.getLimitedRows();
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Returns the value of the first (selected) column of the first row.
|
|
218
|
+
*
|
|
219
|
+
* @returns {T[Promise<T>]|false} First value or `false`, if none row exists.
|
|
220
|
+
*/
|
|
221
|
+
scalar() {
|
|
222
|
+
const firstObject = this.first();
|
|
223
|
+
const firstColumn = this.getFirstColumn();
|
|
224
|
+
return firstObject && firstColumn ? firstObject[firstColumn] ?? false : false;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Returns the values of the first (selected) column of all rows.
|
|
228
|
+
*
|
|
229
|
+
* @returns {T[Promise<T>][]} Values from the first (selected) column.
|
|
230
|
+
*/
|
|
231
|
+
column() {
|
|
232
|
+
const firstColumn = this.getFirstColumn();
|
|
233
|
+
if (!firstColumn) {
|
|
234
|
+
return [];
|
|
235
|
+
}
|
|
236
|
+
return this.getLimitedRows().map((row) => row[firstColumn]);
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Returns the values of the rows. If there are selected columns, only their
|
|
240
|
+
* values will be returned.
|
|
241
|
+
*
|
|
242
|
+
* @returns {T[PropOf<T>][][]} Array with the values of all rows.
|
|
243
|
+
*/
|
|
244
|
+
values() {
|
|
245
|
+
return this.getLimitedRows().map((row) => __classPrivateFieldGet(this, _Query_columns, "f").length ? __classPrivateFieldGet(this, _Query_columns, "f").map((column) => row[column]) : Object.values(row));
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Defines the number of rows to skip.
|
|
249
|
+
*
|
|
250
|
+
* @param {number} numberOfRows Numbers of rows to skip. Only non negative integer numbers
|
|
251
|
+
* are allowed.
|
|
252
|
+
*
|
|
253
|
+
* @returns {this} Current query.
|
|
254
|
+
*
|
|
255
|
+
* @throws {InvalidArgumentError} If the given number is less than 0.
|
|
256
|
+
*/
|
|
257
|
+
skip(numberOfRows) {
|
|
258
|
+
__classPrivateFieldSet(this, _Query_startAt, numberOfRows, "f");
|
|
259
|
+
return this;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Defines a limit for the number of results.
|
|
263
|
+
*
|
|
264
|
+
* @param {number} limit Limit of results. Only non negative integer numbers are allowed.
|
|
265
|
+
*
|
|
266
|
+
* @returns {this} Current query.
|
|
267
|
+
*
|
|
268
|
+
* @throws {InvalidArgumentError} If the given limit is less than 0.
|
|
269
|
+
*/
|
|
270
|
+
limit(limit) {
|
|
271
|
+
__classPrivateFieldSet(this, _Query_limit, limit, "f");
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Returns the rows that should be used in the final results.
|
|
276
|
+
*
|
|
277
|
+
* @returns {T[]} Rows within the specified limit.
|
|
278
|
+
*/
|
|
279
|
+
getLimitedRows() {
|
|
280
|
+
return __classPrivateFieldGet(this, _Query_rows, "f").slice(__classPrivateFieldGet(this, _Query_startAt, "f")).slice(0, __classPrivateFieldGet(this, _Query_limit, "f"));
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Returns the first selected column or the first key of some row.
|
|
284
|
+
*
|
|
285
|
+
* @returns {Promise<T>|null} The first column or `null`, if none is selected
|
|
286
|
+
* or there is no row.
|
|
287
|
+
*/
|
|
288
|
+
getFirstColumn() {
|
|
289
|
+
if (__classPrivateFieldGet(this, _Query_columns, "f").length) {
|
|
290
|
+
return __classPrivateFieldGet(this, _Query_columns, "f")[0];
|
|
291
|
+
}
|
|
292
|
+
const firstObject = this.first();
|
|
293
|
+
return firstObject ? Object.keys(firstObject)[0] : null;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Filters the rows according to the given conditions.
|
|
297
|
+
*
|
|
298
|
+
* @param {QueryConditionsGroupNullable<T> | ((obj: T) => boolean)} condition
|
|
299
|
+
* Object or callback function.
|
|
300
|
+
*/
|
|
301
|
+
filterRows(condition) {
|
|
302
|
+
const isCallbackValidator = (0, type_guards_1.isFunction)(condition);
|
|
303
|
+
__classPrivateFieldSet(this, _Query_rows, __classPrivateFieldGet(this, _Query_rows, "f").filter((row) => (isCallbackValidator ? condition(row) : this.validateRow(row, condition))), "f");
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Validates a row based on the given conditions object.
|
|
307
|
+
*
|
|
308
|
+
* @param {T} row Row to validate.
|
|
309
|
+
* @param {QueryConditionsGroupNullable<T>} condition Conditions object.
|
|
310
|
+
*
|
|
311
|
+
* @returns {boolean} Validation result.
|
|
312
|
+
*/
|
|
313
|
+
validateRow(row, condition) {
|
|
314
|
+
return query_row_validator_1.QueryRowValidator.validate(row, {
|
|
315
|
+
conditionsObject: condition,
|
|
316
|
+
ignoreNullValues: this.ignoreNullValues,
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
_Query_rows = new WeakMap(), _Query_columns = new WeakMap(), _Query_startAt = new WeakMap(), _Query_limit = new WeakMap();
|
|
321
|
+
__decorate([
|
|
322
|
+
number_validaton_1.validateNumbers,
|
|
323
|
+
__param(0, number_validaton_1.integer),
|
|
324
|
+
__param(0, (0, number_validaton_1.min)(0))
|
|
325
|
+
], Query.prototype, "skip", null);
|
|
326
|
+
__decorate([
|
|
327
|
+
number_validaton_1.validateNumbers,
|
|
328
|
+
__param(0, number_validaton_1.integer),
|
|
329
|
+
__param(0, (0, number_validaton_1.min)(0))
|
|
330
|
+
], Query.prototype, "limit", null);
|
|
331
|
+
exports.Query = Query;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
/**
|
|
3
|
+
* Sets a minimal value to be used as argument to the given parameter.
|
|
4
|
+
*
|
|
5
|
+
* @param {number} value Minimal value to set.
|
|
6
|
+
*
|
|
7
|
+
* @returns Decorator function.
|
|
8
|
+
*/
|
|
9
|
+
export declare function min(value: number): (target: object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
10
|
+
/**
|
|
11
|
+
* Sets a maximum value to be used as argument to the given parameter.
|
|
12
|
+
*
|
|
13
|
+
* @param {number} value Maximal value to set.
|
|
14
|
+
*
|
|
15
|
+
* @returns Decorator function.
|
|
16
|
+
*/
|
|
17
|
+
export declare function max(value: number): (target: object, propertyKey: string | symbol, parameterIndex: number) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Marks the given parameter as an integer.
|
|
20
|
+
*
|
|
21
|
+
* @param {Object} target Class to which the parameter belongs.
|
|
22
|
+
* @param {string} propertyKey Method name.
|
|
23
|
+
* @param {number} parameterIndex Parameter index.
|
|
24
|
+
*/
|
|
25
|
+
export declare function integer(target: object, propertyKey: string | symbol, parameterIndex: number): void;
|
|
26
|
+
/**
|
|
27
|
+
* Validates the property decorators `integer`, `min`, and `max`, throwing and error
|
|
28
|
+
* when the arguments passed to the parameters decorated by them are invalid.
|
|
29
|
+
*
|
|
30
|
+
* @param {any} target Class to which the method belongs.
|
|
31
|
+
* @param {string} propertyName Method name.
|
|
32
|
+
* @param {TypedPropertyDescriptor<any>} descriptor Descriptor object.
|
|
33
|
+
*
|
|
34
|
+
* @throws {InvalidArgumentError} If an argument is invalid.
|
|
35
|
+
*/
|
|
36
|
+
export declare function validateNumbers(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<any>): void;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateNumbers = exports.integer = exports.max = exports.min = void 0;
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const errors_1 = require("../../errors");
|
|
6
|
+
const type_guards_1 = require("../functions/type-guards");
|
|
7
|
+
const minMetadataKey = Symbol('min');
|
|
8
|
+
const maxMetadataKey = Symbol('max');
|
|
9
|
+
const integerMetadataKey = Symbol('integer');
|
|
10
|
+
/**
|
|
11
|
+
* Sets a minimal value to be used as argument to the given parameter.
|
|
12
|
+
*
|
|
13
|
+
* @param {number} value Minimal value to set.
|
|
14
|
+
*
|
|
15
|
+
* @returns Decorator function.
|
|
16
|
+
*/
|
|
17
|
+
function min(value) {
|
|
18
|
+
return (target, propertyKey, parameterIndex) => {
|
|
19
|
+
const minParameters = Reflect.getOwnMetadata(minMetadataKey, target, propertyKey) || [];
|
|
20
|
+
minParameters.push({
|
|
21
|
+
value,
|
|
22
|
+
index: parameterIndex,
|
|
23
|
+
});
|
|
24
|
+
Reflect.defineMetadata(minMetadataKey, minParameters, target, propertyKey);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
exports.min = min;
|
|
28
|
+
/**
|
|
29
|
+
* Sets a maximum value to be used as argument to the given parameter.
|
|
30
|
+
*
|
|
31
|
+
* @param {number} value Maximal value to set.
|
|
32
|
+
*
|
|
33
|
+
* @returns Decorator function.
|
|
34
|
+
*/
|
|
35
|
+
function max(value) {
|
|
36
|
+
return (target, propertyKey, parameterIndex) => {
|
|
37
|
+
const maxParameters = Reflect.getOwnMetadata(maxMetadataKey, target, propertyKey) || [];
|
|
38
|
+
maxParameters.push({
|
|
39
|
+
value,
|
|
40
|
+
index: parameterIndex,
|
|
41
|
+
});
|
|
42
|
+
Reflect.defineMetadata(maxMetadataKey, maxParameters, target, propertyKey);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
exports.max = max;
|
|
46
|
+
/**
|
|
47
|
+
* Marks the given parameter as an integer.
|
|
48
|
+
*
|
|
49
|
+
* @param {Object} target Class to which the parameter belongs.
|
|
50
|
+
* @param {string} propertyKey Method name.
|
|
51
|
+
* @param {number} parameterIndex Parameter index.
|
|
52
|
+
*/
|
|
53
|
+
function integer(target, propertyKey, parameterIndex) {
|
|
54
|
+
const integerParameters = Reflect.getOwnMetadata(integerMetadataKey, target, propertyKey) || [];
|
|
55
|
+
integerParameters.push({
|
|
56
|
+
index: parameterIndex,
|
|
57
|
+
});
|
|
58
|
+
Reflect.defineMetadata(integerMetadataKey, integerParameters, target, propertyKey);
|
|
59
|
+
}
|
|
60
|
+
exports.integer = integer;
|
|
61
|
+
/**
|
|
62
|
+
* Validates the property decorators `integer`, `min`, and `max`, throwing and error
|
|
63
|
+
* when the arguments passed to the parameters decorated by them are invalid.
|
|
64
|
+
*
|
|
65
|
+
* @param {any} target Class to which the method belongs.
|
|
66
|
+
* @param {string} propertyName Method name.
|
|
67
|
+
* @param {TypedPropertyDescriptor<any>} descriptor Descriptor object.
|
|
68
|
+
*
|
|
69
|
+
* @throws {InvalidArgumentError} If an argument is invalid.
|
|
70
|
+
*/
|
|
71
|
+
function validateNumbers(target, propertyName, descriptor) {
|
|
72
|
+
const method = descriptor.value;
|
|
73
|
+
descriptor.value = function () {
|
|
74
|
+
const minParams = Reflect.getOwnMetadata(minMetadataKey, target, propertyName) || [];
|
|
75
|
+
const maxParams = Reflect.getOwnMetadata(maxMetadataKey, target, propertyName) || [];
|
|
76
|
+
const integerParams = Reflect.getOwnMetadata(integerMetadataKey, target, propertyName) || [];
|
|
77
|
+
checkMinParams(propertyName, minParams, arguments);
|
|
78
|
+
checkMaxParams(propertyName, maxParams, arguments);
|
|
79
|
+
checkIntegerParams(propertyName, integerParams, arguments);
|
|
80
|
+
return method.apply(this, arguments);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
exports.validateNumbers = validateNumbers;
|
|
84
|
+
function checkMinParams(methodName, params, actualArguments) {
|
|
85
|
+
for (const parameter of params) {
|
|
86
|
+
const actualValue = actualArguments[parameter.index];
|
|
87
|
+
const minValue = parameter.value;
|
|
88
|
+
if (!(0, type_guards_1.isNumber)(actualValue) || actualValue < minValue) {
|
|
89
|
+
throw new errors_1.InvalidArgumentError({
|
|
90
|
+
method: methodName,
|
|
91
|
+
param: parameter.index,
|
|
92
|
+
argument: actualValue,
|
|
93
|
+
expected: `equal or greater than ${minValue}`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function checkMaxParams(methodName, params, actualArguments) {
|
|
99
|
+
for (const parameter of params) {
|
|
100
|
+
const actualValue = actualArguments[parameter.index];
|
|
101
|
+
const maxValue = parameter.value;
|
|
102
|
+
if (!(0, type_guards_1.isNumber)(actualValue) || actualValue > maxValue) {
|
|
103
|
+
throw new errors_1.InvalidArgumentError({
|
|
104
|
+
method: methodName,
|
|
105
|
+
param: parameter.index,
|
|
106
|
+
argument: actualValue,
|
|
107
|
+
expected: `equal or less than ${maxValue}`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function checkIntegerParams(methodName, params, actualArguments) {
|
|
113
|
+
for (const { index } of params) {
|
|
114
|
+
const actualValue = actualArguments[index];
|
|
115
|
+
if (!Number.isSafeInteger(actualValue)) {
|
|
116
|
+
throw new errors_1.InvalidArgumentError({
|
|
117
|
+
method: methodName,
|
|
118
|
+
param: index,
|
|
119
|
+
argument: actualValue,
|
|
120
|
+
expected: 'an integer',
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|