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.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +234 -0
  3. package/lib/base-object.d.ts +6 -0
  4. package/lib/base-object.js +15 -0
  5. package/lib/errors/index.d.ts +2 -0
  6. package/lib/errors/index.js +5 -0
  7. package/lib/errors/invalid-argument-error.d.ts +10 -0
  8. package/lib/errors/invalid-argument-error.js +11 -0
  9. package/lib/index.d.ts +2 -0
  10. package/lib/index.js +5 -0
  11. package/lib/query-conditions-group-nullable.d.ts +4 -0
  12. package/lib/query-conditions-group-nullable.js +2 -0
  13. package/lib/query-conditions-group.d.ts +4 -0
  14. package/lib/query-conditions-group.js +2 -0
  15. package/lib/query-row-validator.d.ts +72 -0
  16. package/lib/query-row-validator.js +85 -0
  17. package/lib/query.d.ts +215 -0
  18. package/lib/query.js +331 -0
  19. package/lib/utils/decorators/number-validaton.d.ts +36 -0
  20. package/lib/utils/decorators/number-validaton.js +124 -0
  21. package/lib/utils/functions/generic/compare-arrays.d.ts +9 -0
  22. package/lib/utils/functions/generic/compare-arrays.js +13 -0
  23. package/lib/utils/functions/generic/get-entries.d.ts +8 -0
  24. package/lib/utils/functions/generic/get-entries.js +12 -0
  25. package/lib/utils/functions/generic/index.d.ts +3 -0
  26. package/lib/utils/functions/generic/index.js +7 -0
  27. package/lib/utils/functions/sort/index.d.ts +3 -0
  28. package/lib/utils/functions/sort/index.js +7 -0
  29. package/lib/utils/functions/sort/sort-by-properties.d.ts +2 -0
  30. package/lib/utils/functions/sort/sort-by-properties.js +17 -0
  31. package/lib/utils/functions/sort/sort-by-property.d.ts +2 -0
  32. package/lib/utils/functions/sort/sort-by-property.js +15 -0
  33. package/lib/utils/functions/type-guards/index.d.ts +4 -0
  34. package/lib/utils/functions/type-guards/index.js +9 -0
  35. package/lib/utils/functions/type-guards/is-function.d.ts +8 -0
  36. package/lib/utils/functions/type-guards/is-function.js +12 -0
  37. package/lib/utils/functions/type-guards/is-number.d.ts +8 -0
  38. package/lib/utils/functions/type-guards/is-number.js +12 -0
  39. package/lib/utils/functions/type-guards/is-object.d.ts +8 -0
  40. package/lib/utils/functions/type-guards/is-object.js +12 -0
  41. package/lib/utils/types/add-prefix-to-object.d.ts +3 -0
  42. package/lib/utils/types/add-prefix-to-object.js +2 -0
  43. package/lib/utils/types/allowed-names.d.ts +5 -0
  44. package/lib/utils/types/allowed-names.js +2 -0
  45. package/lib/utils/types/flag-excluded-type.d.ts +6 -0
  46. package/lib/utils/types/flag-excluded-type.js +2 -0
  47. package/lib/utils/types/generic-object.d.ts +3 -0
  48. package/lib/utils/types/generic-object.js +3 -0
  49. package/lib/utils/types/index.d.ts +10 -0
  50. package/lib/utils/types/index.js +2 -0
  51. package/lib/utils/types/omit-type.d.ts +5 -0
  52. package/lib/utils/types/omit-type.js +2 -0
  53. package/lib/utils/types/partial-of-properties.d.ts +2 -0
  54. package/lib/utils/types/partial-of-properties.js +2 -0
  55. package/lib/utils/types/prop-of.d.ts +5 -0
  56. package/lib/utils/types/prop-of.js +2 -0
  57. package/lib/utils/types/property-only.d.ts +4 -0
  58. package/lib/utils/types/property-only.js +2 -0
  59. package/lib/utils/types/recursive-partial.d.ts +3 -0
  60. package/lib/utils/types/recursive-partial.js +2 -0
  61. package/lib/utils/types/type.d.ts +4 -0
  62. package/lib/utils/types/type.js +2 -0
  63. package/package.json +52 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Luiz Filipe da Silva
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,234 @@
1
+ # query-ts
2
+
3
+ A package that allows you to query data from an array of objects.
4
+
5
+ ## Introduction
6
+
7
+ The following data will be used in the samples of this documentation:
8
+
9
+ ```ts
10
+ interface UserPermissions {
11
+ useCookies: boolean;
12
+ sendNotifications: boolean;
13
+ }
14
+
15
+ class User {
16
+ id: number;
17
+ name: string;
18
+ permissions: UserPermissions;
19
+ isActive: boolean;
20
+ createdAt: Date;
21
+ updatedAt: Date;
22
+
23
+ isAdmin(): boolean {
24
+ ...
25
+ }
26
+ }
27
+
28
+ const users: User[] = [
29
+ ...
30
+ ];
31
+ ```
32
+
33
+ ## `Query`
34
+
35
+ A `Query` can be created this way:
36
+
37
+ ```ts
38
+ const usersQuery = Query.from(users);
39
+ ```
40
+
41
+ TypeScript will automatically assume that the query data type is `User`. You can make it explicit:
42
+
43
+ ```ts
44
+ const usersQuery = Query.from<User>(users);
45
+ ```
46
+
47
+ ### Getting results
48
+
49
+ #### `all()`
50
+
51
+ Returns all results.
52
+
53
+ #### `first()`
54
+
55
+ Returns the first result.
56
+
57
+ #### `last()`
58
+
59
+ Returns the last result.
60
+
61
+ #### `count()`
62
+
63
+ Returns the number of results.
64
+
65
+ #### `exists()`
66
+
67
+ Returns a boolean indicating whether any results exist.
68
+
69
+ ### Filtering data
70
+
71
+ #### `where(condition)`
72
+
73
+ There are two types of parameters:
74
+
75
+ 1. An object where each property represents an attribute to be validated.
76
+ 2. A callback function that returns a boolean validating the object.
77
+
78
+ When the condition is an object, you can pass literal values or callback functions to each attribute that needs to be validated.
79
+
80
+ ```ts
81
+ const activeGmailUsers = Query.from(users)
82
+ .where({
83
+ isActive: true,
84
+ email: (email) => email.endsWith('@gmail.com'),
85
+ })
86
+ .where((user) => (
87
+ !user.isAdmin()
88
+ ))
89
+ .all();
90
+ ```
91
+
92
+ It also works on inner objects:
93
+
94
+ ```ts
95
+ .where({
96
+ permissions: {
97
+ sendNotifications: true,
98
+ },
99
+ })
100
+ ```
101
+
102
+ #### `filterWhere(condition)`
103
+
104
+ The difference of `filterWhere` is that it only accepts an object and it ignores conditions whose values are `null` or `undefined`.
105
+
106
+ ```ts
107
+ let isActive: bool;
108
+
109
+ const filteredUsers = Query.from(users)
110
+ .filterWhere({
111
+ id: 1,
112
+ isActive: isActive, // this condition will be skipped
113
+ })
114
+ .all();
115
+ ```
116
+
117
+ >**Remember**: if you want to check if a value is really `null` or `undefined`, use `where()`.
118
+
119
+ ### Selecting specific data
120
+
121
+ #### `select(columns)`
122
+
123
+ This method can be combined with `scalar()`, `column()`, or `values()`. It determines which columns should be selected.
124
+
125
+ It accepts a string containing a single column name or an array of column names.
126
+
127
+ ```ts
128
+ .select('id')
129
+ ```
130
+
131
+ #### `scalar()`
132
+
133
+ It returns the value of the first property of the first object.
134
+
135
+ ```ts
136
+ const firstId = Query.from(users).scalar();
137
+ ```
138
+
139
+ As mentioned above, it is possible to combine it with `select()` in order to get the value of another property.
140
+
141
+ ```ts
142
+ const firstEmail = Query.from(users)
143
+ .select('email')
144
+ .scalar();
145
+ ```
146
+
147
+ `false` is returned where there is no value.
148
+
149
+ #### `column()`
150
+
151
+ It returns the values of the first properties of all objects.
152
+
153
+ ```ts
154
+ const ids = Query.from(users).column();
155
+ ```
156
+
157
+ You can also use it with `select()`:
158
+
159
+ ```ts
160
+ const emails = Query.from(users)
161
+ .select('email')
162
+ .column();
163
+ ```
164
+
165
+ #### `values()`
166
+
167
+ It returns the values of all objects as arrays.
168
+
169
+ ```ts
170
+ const data = Query.from(users)
171
+ .select(['id', 'email'])
172
+ .values();
173
+ ```
174
+
175
+ `data` would be something like this:
176
+
177
+ ```ts
178
+ [
179
+ [1, 'john@icloud.com'],
180
+ [2, 'mary@gmail.com']
181
+ ]
182
+ ```
183
+
184
+ ### Ordering results
185
+
186
+ #### `orderBy(...columns)`
187
+
188
+ Sorts the results. You can pass multiple arguments to it.
189
+
190
+ ```ts
191
+ .orderBy('name', 'id')
192
+ ```
193
+
194
+ In the example above, `name` will have more priority than `id`.
195
+
196
+ It is also possible to apply descending order:
197
+
198
+ ```ts
199
+ const lastId = Query.from(users)
200
+ .select('id')
201
+ .orderBy('-id')
202
+ .scalar();
203
+ ```
204
+
205
+ ### Limiting results
206
+
207
+ #### `limit(limit)`
208
+
209
+ This method can be used to set a limit of results.
210
+
211
+ ```ts
212
+ .limit(100)
213
+ ```
214
+
215
+ >Passing a float or a negative number will throw an `InvalidArgumentError`.
216
+
217
+ #### `skip(numberOfRows)`
218
+
219
+ Skips the first results.
220
+
221
+ ```ts
222
+ .skip(5)
223
+ ```
224
+
225
+ Example:
226
+
227
+ ```ts
228
+ const secondId = Query.from(users)
229
+ .select('id')
230
+ .skip(1) // skips the first user
231
+ .scalar();
232
+ ```
233
+
234
+ >Passing a float or a negative number will throw an `InvalidArgumentError`.
@@ -0,0 +1,6 @@
1
+ import { PartialOfProperties } from './utils/types';
2
+ export declare abstract class BaseObject {
3
+ constructor(init?: PartialOfProperties<BaseObject>);
4
+ setAttribute<K extends keyof this>(attribute: K, value: this[K]): void;
5
+ setAttributes(attributes: PartialOfProperties<this>): void;
6
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseObject = void 0;
4
+ class BaseObject {
5
+ constructor(init = {}) {
6
+ this.setAttributes(init);
7
+ }
8
+ setAttribute(attribute, value) {
9
+ this[attribute] = value;
10
+ }
11
+ setAttributes(attributes) {
12
+ Object.assign(this, attributes);
13
+ }
14
+ }
15
+ exports.BaseObject = BaseObject;
@@ -0,0 +1,2 @@
1
+ import { InvalidArgumentError } from './invalid-argument-error';
2
+ export { InvalidArgumentError, };
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvalidArgumentError = void 0;
4
+ const invalid_argument_error_1 = require("./invalid-argument-error");
5
+ Object.defineProperty(exports, "InvalidArgumentError", { enumerable: true, get: function () { return invalid_argument_error_1.InvalidArgumentError; } });
@@ -0,0 +1,10 @@
1
+ interface InvalidArgumentErrorConfig {
2
+ method: string;
3
+ param: string | number;
4
+ argument: any;
5
+ expected: string;
6
+ }
7
+ export declare class InvalidArgumentError extends Error {
8
+ constructor({ method, param, argument, expected }: InvalidArgumentErrorConfig);
9
+ }
10
+ export {};
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InvalidArgumentError = void 0;
4
+ class InvalidArgumentError extends Error {
5
+ constructor({ method, param, argument, expected }) {
6
+ super(`${argument} is not a valid argument to param ${param} on ${method}(). ` +
7
+ `It should be ${expected}.`);
8
+ this.name = 'InvalidArgumentError';
9
+ }
10
+ }
11
+ exports.InvalidArgumentError = InvalidArgumentError;
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import { Query } from './query';
2
+ export { Query };
package/lib/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Query = void 0;
4
+ const query_1 = require("./query");
5
+ Object.defineProperty(exports, "Query", { enumerable: true, get: function () { return query_1.Query; } });
@@ -0,0 +1,4 @@
1
+ import { PropertyOnly } from './utils/types';
2
+ export declare type QueryConditionsGroupNullable<T extends object> = {
3
+ [P in keyof PropertyOnly<T>]?: T[P] extends object ? QueryConditionsGroupNullable<T[P]> : T[P] | ((value: T[P]) => boolean) | null;
4
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ import { PropertyOnly } from './utils/types';
2
+ export declare type QueryConditionsGroup<T extends object> = {
3
+ [P in keyof PropertyOnly<T>]?: T[P] extends object ? QueryConditionsGroup<T[P]> : T[P] | ((value: T[P]) => boolean);
4
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,72 @@
1
+ import { BaseObject } from './base-object';
2
+ import { QueryConditionsGroupNullable } from './query-conditions-group-nullable';
3
+ /**
4
+ * Validator configuration.
5
+ */
6
+ interface QueryRowValidatorInitializer<T extends object> {
7
+ conditionsObject: QueryConditionsGroupNullable<T>;
8
+ ignoreNullValues: boolean;
9
+ }
10
+ /**
11
+ * Validates a row in the query.
12
+ */
13
+ export declare class QueryRowValidator<T extends object> extends BaseObject {
14
+ /**
15
+ * Row to be validated.
16
+ */
17
+ private row;
18
+ /**
19
+ * Conditions to be applied to the row.
20
+ */
21
+ private conditionsObject;
22
+ /**
23
+ * Indicates whether conditions with `null` and `undefined` values should be
24
+ * skipped.
25
+ */
26
+ private ignoreNullValues;
27
+ /**
28
+ * Initializes the validator.
29
+ *
30
+ * @param {T} row Row to validated.
31
+ * @param {QueryRowValidatorInitializer<T>} config Validator configuration.
32
+ */
33
+ private constructor();
34
+ /**
35
+ * Validates a row.
36
+ *
37
+ * @param {T} row Row to validated.
38
+ * @param {QueryRowValidatorInitializer<T>} config Validator configuration.
39
+ */
40
+ static validate<T extends object>(row: T, config: QueryRowValidatorInitializer<T>): boolean;
41
+ /**
42
+ * Applies the validation to the row.
43
+ *
44
+ * @returns {boolean} `true` if the row is valid, `false` otherwise.
45
+ */
46
+ private validate;
47
+ /**
48
+ * Validates every condition.
49
+ *
50
+ * @returns {boolean} Validation result.
51
+ */
52
+ private validateConditions;
53
+ /**
54
+ * Validate a condition to a specific column.
55
+ *
56
+ * @param {P} columnName Column name.
57
+ * @param {ColumnCondition<T, P>} condition Condition to be validated.
58
+ *
59
+ * @returns {boolean} Validation result.
60
+ */
61
+ private validateColumnCondition;
62
+ /**
63
+ * Validates an object inside the row.
64
+ *
65
+ * @param {object} obj Object to validated.
66
+ * @param {QueryConditionsGroupNullable<O>} conditionsObject Conditions to be applied to the object.
67
+ *
68
+ * @returns {boolean} Validation result.
69
+ */
70
+ private validateInnerObject;
71
+ }
72
+ export {};
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QueryRowValidator = void 0;
4
+ const base_object_1 = require("./base-object");
5
+ const generic_1 = require("./utils/functions/generic");
6
+ const type_guards_1 = require("./utils/functions/type-guards");
7
+ /**
8
+ * Validates a row in the query.
9
+ */
10
+ class QueryRowValidator extends base_object_1.BaseObject {
11
+ /**
12
+ * Initializes the validator.
13
+ *
14
+ * @param {T} row Row to validated.
15
+ * @param {QueryRowValidatorInitializer<T>} config Validator configuration.
16
+ */
17
+ constructor(row, config) {
18
+ super({ row, ...config });
19
+ }
20
+ /**
21
+ * Validates a row.
22
+ *
23
+ * @param {T} row Row to validated.
24
+ * @param {QueryRowValidatorInitializer<T>} config Validator configuration.
25
+ */
26
+ static validate(row, config) {
27
+ return new QueryRowValidator(row, config).validate();
28
+ }
29
+ /**
30
+ * Applies the validation to the row.
31
+ *
32
+ * @returns {boolean} `true` if the row is valid, `false` otherwise.
33
+ */
34
+ validate() {
35
+ return this.validateConditions();
36
+ }
37
+ /**
38
+ * Validates every condition.
39
+ *
40
+ * @returns {boolean} Validation result.
41
+ */
42
+ validateConditions() {
43
+ const conditionsEntries = (0, generic_1.getEntries)(this.conditionsObject);
44
+ return conditionsEntries.every(([columnName, condition]) => this.validateColumnCondition(columnName, condition));
45
+ }
46
+ /**
47
+ * Validate a condition to a specific column.
48
+ *
49
+ * @param {P} columnName Column name.
50
+ * @param {ColumnCondition<T, P>} condition Condition to be validated.
51
+ *
52
+ * @returns {boolean} Validation result.
53
+ */
54
+ validateColumnCondition(columnName, condition) {
55
+ if (this.ignoreNullValues && (condition === null || condition === undefined)) {
56
+ return true;
57
+ }
58
+ const cellValue = this.row[columnName];
59
+ if ((0, type_guards_1.isFunction)(condition)) {
60
+ return condition(cellValue);
61
+ }
62
+ if (Array.isArray(condition)) {
63
+ return Array.isArray(cellValue) ? (0, generic_1.compareArrays)(cellValue, condition) : false;
64
+ }
65
+ if ((0, type_guards_1.isObject)(condition)) {
66
+ return (0, type_guards_1.isObject)(cellValue) ? this.validateInnerObject(cellValue, condition) : false;
67
+ }
68
+ return cellValue === condition;
69
+ }
70
+ /**
71
+ * Validates an object inside the row.
72
+ *
73
+ * @param {object} obj Object to validated.
74
+ * @param {QueryConditionsGroupNullable<O>} conditionsObject Conditions to be applied to the object.
75
+ *
76
+ * @returns {boolean} Validation result.
77
+ */
78
+ validateInnerObject(obj, conditionsObject) {
79
+ return QueryRowValidator.validate(obj, {
80
+ conditionsObject,
81
+ ignoreNullValues: this.ignoreNullValues,
82
+ });
83
+ }
84
+ }
85
+ exports.QueryRowValidator = QueryRowValidator;