@nestia/e2e 7.0.0-dev.20250608 → 7.0.1
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 -21
- package/README.md +93 -92
- package/lib/ArrayUtil.d.ts +227 -2
- package/lib/ArrayUtil.js +227 -30
- package/lib/ArrayUtil.js.map +1 -1
- package/lib/GaffComparator.d.ts +229 -14
- package/lib/GaffComparator.js +229 -14
- package/lib/GaffComparator.js.map +1 -1
- package/lib/RandomGenerator.d.ts +332 -35
- package/lib/RandomGenerator.js +337 -50
- package/lib/RandomGenerator.js.map +1 -1
- package/lib/TestValidator.d.ts +301 -34
- package/lib/TestValidator.js +222 -57
- package/lib/TestValidator.js.map +1 -1
- package/package.json +1 -1
- package/src/ArrayUtil.ts +322 -98
- package/src/DynamicExecutor.ts +296 -296
- package/src/GaffComparator.ts +280 -64
- package/src/RandomGenerator.ts +451 -162
- package/src/TestValidator.ts +594 -347
- package/src/index.ts +4 -4
- package/src/internal/json_equal_to.ts +35 -35
- package/src/module.ts +5 -5
package/lib/ArrayUtil.js
CHANGED
|
@@ -46,41 +46,61 @@ var __values = (this && this.__values) || function(o) {
|
|
|
46
46
|
};
|
|
47
47
|
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
48
48
|
};
|
|
49
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
50
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
51
|
-
if (!m) return o;
|
|
52
|
-
var i = m.call(o), r, ar = [], e;
|
|
53
|
-
try {
|
|
54
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
55
|
-
}
|
|
56
|
-
catch (error) { e = { error: error }; }
|
|
57
|
-
finally {
|
|
58
|
-
try {
|
|
59
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
60
|
-
}
|
|
61
|
-
finally { if (e) throw e.error; }
|
|
62
|
-
}
|
|
63
|
-
return ar;
|
|
64
|
-
};
|
|
65
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
66
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
67
|
-
if (ar || !(i in from)) {
|
|
68
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
69
|
-
ar[i] = from[i];
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
73
|
-
};
|
|
74
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
75
50
|
exports.ArrayUtil = void 0;
|
|
76
51
|
/**
|
|
77
|
-
*
|
|
52
|
+
* A namespace providing utility functions for array manipulation.
|
|
53
|
+
*
|
|
54
|
+
* This namespace contains utility functions for array operations including
|
|
55
|
+
* asynchronous processing, filtering, mapping, and repetition tasks implemented
|
|
56
|
+
* in functional programming style. All functions are implemented using currying
|
|
57
|
+
* to enhance reusability and composability.
|
|
78
58
|
*
|
|
79
59
|
* @author Jeongho Nam - https://github.com/samchon
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* // Asynchronous filtering example
|
|
63
|
+
* const numbers = [1, 2, 3, 4, 5];
|
|
64
|
+
* const evenNumbers = await ArrayUtil.asyncFilter(numbers)(
|
|
65
|
+
* async (num) => num % 2 === 0
|
|
66
|
+
* );
|
|
67
|
+
* console.log(evenNumbers); // [2, 4]
|
|
68
|
+
* ```;
|
|
80
69
|
*/
|
|
81
70
|
var ArrayUtil;
|
|
82
71
|
(function (ArrayUtil) {
|
|
83
72
|
var _this = this;
|
|
73
|
+
/**
|
|
74
|
+
* Filters an array by applying an asynchronous predicate function to each
|
|
75
|
+
* element.
|
|
76
|
+
*
|
|
77
|
+
* This function is implemented in curried form, first taking an array and
|
|
78
|
+
* then a predicate function. Elements are processed sequentially, ensuring
|
|
79
|
+
* order is maintained.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const users = [
|
|
84
|
+
* { id: 1, name: 'Alice', active: true },
|
|
85
|
+
* { id: 2, name: 'Bob', active: false },
|
|
86
|
+
* { id: 3, name: 'Charlie', active: true }
|
|
87
|
+
* ];
|
|
88
|
+
*
|
|
89
|
+
* const activeUsers = await ArrayUtil.asyncFilter(users)(
|
|
90
|
+
* async (user) => {
|
|
91
|
+
* // Async validation logic (e.g., API call)
|
|
92
|
+
* await new Promise(resolve => setTimeout(resolve, 100));
|
|
93
|
+
* return user.active;
|
|
94
|
+
* }
|
|
95
|
+
* );
|
|
96
|
+
* console.log(activeUsers); // [{ id: 1, name: 'Alice', active: true }, { id: 3, name: 'Charlie', active: true }]
|
|
97
|
+
* ```;
|
|
98
|
+
*
|
|
99
|
+
* @template Input - The type of elements in the input array
|
|
100
|
+
* @param elements - The readonly array to filter
|
|
101
|
+
* @returns A function that takes a predicate and returns a Promise resolving
|
|
102
|
+
* to the filtered array
|
|
103
|
+
*/
|
|
84
104
|
ArrayUtil.asyncFilter = function (elements) {
|
|
85
105
|
return function (pred) { return __awaiter(_this, void 0, void 0, function () {
|
|
86
106
|
var ret;
|
|
@@ -109,6 +129,32 @@ var ArrayUtil;
|
|
|
109
129
|
});
|
|
110
130
|
}); };
|
|
111
131
|
};
|
|
132
|
+
/**
|
|
133
|
+
* Executes an asynchronous function for each element in an array
|
|
134
|
+
* sequentially.
|
|
135
|
+
*
|
|
136
|
+
* Unlike JavaScript's native forEach, this function processes asynchronous
|
|
137
|
+
* functions sequentially and waits for all operations to complete. It
|
|
138
|
+
* performs sequential processing rather than parallel processing, making it
|
|
139
|
+
* suitable for operations where order matters.
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* const urls = ['url1', 'url2', 'url3'];
|
|
144
|
+
*
|
|
145
|
+
* await ArrayUtil.asyncForEach(urls)(async (url, index) => {
|
|
146
|
+
* console.log(`Processing ${index}: ${url}`);
|
|
147
|
+
* const data = await fetch(url);
|
|
148
|
+
* await processData(data);
|
|
149
|
+
* console.log(`Completed ${index}: ${url}`);
|
|
150
|
+
* });
|
|
151
|
+
* console.log('All URLs processed sequentially');
|
|
152
|
+
* ```
|
|
153
|
+
*
|
|
154
|
+
* @template Input - The type of elements in the input array
|
|
155
|
+
* @param elements - The readonly array to process
|
|
156
|
+
* @returns A function that takes an async closure and returns a Promise<void>
|
|
157
|
+
*/
|
|
112
158
|
ArrayUtil.asyncForEach = function (elements) {
|
|
113
159
|
return function (closure) { return __awaiter(_this, void 0, void 0, function () {
|
|
114
160
|
return __generator(this, function (_a) {
|
|
@@ -123,6 +169,34 @@ var ArrayUtil;
|
|
|
123
169
|
});
|
|
124
170
|
}); };
|
|
125
171
|
};
|
|
172
|
+
/**
|
|
173
|
+
* Transforms each element of an array using an asynchronous function to
|
|
174
|
+
* create a new array.
|
|
175
|
+
*
|
|
176
|
+
* Similar to JavaScript's native map but processes asynchronous functions
|
|
177
|
+
* sequentially. Each element's transformation is completed before proceeding
|
|
178
|
+
* to the next element, ensuring order is maintained.
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* const userIds = [1, 2, 3, 4, 5];
|
|
183
|
+
*
|
|
184
|
+
* const userDetails = await ArrayUtil.asyncMap(userIds)(
|
|
185
|
+
* async (id, index) => {
|
|
186
|
+
* console.log(`Fetching user ${id} (${index + 1}/${userIds.length})`);
|
|
187
|
+
* const response = await fetch(`/api/users/${id}`);
|
|
188
|
+
* return await response.json();
|
|
189
|
+
* }
|
|
190
|
+
* );
|
|
191
|
+
* console.log('All users fetched:', userDetails);
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* @template Input - The type of elements in the input array
|
|
195
|
+
* @template Output - The type of elements in the output array
|
|
196
|
+
* @param elements - The readonly array to transform
|
|
197
|
+
* @returns A function that takes a transformation function and returns a
|
|
198
|
+
* Promise resolving to the transformed array
|
|
199
|
+
*/
|
|
126
200
|
ArrayUtil.asyncMap = function (elements) {
|
|
127
201
|
return function (closure) { return __awaiter(_this, void 0, void 0, function () {
|
|
128
202
|
var ret;
|
|
@@ -150,6 +224,31 @@ var ArrayUtil;
|
|
|
150
224
|
});
|
|
151
225
|
}); };
|
|
152
226
|
};
|
|
227
|
+
/**
|
|
228
|
+
* Executes an asynchronous function a specified number of times sequentially.
|
|
229
|
+
*
|
|
230
|
+
* Executes the function with indices from 0 to count-1 incrementally. Each
|
|
231
|
+
* execution is performed sequentially, and all results are collected into an
|
|
232
|
+
* array.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```typescript
|
|
236
|
+
* // Generate random data 5 times
|
|
237
|
+
* const randomData = await ArrayUtil.asyncRepeat(5)(async (index) => {
|
|
238
|
+
* await new Promise(resolve => setTimeout(resolve, 100)); // Wait 0.1 seconds
|
|
239
|
+
* return {
|
|
240
|
+
* id: index,
|
|
241
|
+
* value: Math.random(),
|
|
242
|
+
* timestamp: new Date().toISOString()
|
|
243
|
+
* };
|
|
244
|
+
* });
|
|
245
|
+
* console.log('Generated data:', randomData);
|
|
246
|
+
* ```;
|
|
247
|
+
*
|
|
248
|
+
* @param count - The number of times to repeat (non-negative integer)
|
|
249
|
+
* @returns A function that takes an async closure and returns a Promise
|
|
250
|
+
* resolving to an array of results
|
|
251
|
+
*/
|
|
153
252
|
ArrayUtil.asyncRepeat = function (count) {
|
|
154
253
|
return function (closure) { return __awaiter(_this, void 0, void 0, function () {
|
|
155
254
|
var indexes, output, indexes_1, indexes_1_1, index, _a, _b, e_1_1;
|
|
@@ -193,20 +292,118 @@ var ArrayUtil;
|
|
|
193
292
|
});
|
|
194
293
|
}); };
|
|
195
294
|
};
|
|
295
|
+
/**
|
|
296
|
+
* Checks if at least one element in the array satisfies the given condition.
|
|
297
|
+
*
|
|
298
|
+
* Similar to JavaScript's native some() method but implemented in curried
|
|
299
|
+
* form for better compatibility with functional programming style. Returns
|
|
300
|
+
* true immediately when the first element satisfying the condition is found.
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* ```typescript
|
|
304
|
+
* const numbers = [1, 3, 5, 7, 8, 9];
|
|
305
|
+
* const products = [
|
|
306
|
+
* { name: 'Apple', price: 100, inStock: true },
|
|
307
|
+
* { name: 'Banana', price: 50, inStock: false },
|
|
308
|
+
* { name: 'Orange', price: 80, inStock: true }
|
|
309
|
+
* ];
|
|
310
|
+
*
|
|
311
|
+
* const hasEvenNumber = ArrayUtil.has(numbers)(num => num % 2 === 0);
|
|
312
|
+
* console.log(hasEvenNumber); // true (8 exists)
|
|
313
|
+
*
|
|
314
|
+
* const hasExpensiveItem = ArrayUtil.has(products)(product => product.price > 90);
|
|
315
|
+
* console.log(hasExpensiveItem); // true (Apple costs 100)
|
|
316
|
+
*
|
|
317
|
+
* const hasOutOfStock = ArrayUtil.has(products)(product => !product.inStock);
|
|
318
|
+
* console.log(hasOutOfStock); // true (Banana is out of stock)
|
|
319
|
+
* ```;
|
|
320
|
+
*
|
|
321
|
+
* @template T - The type of elements in the array
|
|
322
|
+
* @param elements - The readonly array to check
|
|
323
|
+
* @returns A function that takes a predicate and returns a boolean
|
|
324
|
+
*/
|
|
196
325
|
ArrayUtil.has = function (elements) {
|
|
197
326
|
return function (pred) {
|
|
198
327
|
return elements.find(pred) !== undefined;
|
|
199
328
|
};
|
|
200
329
|
};
|
|
330
|
+
/**
|
|
331
|
+
* Executes a function a specified number of times and collects the results
|
|
332
|
+
* into an array.
|
|
333
|
+
*
|
|
334
|
+
* A synchronous repetition function that executes the given function for each
|
|
335
|
+
* index (from 0 to count-1) and collects the results into an array.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```typescript
|
|
339
|
+
* // Generate an array of squares from 1 to 5
|
|
340
|
+
* const squares = ArrayUtil.repeat(5)(index => (index + 1) ** 2);
|
|
341
|
+
* console.log(squares); // [1, 4, 9, 16, 25]
|
|
342
|
+
*
|
|
343
|
+
* // Generate an array of default user objects
|
|
344
|
+
* const users = ArrayUtil.repeat(3)(index => ({
|
|
345
|
+
* id: index + 1,
|
|
346
|
+
* name: `User${index + 1}`,
|
|
347
|
+
* email: `user${index + 1}@example.com`
|
|
348
|
+
* }));
|
|
349
|
+
* console.log(users);
|
|
350
|
+
* // [
|
|
351
|
+
* // { id: 1, name: 'User1', email: 'user1@example.com' },
|
|
352
|
+
* // { id: 2, name: 'User2', email: 'user2@example.com' },
|
|
353
|
+
* // { id: 3, name: 'User3', email: 'user3@example.com' }
|
|
354
|
+
* // ]
|
|
355
|
+
* ```
|
|
356
|
+
*
|
|
357
|
+
* @param count - The number of times to repeat (non-negative integer)
|
|
358
|
+
* @returns A function that takes a closure and returns an array of results
|
|
359
|
+
*/
|
|
201
360
|
ArrayUtil.repeat = function (count) {
|
|
202
361
|
return function (closure) {
|
|
203
362
|
return new Array(count).fill("").map(function (_, index) { return closure(index); });
|
|
204
363
|
};
|
|
205
364
|
};
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
365
|
+
/**
|
|
366
|
+
* Generates all possible subsets of a given array.
|
|
367
|
+
*
|
|
368
|
+
* Implements the mathematical concept of power set, generating 2^n subsets
|
|
369
|
+
* from an array of n elements. Uses depth-first search (DFS) algorithm to
|
|
370
|
+
* calculate all possible combinations of including or excluding each
|
|
371
|
+
* element.
|
|
372
|
+
*
|
|
373
|
+
* @example
|
|
374
|
+
* ```typescript
|
|
375
|
+
* const numbers = [1, 2, 3];
|
|
376
|
+
* const allSubsets = ArrayUtil.subsets(numbers);
|
|
377
|
+
* console.log(allSubsets);
|
|
378
|
+
* // [
|
|
379
|
+
* // [], // empty set
|
|
380
|
+
* // [3], // {3}
|
|
381
|
+
* // [2], // {2}
|
|
382
|
+
* // [2, 3], // {2, 3}
|
|
383
|
+
* // [1], // {1}
|
|
384
|
+
* // [1, 3], // {1, 3}
|
|
385
|
+
* // [1, 2], // {1, 2}
|
|
386
|
+
* // [1, 2, 3] // {1, 2, 3}
|
|
387
|
+
* // ]
|
|
388
|
+
*
|
|
389
|
+
* const colors = ['red', 'blue'];
|
|
390
|
+
* const colorSubsets = ArrayUtil.subsets(colors);
|
|
391
|
+
* console.log(colorSubsets);
|
|
392
|
+
* // [
|
|
393
|
+
* // [],
|
|
394
|
+
* // ['blue'],
|
|
395
|
+
* // ['red'],
|
|
396
|
+
* // ['red', 'blue']
|
|
397
|
+
* // ]
|
|
398
|
+
*
|
|
399
|
+
* // Warning: Result size grows exponentially with array size
|
|
400
|
+
* // Example: 10 elements → 1,024 subsets, 20 elements → 1,048,576 subsets
|
|
401
|
+
* ```;
|
|
402
|
+
*
|
|
403
|
+
* @template T - The type of elements in the array
|
|
404
|
+
* @param array - The array to generate subsets from
|
|
405
|
+
* @returns An array containing all possible subsets
|
|
406
|
+
*/
|
|
210
407
|
ArrayUtil.subsets = function (array) {
|
|
211
408
|
var check = new Array(array.length).fill(false);
|
|
212
409
|
var output = [];
|
package/lib/ArrayUtil.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ArrayUtil.js","sourceRoot":"","sources":["../src/ArrayUtil.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ArrayUtil.js","sourceRoot":"","sources":["../src/ArrayUtil.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,IAAiB,SAAS,CA8SzB;AA9SD,WAAiB,SAAS;;IACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACU,qBAAW,GACtB,UAAQ,QAA0B;QAClC,OAAA,UACE,IAIqB;;;;;;wBAEf,GAAG,GAAY,EAAE,CAAC;wBACxB,qBAAM,UAAA,YAAY,CAAC,QAAQ,CAAC,CAAC,UAAO,IAAI,EAAE,KAAK,EAAE,KAAK;;;;gDAC9B,qBAAM,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAA;;4CAA9C,IAAI,GAAY,SAA8B;4CACpD,IAAI,IAAI,KAAK,IAAI;gDAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;;;;iCACnC,CAAC,EAAA;;wBAHF,SAGE,CAAC;wBACH,sBAAO,GAAG,EAAC;;;aACZ;IAbD,CAaC,CAAC;IAEJ;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACU,sBAAY,GACvB,UAAQ,QAA0B;QAClC,OAAA,UACE,OAIiB;;;4BAEjB,qBAAM,UAAA,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,UAAC,KAAK;4BACvC,OAAA,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC;wBAAzC,CAAyC,CAC1C,EAAA;;wBAFD,SAEC,CAAC;;;;aACH;IAVD,CAUC,CAAC;IAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACU,kBAAQ,GACnB,UAAQ,QAA0B;QAClC,OAAA,UACE,OAIoB;;;;;;wBAEd,GAAG,GAAa,EAAE,CAAC;wBACzB,qBAAM,UAAA,YAAY,CAAC,QAAQ,CAAC,CAAC,UAAO,IAAI,EAAE,KAAK,EAAE,KAAK;;;;gDAC7B,qBAAM,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,EAAA;;4CAAlD,MAAM,GAAW,SAAiC;4CACxD,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;;;;iCAClB,CAAC,EAAA;;wBAHF,SAGE,CAAC;wBACH,sBAAO,GAAG,EAAC;;;aACZ;IAbD,CAaC,CAAC;IAEJ;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACU,qBAAW,GACtB,UAAC,KAAa;QACd,OAAA,UAAU,OAAsC;;;;;;wBACxC,OAAO,GAAa,IAAI,KAAK,CAAC,KAAK,CAAC;6BACvC,IAAI,CAAC,CAAC,CAAC;6BACP,GAAG,CAAC,UAAC,CAAC,EAAE,KAAK,IAAK,OAAA,KAAK,EAAL,CAAK,CAAC,CAAC;wBAEtB,MAAM,GAAQ,EAAE,CAAC;;;;wBACH,YAAA,SAAA,OAAO,CAAA;;;;wBAAhB,KAAK;wBAAa,KAAA,CAAA,KAAA,MAAM,CAAA,CAAC,IAAI,CAAA;wBAAC,qBAAM,OAAO,CAAC,KAAK,CAAC,EAAA;;wBAAhC,cAAY,SAAoB,EAAC,CAAC;;;;;;;;;;;;;;;;4BAE/D,sBAAO,MAAM,EAAC;;;aACf;IATD,CASC,CAAC;IAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACU,aAAG,GACd,UAAI,QAAsB;QAC1B,OAAA,UAAC,IAA0B;YACzB,OAAA,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,SAAS;QAAjC,CAAiC;IADnC,CACmC,CAAC;IAEtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACU,gBAAM,GACjB,UAAC,KAAa;QACd,OAAA,UAAI,OAA6B;YAC/B,OAAA,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAC,CAAC,EAAE,KAAK,IAAK,OAAA,OAAO,CAAC,KAAK,CAAC,EAAd,CAAc,CAAC;QAA3D,CAA2D;IAD7D,CAC6D,CAAC;IAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;IACU,iBAAO,GAAG,UAAI,KAAU;QACnC,IAAM,KAAK,GAAc,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7D,IAAM,MAAM,GAAU,EAAE,CAAC;QAEzB,IAAM,GAAG,GAAG,UAAC,KAAa;YACxB,IAAI,KAAK,KAAK,KAAK,CAAC,MAAM;gBACxB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAC,EAAE,EAAE,GAAG,IAAK,OAAA,KAAK,CAAC,GAAG,CAAC,EAAV,CAAU,CAAC,CAAC,CAAC;iBAChD,CAAC;gBACJ,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC;gBACpB,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;gBAEf,KAAK,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;gBACrB,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YACjB,CAAC;QACH,CAAC,CAAC;QACF,GAAG,CAAC,CAAC,CAAC,CAAC;QACP,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC,EA9SgB,SAAS,yBAAT,SAAS,QA8SzB"}
|
package/lib/GaffComparator.d.ts
CHANGED
|
@@ -1,33 +1,248 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Type-safe comparator functions for Array.sort() operations with advanced
|
|
3
|
+
* field access.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* GaffComparator provides a collection of specialized comparator functions
|
|
6
|
+
* designed to work seamlessly with Array.sort() and testing frameworks like
|
|
7
|
+
* TestValidator.sort(). Each comparator supports both single values and arrays
|
|
8
|
+
* of values, enabling complex multi-field sorting scenarios with lexicographic
|
|
9
|
+
* ordering.
|
|
10
|
+
*
|
|
11
|
+
* Key features:
|
|
12
|
+
*
|
|
13
|
+
* - Generic type safety for any object structure
|
|
14
|
+
* - Support for single values or arrays of values per field
|
|
15
|
+
* - Lexicographic comparison for multi-value scenarios
|
|
16
|
+
* - Locale-aware string comparison
|
|
17
|
+
* - Automatic type conversion for dates and numbers
|
|
18
|
+
*
|
|
19
|
+
* The comparators follow the standard JavaScript sort contract:
|
|
20
|
+
*
|
|
21
|
+
* - Return < 0 if first element should come before second
|
|
22
|
+
* - Return > 0 if first element should come after second
|
|
23
|
+
* - Return 0 if elements are equal
|
|
7
24
|
*
|
|
8
|
-
* @example https://github.com/samchon/nestia-template/blob/master/src/test/features/api/bbs/test_api_bbs_article_index_sort.ts
|
|
9
25
|
* @author Jeongho Nam - https://github.com/samchon
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // Basic usage with single fields
|
|
29
|
+
* users.sort(GaffComparator.strings(user => user.name));
|
|
30
|
+
* posts.sort(GaffComparator.dates(post => post.createdAt));
|
|
31
|
+
* products.sort(GaffComparator.numbers(product => product.price));
|
|
32
|
+
*
|
|
33
|
+
* // Multi-field sorting with arrays
|
|
34
|
+
* users.sort(GaffComparator.strings(user => [user.lastName, user.firstName]));
|
|
35
|
+
* events.sort(GaffComparator.dates(event => [event.startDate, event.endDate]));
|
|
36
|
+
*
|
|
37
|
+
* // Integration with TestValidator
|
|
38
|
+
* await TestValidator.sort("user sorting")(
|
|
39
|
+
* (sortable) => api.getUsers({ sort: sortable })
|
|
40
|
+
* )("name", "email")(
|
|
41
|
+
* GaffComparator.strings(user => [user.name, user.email])
|
|
42
|
+
* )("+");
|
|
43
|
+
* ```;
|
|
10
44
|
*/
|
|
11
45
|
export declare namespace GaffComparator {
|
|
12
46
|
/**
|
|
13
|
-
*
|
|
47
|
+
* Creates a comparator function for string-based sorting with locale-aware
|
|
48
|
+
* comparison.
|
|
49
|
+
*
|
|
50
|
+
* Generates a comparator that extracts string values from objects and
|
|
51
|
+
* performs lexicographic comparison using locale-sensitive string comparison.
|
|
52
|
+
* Supports both single strings and arrays of strings for multi-field sorting
|
|
53
|
+
* scenarios.
|
|
54
|
+
*
|
|
55
|
+
* When comparing arrays, performs lexicographic ordering: compares the first
|
|
56
|
+
* elements, then the second elements if the first are equal, and so on. This
|
|
57
|
+
* enables complex sorting like "sort by last name, then by first name".
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* interface User {
|
|
62
|
+
* id: string;
|
|
63
|
+
* firstName: string;
|
|
64
|
+
* lastName: string;
|
|
65
|
+
* email: string;
|
|
66
|
+
* status: 'active' | 'inactive';
|
|
67
|
+
* }
|
|
14
68
|
*
|
|
15
|
-
*
|
|
16
|
-
* @
|
|
69
|
+
* const users: User[] = [
|
|
70
|
+
* { id: '1', firstName: 'John', lastName: 'Doe', email: 'john@example.com', status: 'active' },
|
|
71
|
+
* { id: '2', firstName: 'Jane', lastName: 'Doe', email: 'jane@example.com', status: 'inactive' },
|
|
72
|
+
* { id: '3', firstName: 'Bob', lastName: 'Smith', email: 'bob@example.com', status: 'active' }
|
|
73
|
+
* ];
|
|
74
|
+
*
|
|
75
|
+
* // Single field sorting
|
|
76
|
+
* users.sort(GaffComparator.strings(user => user.lastName));
|
|
77
|
+
* // Result: Doe, Doe, Smith
|
|
78
|
+
*
|
|
79
|
+
* // Multi-field sorting: last name, then first name
|
|
80
|
+
* users.sort(GaffComparator.strings(user => [user.lastName, user.firstName]));
|
|
81
|
+
* // Result: Doe Jane, Doe John, Smith Bob
|
|
82
|
+
*
|
|
83
|
+
* // Status-based sorting
|
|
84
|
+
* users.sort(GaffComparator.strings(user => user.status));
|
|
85
|
+
* // Result: active users first, then inactive
|
|
86
|
+
*
|
|
87
|
+
* // Complex multi-field: status, then last name, then first name
|
|
88
|
+
* users.sort(GaffComparator.strings(user => [user.status, user.lastName, user.firstName]));
|
|
89
|
+
*
|
|
90
|
+
* // Integration with API sorting validation
|
|
91
|
+
* await TestValidator.sort("user name sorting")(
|
|
92
|
+
* (sortFields) => userApi.getUsers({ sort: sortFields })
|
|
93
|
+
* )("lastName", "firstName")(
|
|
94
|
+
* GaffComparator.strings(user => [user.lastName, user.firstName])
|
|
95
|
+
* )("+");
|
|
96
|
+
* ```;
|
|
97
|
+
*
|
|
98
|
+
* @template T - The type of objects being compared
|
|
99
|
+
* @param getter - Function that extracts string value(s) from input objects
|
|
100
|
+
* @returns A comparator function suitable for Array.sort()
|
|
17
101
|
*/
|
|
18
102
|
const strings: <T>(getter: (input: T) => string | string[]) => (x: T, y: T) => number;
|
|
19
103
|
/**
|
|
20
|
-
*
|
|
104
|
+
* Creates a comparator function for date-based sorting with automatic string
|
|
105
|
+
* parsing.
|
|
106
|
+
*
|
|
107
|
+
* Generates a comparator that extracts date values from objects,
|
|
108
|
+
* automatically converting string representations to Date objects for
|
|
109
|
+
* numerical comparison. Supports both single dates and arrays of dates for
|
|
110
|
+
* complex temporal sorting.
|
|
111
|
+
*
|
|
112
|
+
* Date strings are parsed using the standard Date constructor, which supports
|
|
113
|
+
* ISO 8601 format, RFC 2822 format, and other common date representations.
|
|
114
|
+
* The comparison is performed on millisecond timestamps for precise
|
|
115
|
+
* ordering.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* interface Event {
|
|
120
|
+
* id: string;
|
|
121
|
+
* title: string;
|
|
122
|
+
* startDate: string;
|
|
123
|
+
* endDate: string;
|
|
124
|
+
* createdAt: string;
|
|
125
|
+
* updatedAt: string;
|
|
126
|
+
* }
|
|
21
127
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
128
|
+
* const events: Event[] = [
|
|
129
|
+
* {
|
|
130
|
+
* id: '1',
|
|
131
|
+
* title: 'Conference',
|
|
132
|
+
* startDate: '2024-03-15T09:00:00Z',
|
|
133
|
+
* endDate: '2024-03-15T17:00:00Z',
|
|
134
|
+
* createdAt: '2024-01-10T10:00:00Z',
|
|
135
|
+
* updatedAt: '2024-02-01T15:30:00Z'
|
|
136
|
+
* },
|
|
137
|
+
* {
|
|
138
|
+
* id: '2',
|
|
139
|
+
* title: 'Workshop',
|
|
140
|
+
* startDate: '2024-03-10T14:00:00Z',
|
|
141
|
+
* endDate: '2024-03-10T16:00:00Z',
|
|
142
|
+
* createdAt: '2024-01-15T11:00:00Z',
|
|
143
|
+
* updatedAt: '2024-01-20T09:15:00Z'
|
|
144
|
+
* }
|
|
145
|
+
* ];
|
|
146
|
+
*
|
|
147
|
+
* // Sort by start date (chronological order)
|
|
148
|
+
* events.sort(GaffComparator.dates(event => event.startDate));
|
|
149
|
+
*
|
|
150
|
+
* // Sort by creation date (oldest first)
|
|
151
|
+
* events.sort(GaffComparator.dates(event => event.createdAt));
|
|
152
|
+
*
|
|
153
|
+
* // Multi-field: start date, then end date
|
|
154
|
+
* events.sort(GaffComparator.dates(event => [event.startDate, event.endDate]));
|
|
155
|
+
*
|
|
156
|
+
* // Sort by modification history: created date, then updated date
|
|
157
|
+
* events.sort(GaffComparator.dates(event => [event.createdAt, event.updatedAt]));
|
|
158
|
+
*
|
|
159
|
+
* // Validate API date sorting
|
|
160
|
+
* await TestValidator.sort("event chronological sorting")(
|
|
161
|
+
* (sortFields) => eventApi.getEvents({ sort: sortFields })
|
|
162
|
+
* )("startDate")(
|
|
163
|
+
* GaffComparator.dates(event => event.startDate)
|
|
164
|
+
* )("+");
|
|
165
|
+
*
|
|
166
|
+
* // Test complex date-based sorting
|
|
167
|
+
* const sortByEventSchedule = GaffComparator.dates(event => [
|
|
168
|
+
* event.startDate,
|
|
169
|
+
* event.endDate
|
|
170
|
+
* ]);
|
|
171
|
+
* ```;
|
|
172
|
+
*
|
|
173
|
+
* @template T - The type of objects being compared
|
|
174
|
+
* @param getter - Function that extracts date string(s) from input objects
|
|
175
|
+
* @returns A comparator function suitable for Array.sort()
|
|
24
176
|
*/
|
|
25
177
|
const dates: <T>(getter: (input: T) => string | string[]) => (x: T, y: T) => number;
|
|
26
178
|
/**
|
|
27
|
-
*
|
|
179
|
+
* Creates a comparator function for numerical sorting with multi-value
|
|
180
|
+
* support.
|
|
181
|
+
*
|
|
182
|
+
* Generates a comparator that extracts numerical values from objects and
|
|
183
|
+
* performs mathematical comparison. Supports both single numbers and arrays
|
|
184
|
+
* of numbers for complex numerical sorting scenarios like sorting by price
|
|
185
|
+
* then by rating.
|
|
186
|
+
*
|
|
187
|
+
* When comparing arrays, performs lexicographic numerical ordering: compares
|
|
188
|
+
* the first numbers, then the second numbers if the first are equal, and so
|
|
189
|
+
* on. This enables sophisticated sorting like "sort by price ascending, then
|
|
190
|
+
* by rating descending".
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* interface Product {
|
|
195
|
+
* id: string;
|
|
196
|
+
* name: string;
|
|
197
|
+
* price: number;
|
|
198
|
+
* rating: number;
|
|
199
|
+
* stock: number;
|
|
200
|
+
* categoryId: number;
|
|
201
|
+
* salesCount: number;
|
|
202
|
+
* }
|
|
203
|
+
*
|
|
204
|
+
* const products: Product[] = [
|
|
205
|
+
* { id: '1', name: 'Laptop', price: 999.99, rating: 4.5, stock: 15, categoryId: 1, salesCount: 150 },
|
|
206
|
+
* { id: '2', name: 'Mouse', price: 29.99, rating: 4.2, stock: 50, categoryId: 1, salesCount: 300 },
|
|
207
|
+
* { id: '3', name: 'Keyboard', price: 79.99, rating: 4.8, stock: 25, categoryId: 1, salesCount: 200 }
|
|
208
|
+
* ];
|
|
209
|
+
*
|
|
210
|
+
* // Sort by price (ascending)
|
|
211
|
+
* products.sort(GaffComparator.numbers(product => product.price));
|
|
212
|
+
* // Result: Mouse ($29.99), Keyboard ($79.99), Laptop ($999.99)
|
|
213
|
+
*
|
|
214
|
+
* // Sort by rating (descending requires negation)
|
|
215
|
+
* products.sort(GaffComparator.numbers(product => -product.rating));
|
|
216
|
+
* // Result: Keyboard (4.8), Laptop (4.5), Mouse (4.2)
|
|
217
|
+
*
|
|
218
|
+
* // Multi-field: category, then price
|
|
219
|
+
* products.sort(GaffComparator.numbers(product => [product.categoryId, product.price]));
|
|
220
|
+
*
|
|
221
|
+
* // Complex business logic: popularity (sales) then rating
|
|
222
|
+
* products.sort(GaffComparator.numbers(product => [-product.salesCount, -product.rating]));
|
|
223
|
+
* // Negative values for descending order
|
|
224
|
+
*
|
|
225
|
+
* // Sort by inventory priority: low stock first, then by sales
|
|
226
|
+
* products.sort(GaffComparator.numbers(product => [product.stock, -product.salesCount]));
|
|
227
|
+
*
|
|
228
|
+
* // Validate API numerical sorting
|
|
229
|
+
* await TestValidator.sort("product price sorting")(
|
|
230
|
+
* (sortFields) => productApi.getProducts({ sort: sortFields })
|
|
231
|
+
* )("price")(
|
|
232
|
+
* GaffComparator.numbers(product => product.price)
|
|
233
|
+
* )("+");
|
|
234
|
+
*
|
|
235
|
+
* // Test multi-criteria sorting
|
|
236
|
+
* const sortByBusinessValue = GaffComparator.numbers(product => [
|
|
237
|
+
* -product.salesCount, // High sales first
|
|
238
|
+
* -product.rating, // High rating first
|
|
239
|
+
* product.price // Low price first (for tie-breaking)
|
|
240
|
+
* ]);
|
|
241
|
+
* ```;
|
|
28
242
|
*
|
|
29
|
-
* @
|
|
30
|
-
* @
|
|
243
|
+
* @template T - The type of objects being compared
|
|
244
|
+
* @param closure - Function that extracts number value(s) from input objects
|
|
245
|
+
* @returns A comparator function suitable for Array.sort()
|
|
31
246
|
*/
|
|
32
247
|
const numbers: <T>(closure: (input: T) => number | number[]) => (x: T, y: T) => number;
|
|
33
248
|
}
|