querier-ts 0.0.0 → 1.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/lib/__tests__/query.spec.d.ts +1 -0
- package/lib/__tests__/query.spec.js +149 -0
- package/lib/core/errors/__tests__/invalid-argument-error.spec.d.ts +1 -0
- package/lib/core/errors/__tests__/invalid-argument-error.spec.js +54 -0
- package/lib/core/errors/index.d.ts +1 -0
- package/lib/core/errors/index.js +17 -0
- package/lib/core/errors/invalid-argument-error.d.ts +14 -0
- package/lib/core/errors/invalid-argument-error.js +16 -0
- package/lib/core/types/attribute-validation-function.d.ts +1 -0
- package/lib/core/types/attribute-validation-function.js +2 -0
- package/lib/core/types/column-condition.d.ts +6 -0
- package/lib/core/types/column-condition.js +2 -0
- package/lib/core/types/index.d.ts +4 -0
- package/lib/core/types/index.js +20 -0
- package/lib/core/types/query-conditions-group-nullable.d.ts +4 -0
- package/lib/core/types/query-conditions-group-nullable.js +2 -0
- package/lib/core/types/query-conditions-group.d.ts +4 -0
- package/lib/core/types/query-conditions-group.js +2 -0
- package/lib/core/types/query-row-validator-initializer.d.ts +8 -0
- package/lib/core/types/query-row-validator-initializer.js +2 -0
- package/lib/core/validation/__tests__/query-row-validator.spec.d.ts +1 -0
- package/lib/core/validation/__tests__/query-row-validator.spec.js +195 -0
- package/lib/core/validation/decorators/__tests__/number-validation.spec.d.ts +1 -0
- package/lib/core/validation/decorators/__tests__/number-validation.spec.js +114 -0
- package/lib/core/validation/decorators/index.d.ts +1 -0
- package/lib/core/validation/decorators/index.js +17 -0
- package/lib/core/validation/decorators/number-validaton.d.ts +36 -0
- package/lib/core/validation/decorators/number-validaton.js +123 -0
- package/lib/core/validation/index.d.ts +1 -0
- package/lib/core/validation/index.js +17 -0
- package/lib/core/validation/query-row-validator.d.ts +57 -0
- package/lib/core/validation/query-row-validator.js +84 -0
- package/lib/index.d.ts +1 -2
- package/lib/index.js +15 -3
- package/lib/query.d.ts +33 -38
- package/lib/query.js +51 -50
- package/lib/utils/functions/generic/__tests__/compare-arrays.spec.d.ts +1 -0
- package/lib/utils/functions/generic/__tests__/compare-arrays.spec.js +21 -0
- package/lib/utils/functions/generic/__tests__/deep-equal.spec.d.ts +1 -0
- package/lib/utils/functions/generic/__tests__/deep-equal.spec.js +82 -0
- package/lib/utils/functions/generic/__tests__/get-entries.spec.d.ts +1 -0
- package/lib/utils/functions/generic/__tests__/get-entries.spec.js +55 -0
- package/lib/utils/functions/generic/compare-arrays.d.ts +1 -9
- package/lib/utils/functions/generic/compare-arrays.js +2 -9
- package/lib/utils/functions/generic/deep-equal.d.ts +1 -0
- package/lib/utils/functions/generic/deep-equal.js +23 -0
- package/lib/utils/functions/generic/get-entries.d.ts +5 -8
- package/lib/utils/functions/generic/get-entries.js +7 -9
- package/lib/utils/functions/generic/index.d.ts +3 -3
- package/lib/utils/functions/generic/index.js +17 -5
- package/lib/utils/functions/sort/__tests__/sort-by-properties.spec.d.ts +1 -0
- package/lib/utils/functions/sort/__tests__/sort-by-properties.spec.js +69 -0
- package/lib/utils/functions/sort/__tests__/sort-by-property.spec.d.ts +1 -0
- package/lib/utils/functions/sort/__tests__/sort-by-property.spec.js +63 -0
- package/lib/utils/functions/sort/index.d.ts +2 -3
- package/lib/utils/functions/sort/index.js +16 -5
- package/lib/utils/functions/sort/sort-by-properties.d.ts +2 -2
- package/lib/utils/functions/sort/sort-by-properties.js +11 -9
- package/lib/utils/functions/sort/sort-by-property.d.ts +2 -2
- package/lib/utils/functions/sort/sort-by-property.js +18 -6
- package/lib/utils/functions/type-guards/__tests__/is-function.spec.d.ts +1 -0
- package/lib/utils/functions/type-guards/__tests__/is-function.spec.js +38 -0
- package/lib/utils/functions/type-guards/__tests__/is-number.spec.d.ts +1 -0
- package/lib/utils/functions/type-guards/__tests__/is-number.spec.js +35 -0
- package/lib/utils/functions/type-guards/__tests__/is-object.spec.d.ts +1 -0
- package/lib/utils/functions/type-guards/__tests__/is-object.spec.js +38 -0
- package/lib/utils/functions/type-guards/index.d.ts +3 -4
- package/lib/utils/functions/type-guards/index.js +17 -7
- package/lib/utils/functions/type-guards/is-function.d.ts +3 -3
- package/lib/utils/functions/type-guards/is-function.js +2 -2
- package/lib/utils/functions/type-guards/is-number.d.ts +3 -3
- package/lib/utils/functions/type-guards/is-number.js +2 -2
- package/lib/utils/functions/type-guards/is-object.d.ts +3 -3
- package/lib/utils/functions/type-guards/is-object.js +2 -2
- package/lib/utils/types/add-prefix-to-object.d.ts +1 -1
- package/lib/utils/types/allowed-names.d.ts +1 -1
- package/lib/utils/types/flag-excluded-type.d.ts +1 -1
- package/lib/utils/types/generic-object.d.ts +1 -1
- package/lib/utils/types/generic-object.js +0 -1
- package/lib/utils/types/index.d.ts +9 -10
- package/lib/utils/types/index.js +23 -0
- package/lib/utils/types/omit-type.d.ts +1 -1
- package/lib/utils/types/partial-of-properties.d.ts +1 -1
- package/lib/utils/types/prop-of.d.ts +1 -1
- package/lib/utils/types/property-only.d.ts +1 -1
- package/lib/utils/types/recursive-partial.d.ts +1 -1
- package/lib/utils/types/type.d.ts +1 -1
- package/package.json +23 -24
package/lib/query.js
CHANGED
|
@@ -22,10 +22,10 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
22
22
|
var _Query_rows, _Query_columns, _Query_startAt, _Query_limit;
|
|
23
23
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
24
|
exports.Query = void 0;
|
|
25
|
+
const validation_1 = require("./core/validation");
|
|
26
|
+
const decorators_1 = require("./core/validation/decorators");
|
|
25
27
|
const sort_1 = require("./utils/functions/sort");
|
|
26
28
|
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
29
|
/**
|
|
30
30
|
* Allows filtering data from an array of objects.
|
|
31
31
|
*
|
|
@@ -76,7 +76,7 @@ class Query {
|
|
|
76
76
|
/**
|
|
77
77
|
* Initializes the query.
|
|
78
78
|
*
|
|
79
|
-
* @param
|
|
79
|
+
* @param rows Rows to be queried.
|
|
80
80
|
*/
|
|
81
81
|
constructor(rows) {
|
|
82
82
|
/**
|
|
@@ -105,9 +105,9 @@ class Query {
|
|
|
105
105
|
/**
|
|
106
106
|
* Creates a new query based on the given data.
|
|
107
107
|
*
|
|
108
|
-
* @param
|
|
108
|
+
* @param rows Rows to be queried.
|
|
109
109
|
*
|
|
110
|
-
* @returns
|
|
110
|
+
* @returns Query to the given rows.
|
|
111
111
|
*/
|
|
112
112
|
static from(rows) {
|
|
113
113
|
return new Query(rows);
|
|
@@ -115,9 +115,9 @@ class Query {
|
|
|
115
115
|
/**
|
|
116
116
|
* Defines specific columns to be returned on the final results.
|
|
117
117
|
*
|
|
118
|
-
* @param
|
|
118
|
+
* @param columns Selected columns.
|
|
119
119
|
*
|
|
120
|
-
* @returns
|
|
120
|
+
* @returns Current query.
|
|
121
121
|
*/
|
|
122
122
|
select(columns) {
|
|
123
123
|
__classPrivateFieldSet(this, _Query_columns, Array.isArray(columns) ? columns : [columns], "f");
|
|
@@ -126,8 +126,7 @@ class Query {
|
|
|
126
126
|
/**
|
|
127
127
|
* Applies conditions to the query.
|
|
128
128
|
*
|
|
129
|
-
* @param
|
|
130
|
-
* be applied to the query.
|
|
129
|
+
* @param condition Filter to be applied to the query.
|
|
131
130
|
*
|
|
132
131
|
* If a callback function is provided, it must return a boolean value.
|
|
133
132
|
*
|
|
@@ -135,7 +134,7 @@ class Query {
|
|
|
135
134
|
* corresponding values must be the expected values for the attributes or a
|
|
136
135
|
* callback functions that return boolean values.
|
|
137
136
|
*
|
|
138
|
-
* @returns
|
|
137
|
+
* @returns Current query.
|
|
139
138
|
*/
|
|
140
139
|
where(condition) {
|
|
141
140
|
this.filterRows(condition);
|
|
@@ -145,12 +144,12 @@ class Query {
|
|
|
145
144
|
* Applies a set of conditions to the query ignoring `null` and `undefined`
|
|
146
145
|
* values as conditions.
|
|
147
146
|
*
|
|
148
|
-
* @param
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
*
|
|
147
|
+
* @param condition An object where each property represents an attribute
|
|
148
|
+
* to be validated. The values can be literal or callback functions that
|
|
149
|
+
* return a boolean. If `null` or `undefined` is passed, that condition
|
|
150
|
+
* will be skipped.
|
|
152
151
|
*
|
|
153
|
-
* @returns
|
|
152
|
+
* @returns Current query.
|
|
154
153
|
*/
|
|
155
154
|
filterWhere(condition) {
|
|
156
155
|
this.ignoreNullValues = true;
|
|
@@ -161,11 +160,10 @@ class Query {
|
|
|
161
160
|
/**
|
|
162
161
|
* Adds ordering to the results.
|
|
163
162
|
*
|
|
164
|
-
* @param
|
|
165
|
-
*
|
|
166
|
-
* its name.
|
|
163
|
+
* @param columns Ascending or descending columns. To mark a field as
|
|
164
|
+
* descending, use `-` before its name.
|
|
167
165
|
*
|
|
168
|
-
* @returns
|
|
166
|
+
* @returns Current query.
|
|
169
167
|
*/
|
|
170
168
|
orderBy(...columns) {
|
|
171
169
|
__classPrivateFieldGet(this, _Query_rows, "f").sort((0, sort_1.sortByProperties)(...columns));
|
|
@@ -174,7 +172,7 @@ class Query {
|
|
|
174
172
|
/**
|
|
175
173
|
* Returns the current number of rows.
|
|
176
174
|
*
|
|
177
|
-
* @return
|
|
175
|
+
* @return Filtered rows count.
|
|
178
176
|
*/
|
|
179
177
|
count() {
|
|
180
178
|
return this.getLimitedRows().length;
|
|
@@ -182,7 +180,7 @@ class Query {
|
|
|
182
180
|
/**
|
|
183
181
|
* Checks if there is at least one row compatible with the query.
|
|
184
182
|
*
|
|
185
|
-
* @returns
|
|
183
|
+
* @returns Whether any row exists after filtering.
|
|
186
184
|
*/
|
|
187
185
|
exists() {
|
|
188
186
|
return this.count() > 0;
|
|
@@ -190,7 +188,7 @@ class Query {
|
|
|
190
188
|
/**
|
|
191
189
|
* Returns the first result.
|
|
192
190
|
*
|
|
193
|
-
* @returns
|
|
191
|
+
* @returns The first result.
|
|
194
192
|
*/
|
|
195
193
|
first() {
|
|
196
194
|
const rows = this.getLimitedRows();
|
|
@@ -199,7 +197,7 @@ class Query {
|
|
|
199
197
|
/**
|
|
200
198
|
* Returns the last result.
|
|
201
199
|
*
|
|
202
|
-
* @returns
|
|
200
|
+
* @returns The last result.
|
|
203
201
|
*/
|
|
204
202
|
last() {
|
|
205
203
|
const rows = this.getLimitedRows();
|
|
@@ -208,7 +206,7 @@ class Query {
|
|
|
208
206
|
/**
|
|
209
207
|
* Returns all results.
|
|
210
208
|
*
|
|
211
|
-
* @returns
|
|
209
|
+
* @returns All filtered rows.
|
|
212
210
|
*/
|
|
213
211
|
all() {
|
|
214
212
|
return this.getLimitedRows();
|
|
@@ -216,17 +214,19 @@ class Query {
|
|
|
216
214
|
/**
|
|
217
215
|
* Returns the value of the first (selected) column of the first row.
|
|
218
216
|
*
|
|
219
|
-
* @returns
|
|
217
|
+
* @returns First value or `false`, if none row exists.
|
|
220
218
|
*/
|
|
221
219
|
scalar() {
|
|
222
220
|
const firstObject = this.first();
|
|
223
221
|
const firstColumn = this.getFirstColumn();
|
|
224
|
-
return firstObject && firstColumn
|
|
222
|
+
return firstObject && firstColumn
|
|
223
|
+
? (firstObject[firstColumn] ?? false)
|
|
224
|
+
: false;
|
|
225
225
|
}
|
|
226
226
|
/**
|
|
227
227
|
* Returns the values of the first (selected) column of all rows.
|
|
228
228
|
*
|
|
229
|
-
* @returns
|
|
229
|
+
* @returns Values from the first (selected) column.
|
|
230
230
|
*/
|
|
231
231
|
column() {
|
|
232
232
|
const firstColumn = this.getFirstColumn();
|
|
@@ -239,18 +239,20 @@ class Query {
|
|
|
239
239
|
* Returns the values of the rows. If there are selected columns, only their
|
|
240
240
|
* values will be returned.
|
|
241
241
|
*
|
|
242
|
-
* @returns
|
|
242
|
+
* @returns Array with the values of all rows.
|
|
243
243
|
*/
|
|
244
244
|
values() {
|
|
245
|
-
return this.getLimitedRows().map((row) => __classPrivateFieldGet(this, _Query_columns, "f").length
|
|
245
|
+
return this.getLimitedRows().map((row) => __classPrivateFieldGet(this, _Query_columns, "f").length
|
|
246
|
+
? __classPrivateFieldGet(this, _Query_columns, "f").map((column) => row[column])
|
|
247
|
+
: Object.values(row));
|
|
246
248
|
}
|
|
247
249
|
/**
|
|
248
250
|
* Defines the number of rows to skip.
|
|
249
251
|
*
|
|
250
|
-
* @param
|
|
252
|
+
* @param numberOfRows Numbers of rows to skip. Only non negative integer numbers
|
|
251
253
|
* are allowed.
|
|
252
254
|
*
|
|
253
|
-
* @returns
|
|
255
|
+
* @returns Current query.
|
|
254
256
|
*
|
|
255
257
|
* @throws {InvalidArgumentError} If the given number is less than 0.
|
|
256
258
|
*/
|
|
@@ -261,9 +263,9 @@ class Query {
|
|
|
261
263
|
/**
|
|
262
264
|
* Defines a limit for the number of results.
|
|
263
265
|
*
|
|
264
|
-
* @param
|
|
266
|
+
* @param limit Limit of results. Only non negative integer numbers are allowed.
|
|
265
267
|
*
|
|
266
|
-
* @returns
|
|
268
|
+
* @returns Current query.
|
|
267
269
|
*
|
|
268
270
|
* @throws {InvalidArgumentError} If the given limit is less than 0.
|
|
269
271
|
*/
|
|
@@ -274,7 +276,7 @@ class Query {
|
|
|
274
276
|
/**
|
|
275
277
|
* Returns the rows that should be used in the final results.
|
|
276
278
|
*
|
|
277
|
-
* @returns
|
|
279
|
+
* @returns Rows within the specified limit.
|
|
278
280
|
*/
|
|
279
281
|
getLimitedRows() {
|
|
280
282
|
return __classPrivateFieldGet(this, _Query_rows, "f").slice(__classPrivateFieldGet(this, _Query_startAt, "f")).slice(0, __classPrivateFieldGet(this, _Query_limit, "f"));
|
|
@@ -282,8 +284,7 @@ class Query {
|
|
|
282
284
|
/**
|
|
283
285
|
* Returns the first selected column or the first key of some row.
|
|
284
286
|
*
|
|
285
|
-
* @returns
|
|
286
|
-
* or there is no row.
|
|
287
|
+
* @returns The first column or `null`, if none is selected or there is no row.
|
|
287
288
|
*/
|
|
288
289
|
getFirstColumn() {
|
|
289
290
|
if (__classPrivateFieldGet(this, _Query_columns, "f").length) {
|
|
@@ -295,37 +296,37 @@ class Query {
|
|
|
295
296
|
/**
|
|
296
297
|
* Filters the rows according to the given conditions.
|
|
297
298
|
*
|
|
298
|
-
* @param
|
|
299
|
-
* Object or callback function.
|
|
299
|
+
* @param condition Object or callback function.
|
|
300
300
|
*/
|
|
301
301
|
filterRows(condition) {
|
|
302
|
-
|
|
303
|
-
|
|
302
|
+
__classPrivateFieldSet(this, _Query_rows, __classPrivateFieldGet(this, _Query_rows, "f").filter((row) => (0, type_guards_1.isFunction)(condition)
|
|
303
|
+
? condition(row)
|
|
304
|
+
: this.validateRow(row, condition)), "f");
|
|
304
305
|
}
|
|
305
306
|
/**
|
|
306
307
|
* Validates a row based on the given conditions object.
|
|
307
308
|
*
|
|
308
|
-
* @param
|
|
309
|
-
* @param
|
|
309
|
+
* @param row Row to validate.
|
|
310
|
+
* @param condition Conditions object.
|
|
310
311
|
*
|
|
311
312
|
* @returns {boolean} Validation result.
|
|
312
313
|
*/
|
|
313
314
|
validateRow(row, condition) {
|
|
314
|
-
return
|
|
315
|
+
return validation_1.QueryRowValidator.validate(row, {
|
|
315
316
|
conditionsObject: condition,
|
|
316
317
|
ignoreNullValues: this.ignoreNullValues,
|
|
317
318
|
});
|
|
318
319
|
}
|
|
319
320
|
}
|
|
321
|
+
exports.Query = Query;
|
|
320
322
|
_Query_rows = new WeakMap(), _Query_columns = new WeakMap(), _Query_startAt = new WeakMap(), _Query_limit = new WeakMap();
|
|
321
323
|
__decorate([
|
|
322
|
-
|
|
323
|
-
__param(0,
|
|
324
|
-
__param(0, (0,
|
|
324
|
+
decorators_1.validateNumbers,
|
|
325
|
+
__param(0, decorators_1.integer),
|
|
326
|
+
__param(0, (0, decorators_1.min)(0))
|
|
325
327
|
], Query.prototype, "skip", null);
|
|
326
328
|
__decorate([
|
|
327
|
-
|
|
328
|
-
__param(0,
|
|
329
|
-
__param(0, (0,
|
|
329
|
+
decorators_1.validateNumbers,
|
|
330
|
+
__param(0, decorators_1.integer),
|
|
331
|
+
__param(0, (0, decorators_1.min)(0))
|
|
330
332
|
], Query.prototype, "limit", null);
|
|
331
|
-
exports.Query = Query;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const compare_arrays_1 = require("../compare-arrays");
|
|
4
|
+
describe('compareArrays', () => {
|
|
5
|
+
it('returns true for ly equal arrays', () => {
|
|
6
|
+
const a = [{ x: 1 }, { y: 2 }];
|
|
7
|
+
const b = [{ x: 1 }, { y: 2 }];
|
|
8
|
+
expect((0, compare_arrays_1.compareArrays)(a, b)).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
it('returns false for ly different arrays', () => {
|
|
11
|
+
expect((0, compare_arrays_1.compareArrays)([{ x: 1 }], [{ x: 2 }])).toBe(false);
|
|
12
|
+
});
|
|
13
|
+
it('returns false when order differs', () => {
|
|
14
|
+
expect((0, compare_arrays_1.compareArrays)([{ a: 1 }, { b: 2 }], [{ b: 2 }, { a: 1 }])).toBe(false);
|
|
15
|
+
});
|
|
16
|
+
it('works with nested objects', () => {
|
|
17
|
+
const a = [{ x: { y: 1 } }];
|
|
18
|
+
const b = [{ x: { y: 1 } }];
|
|
19
|
+
expect((0, compare_arrays_1.compareArrays)(a, b)).toBe(true);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const deep_equal_1 = require("../deep-equal");
|
|
4
|
+
describe('deepEqual', () => {
|
|
5
|
+
describe('primitive values', () => {
|
|
6
|
+
it('returns true for strictly equal primitives', () => {
|
|
7
|
+
expect((0, deep_equal_1.deepEqual)(1, 1)).toBe(true);
|
|
8
|
+
expect((0, deep_equal_1.deepEqual)('a', 'a')).toBe(true);
|
|
9
|
+
expect((0, deep_equal_1.deepEqual)(true, true)).toBe(true);
|
|
10
|
+
expect((0, deep_equal_1.deepEqual)(null, null)).toBe(true);
|
|
11
|
+
expect((0, deep_equal_1.deepEqual)(undefined, undefined)).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
it('returns false for different primitive values', () => {
|
|
14
|
+
expect((0, deep_equal_1.deepEqual)(1, 2)).toBe(false);
|
|
15
|
+
expect((0, deep_equal_1.deepEqual)('a', 'b')).toBe(false);
|
|
16
|
+
expect((0, deep_equal_1.deepEqual)(true, false)).toBe(false);
|
|
17
|
+
expect((0, deep_equal_1.deepEqual)(null, undefined)).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe('objects', () => {
|
|
21
|
+
it('returns true for deeply equal plain objects', () => {
|
|
22
|
+
const a = { x: 1, y: 2 };
|
|
23
|
+
const b = { x: 1, y: 2 };
|
|
24
|
+
expect((0, deep_equal_1.deepEqual)(a, b)).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
it('returns false for objects with different keys', () => {
|
|
27
|
+
expect((0, deep_equal_1.deepEqual)({ x: 1 }, { y: 1 })).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
it('returns false for objects with same keys but different values', () => {
|
|
30
|
+
expect((0, deep_equal_1.deepEqual)({ x: 1 }, { x: 2 })).toBe(false);
|
|
31
|
+
});
|
|
32
|
+
it('returns false when one object has extra keys', () => {
|
|
33
|
+
expect((0, deep_equal_1.deepEqual)({ x: 1 }, { x: 1, y: 2 })).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe('nested structures', () => {
|
|
37
|
+
it('returns true for deeply nested objects', () => {
|
|
38
|
+
const a = { x: { y: { z: 1 } } };
|
|
39
|
+
const b = { x: { y: { z: 1 } } };
|
|
40
|
+
expect((0, deep_equal_1.deepEqual)(a, b)).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
it('returns false for deeply nested differences', () => {
|
|
43
|
+
const a = { x: { y: { z: 1 } } };
|
|
44
|
+
const b = { x: { y: { z: 2 } } };
|
|
45
|
+
expect((0, deep_equal_1.deepEqual)(a, b)).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe('arrays', () => {
|
|
49
|
+
it('returns true for deeply equal arrays', () => {
|
|
50
|
+
expect((0, deep_equal_1.deepEqual)([1, 2, 3], [1, 2, 3])).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
it('returns false for arrays with different order', () => {
|
|
53
|
+
expect((0, deep_equal_1.deepEqual)([1, 2, 3], [3, 2, 1])).toBe(false);
|
|
54
|
+
});
|
|
55
|
+
it('returns true for arrays with nested objects', () => {
|
|
56
|
+
const a = [{ x: 1 }, { y: 2 }];
|
|
57
|
+
const b = [{ x: 1 }, { y: 2 }];
|
|
58
|
+
expect((0, deep_equal_1.deepEqual)(a, b)).toBe(true);
|
|
59
|
+
});
|
|
60
|
+
it('returns false for arrays with different lengths', () => {
|
|
61
|
+
expect((0, deep_equal_1.deepEqual)([1, 2], [1, 2, 3])).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe('mixed and edge cases', () => {
|
|
65
|
+
it('returns false when comparing array and object', () => {
|
|
66
|
+
expect((0, deep_equal_1.deepEqual)([], {})).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
it('returns false when one value is object and the other is primitive', () => {
|
|
69
|
+
expect((0, deep_equal_1.deepEqual)({ x: 1 }, 1)).toBe(false);
|
|
70
|
+
});
|
|
71
|
+
it('returns true for same object reference', () => {
|
|
72
|
+
const obj = { x: 1 };
|
|
73
|
+
expect((0, deep_equal_1.deepEqual)(obj, obj)).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
it('returns false for Date objects with same value (by design)', () => {
|
|
76
|
+
const a = new Date(2020, 1, 1);
|
|
77
|
+
const b = new Date(2020, 1, 1);
|
|
78
|
+
// Date has no enumerable keys, so this documents the limitation
|
|
79
|
+
expect((0, deep_equal_1.deepEqual)(a, b)).toBe(true);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const get_entries_1 = require("../get-entries");
|
|
4
|
+
describe('getEntries', () => {
|
|
5
|
+
it('should return entries for a simple object', () => {
|
|
6
|
+
const obj = {
|
|
7
|
+
a: 1,
|
|
8
|
+
b: 2,
|
|
9
|
+
};
|
|
10
|
+
const entries = (0, get_entries_1.getEntries)(obj);
|
|
11
|
+
expect(entries).toEqual([
|
|
12
|
+
['a', 1],
|
|
13
|
+
['b', 2],
|
|
14
|
+
]);
|
|
15
|
+
});
|
|
16
|
+
it('should return an empty array for an empty object', () => {
|
|
17
|
+
const obj = {};
|
|
18
|
+
const entries = (0, get_entries_1.getEntries)(obj);
|
|
19
|
+
expect(entries).toEqual([]);
|
|
20
|
+
});
|
|
21
|
+
it('should work with different value types', () => {
|
|
22
|
+
const obj = {
|
|
23
|
+
name: 'Alice',
|
|
24
|
+
age: 30,
|
|
25
|
+
active: true,
|
|
26
|
+
};
|
|
27
|
+
const entries = (0, get_entries_1.getEntries)(obj);
|
|
28
|
+
expect(entries).toEqual([
|
|
29
|
+
['name', 'Alice'],
|
|
30
|
+
['age', 30],
|
|
31
|
+
['active', true],
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
it('should preserve key-value association', () => {
|
|
35
|
+
const obj = {
|
|
36
|
+
x: 10,
|
|
37
|
+
y: 20,
|
|
38
|
+
};
|
|
39
|
+
const entries = (0, get_entries_1.getEntries)(obj);
|
|
40
|
+
for (const [key, value] of entries) {
|
|
41
|
+
expect(obj[key]).toBe(value);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
it('should provide correct typing for keys and values (type-level test)', () => {
|
|
45
|
+
const obj = {
|
|
46
|
+
id: 1,
|
|
47
|
+
title: 'Post',
|
|
48
|
+
};
|
|
49
|
+
const entries = (0, get_entries_1.getEntries)(obj);
|
|
50
|
+
const key = 'id';
|
|
51
|
+
const value = obj[key];
|
|
52
|
+
expect(key).toBe('id');
|
|
53
|
+
expect(value).toBe(1);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Compares two arrays.
|
|
3
|
-
*
|
|
4
|
-
* @param {any[]} a First array to compare.
|
|
5
|
-
* @param {any[]} b Second array to compare.
|
|
6
|
-
*
|
|
7
|
-
* @returns {boolean} Validation result.
|
|
8
|
-
*/
|
|
9
|
-
export declare const compareArrays: (a: any[], b: any[]) => boolean;
|
|
1
|
+
export declare const compareArrays: <T>(a: T[], b: T[]) => boolean;
|
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.compareArrays = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
* @param {any[]} a First array to compare.
|
|
8
|
-
* @param {any[]} b Second array to compare.
|
|
9
|
-
*
|
|
10
|
-
* @returns {boolean} Validation result.
|
|
11
|
-
*/
|
|
12
|
-
const compareArrays = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
|
|
4
|
+
const deep_equal_1 = require("./deep-equal");
|
|
5
|
+
const compareArrays = (a, b) => a.length === b.length && a.every((v, i) => (0, deep_equal_1.deepEqual)(v, b[i]));
|
|
13
6
|
exports.compareArrays = compareArrays;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const deepEqual: (a: unknown, b: unknown) => boolean;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deepEqual = void 0;
|
|
4
|
+
const type_guards_1 = require("../type-guards");
|
|
5
|
+
const deepEqual = (a, b) => {
|
|
6
|
+
if (a === b) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
if (!(0, type_guards_1.isObject)(a) || !(0, type_guards_1.isObject)(b)) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
if (Array.isArray(a) !== Array.isArray(b)) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
const keysA = Object.keys(a);
|
|
16
|
+
const keysB = Object.keys(b);
|
|
17
|
+
if (keysA.length !== keysB.length) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return keysA.every((key) => Object.prototype.hasOwnProperty.call(b, key) &&
|
|
21
|
+
(0, exports.deepEqual)(a[key], b[key]));
|
|
22
|
+
};
|
|
23
|
+
exports.deepEqual = deepEqual;
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* @returns {[string, any]} The entries of the object.
|
|
7
|
-
*/
|
|
8
|
-
export declare const getEntries: <T extends object>(obj: T) => [[keyof T, T[keyof T]]];
|
|
1
|
+
type Entries<T> = {
|
|
2
|
+
[K in keyof T]: [K, T[K]];
|
|
3
|
+
}[keyof T][];
|
|
4
|
+
export declare function getEntries<T extends Record<PropertyKey, unknown>>(obj: T): Entries<T>;
|
|
5
|
+
export {};
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getEntries = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Returns the entries of an object.
|
|
6
|
-
*
|
|
7
|
-
* @param {object} obj The object to retrieve entries.
|
|
8
|
-
*
|
|
9
|
-
* @returns {[string, any]} The entries of the object.
|
|
10
|
-
*/
|
|
11
|
-
const getEntries = (obj) => Object.entries(obj);
|
|
12
3
|
exports.getEntries = getEntries;
|
|
4
|
+
function getEntries(obj) {
|
|
5
|
+
const entries = [];
|
|
6
|
+
for (const key of Object.keys(obj)) {
|
|
7
|
+
entries.push([key, obj[key]]);
|
|
8
|
+
}
|
|
9
|
+
return entries;
|
|
10
|
+
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
1
|
+
export * from './compare-arrays';
|
|
2
|
+
export * from './deep-equal';
|
|
3
|
+
export * from './get-entries';
|
|
@@ -1,7 +1,19 @@
|
|
|
1
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
|
+
};
|
|
2
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const get_entries_1 = require("./get-entries");
|
|
7
|
-
Object.defineProperty(exports, "getEntries", { enumerable: true, get: function () { return get_entries_1.getEntries; } });
|
|
17
|
+
__exportStar(require("./compare-arrays"), exports);
|
|
18
|
+
__exportStar(require("./deep-equal"), exports);
|
|
19
|
+
__exportStar(require("./get-entries"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const sort_by_properties_1 = require("../sort-by-properties");
|
|
4
|
+
describe('sortByProperties', () => {
|
|
5
|
+
it('sorts by a single property', () => {
|
|
6
|
+
const data = [
|
|
7
|
+
{ id: 2, name: 'B' },
|
|
8
|
+
{ id: 1, name: 'A' },
|
|
9
|
+
];
|
|
10
|
+
data.sort((0, sort_by_properties_1.sortByProperties)('id'));
|
|
11
|
+
expect(data).toEqual([
|
|
12
|
+
{ id: 1, name: 'A' },
|
|
13
|
+
{ id: 2, name: 'B' },
|
|
14
|
+
]);
|
|
15
|
+
});
|
|
16
|
+
it('sorts by multiple properties in order', () => {
|
|
17
|
+
const data = [
|
|
18
|
+
{ id: 1, name: 'Bob', age: 30 },
|
|
19
|
+
{ id: 2, name: 'Alice', age: 30 },
|
|
20
|
+
{ id: 3, name: 'Alice', age: 25 },
|
|
21
|
+
];
|
|
22
|
+
data.sort((0, sort_by_properties_1.sortByProperties)('name', 'age'));
|
|
23
|
+
expect(data).toEqual([
|
|
24
|
+
{ id: 3, name: 'Alice', age: 25 },
|
|
25
|
+
{ id: 2, name: 'Alice', age: 30 },
|
|
26
|
+
{ id: 1, name: 'Bob', age: 30 },
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
it('supports descending order with "-" prefix', () => {
|
|
30
|
+
const data = [
|
|
31
|
+
{ id: 1, name: 'Bob', age: 30 },
|
|
32
|
+
{ id: 2, name: 'Alice', age: 30 },
|
|
33
|
+
{ id: 3, name: 'Alice', age: 25 },
|
|
34
|
+
];
|
|
35
|
+
data.sort((0, sort_by_properties_1.sortByProperties)('name', '-age'));
|
|
36
|
+
expect(data).toEqual([
|
|
37
|
+
{ id: 2, name: 'Alice', age: 30 },
|
|
38
|
+
{ id: 3, name: 'Alice', age: 25 },
|
|
39
|
+
{ id: 1, name: 'Bob', age: 30 },
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
it('places undefined values last when used as secondary key', () => {
|
|
43
|
+
const data = [
|
|
44
|
+
{ id: 1, name: 'Alice' },
|
|
45
|
+
{ id: 2, name: 'Alice', age: 20 },
|
|
46
|
+
{ id: 3, name: 'Alice', age: 10 },
|
|
47
|
+
];
|
|
48
|
+
data.sort((0, sort_by_properties_1.sortByProperties)('name', 'age'));
|
|
49
|
+
expect(data).toEqual([
|
|
50
|
+
{ id: 3, name: 'Alice', age: 10 },
|
|
51
|
+
{ id: 2, name: 'Alice', age: 20 },
|
|
52
|
+
{ id: 1, name: 'Alice' },
|
|
53
|
+
]);
|
|
54
|
+
});
|
|
55
|
+
it('returns 0 when all compared properties are equal', () => {
|
|
56
|
+
const comparator = (0, sort_by_properties_1.sortByProperties)('name', 'age');
|
|
57
|
+
expect(comparator({ id: 1, name: 'Alice', age: 20 }, { id: 2, name: 'Alice', age: 20 })).toBe(0);
|
|
58
|
+
});
|
|
59
|
+
it('returns 0 when no properties are provided', () => {
|
|
60
|
+
const comparator = (0, sort_by_properties_1.sortByProperties)();
|
|
61
|
+
expect(comparator({ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' })).toBe(0);
|
|
62
|
+
});
|
|
63
|
+
it('enforces type safety at compile time', () => {
|
|
64
|
+
// @ts-expect-error
|
|
65
|
+
(0, sort_by_properties_1.sortByProperties)('invalid');
|
|
66
|
+
// @ts-expect-error
|
|
67
|
+
(0, sort_by_properties_1.sortByProperties)('-invalid');
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|