@nestia/e2e 11.0.0-dev.20260305 → 11.0.0-dev.20260312
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/ArrayUtil.d.ts +244 -0
- package/lib/ArrayUtil.js +296 -0
- package/lib/ArrayUtil.js.map +1 -0
- package/lib/DynamicExecutor.d.ts +144 -0
- package/lib/DynamicExecutor.js +176 -0
- package/lib/DynamicExecutor.js.map +1 -0
- package/lib/GaffComparator.d.ts +255 -0
- package/lib/GaffComparator.js +278 -0
- package/lib/GaffComparator.js.map +1 -0
- package/lib/MapUtil.d.ts +79 -0
- package/lib/MapUtil.js +92 -0
- package/lib/MapUtil.js.map +1 -0
- package/lib/RandomGenerator.d.ts +416 -0
- package/lib/RandomGenerator.js +464 -0
- package/lib/RandomGenerator.js.map +1 -0
- package/lib/TestValidator.d.ts +389 -0
- package/lib/TestValidator.js +495 -0
- package/lib/TestValidator.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.js +42 -0
- package/lib/index.js.map +1 -0
- package/lib/internal/json_equal_to.d.ts +1 -0
- package/lib/internal/json_equal_to.js +33 -0
- package/lib/internal/json_equal_to.js.map +1 -0
- package/lib/module.d.ts +6 -0
- package/lib/module.js +23 -0
- package/lib/module.js.map +1 -0
- package/package.json +1 -1
- package/src/DynamicExecutor.ts +274 -274
- package/src/index.ts +4 -4
- package/src/internal/json_equal_to.ts +35 -35
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A namespace providing utility functions for array manipulation.
|
|
3
|
+
*
|
|
4
|
+
* This namespace contains utility functions for array operations including
|
|
5
|
+
* asynchronous processing, filtering, mapping, and repetition tasks implemented
|
|
6
|
+
* in functional programming style. Functions use direct parameter passing for
|
|
7
|
+
* simplicity while maintaining functional programming principles.
|
|
8
|
+
*
|
|
9
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* // Asynchronous filtering example
|
|
13
|
+
* const numbers = [1, 2, 3, 4, 5];
|
|
14
|
+
* const evenNumbers = await ArrayUtil.asyncFilter(numbers,
|
|
15
|
+
* async (num) => num % 2 === 0
|
|
16
|
+
* );
|
|
17
|
+
* console.log(evenNumbers); // [2, 4]
|
|
18
|
+
* ```;
|
|
19
|
+
*/
|
|
20
|
+
export declare namespace ArrayUtil {
|
|
21
|
+
/**
|
|
22
|
+
* Filters an array by applying an asynchronous predicate function to each
|
|
23
|
+
* element.
|
|
24
|
+
*
|
|
25
|
+
* Elements are processed sequentially, ensuring order is maintained. The
|
|
26
|
+
* predicate function receives the element, index, and the full array as
|
|
27
|
+
* parameters.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const users = [
|
|
32
|
+
* { id: 1, name: 'Alice', active: true },
|
|
33
|
+
* { id: 2, name: 'Bob', active: false },
|
|
34
|
+
* { id: 3, name: 'Charlie', active: true }
|
|
35
|
+
* ];
|
|
36
|
+
*
|
|
37
|
+
* const activeUsers = await ArrayUtil.asyncFilter(users,
|
|
38
|
+
* async (user) => {
|
|
39
|
+
* // Async validation logic (e.g., API call)
|
|
40
|
+
* await new Promise(resolve => setTimeout(resolve, 100));
|
|
41
|
+
* return user.active;
|
|
42
|
+
* }
|
|
43
|
+
* );
|
|
44
|
+
* console.log(activeUsers); // [{ id: 1, name: 'Alice', active: true }, { id: 3, name: 'Charlie', active: true }]
|
|
45
|
+
* ```;
|
|
46
|
+
*
|
|
47
|
+
* @template Input - The type of elements in the input array
|
|
48
|
+
* @param elements - The readonly array to filter
|
|
49
|
+
* @param pred - The asynchronous predicate function to test each element
|
|
50
|
+
* @returns A Promise resolving to the filtered array
|
|
51
|
+
*/
|
|
52
|
+
const asyncFilter: <Input>(elements: readonly Input[], pred: (elem: Input, index: number, array: readonly Input[]) => Promise<boolean>) => Promise<Input[]>;
|
|
53
|
+
/**
|
|
54
|
+
* Executes an asynchronous function for each element in an array
|
|
55
|
+
* sequentially.
|
|
56
|
+
*
|
|
57
|
+
* Unlike JavaScript's native forEach, this function processes asynchronous
|
|
58
|
+
* functions sequentially and waits for all operations to complete. It
|
|
59
|
+
* performs sequential processing rather than parallel processing, making it
|
|
60
|
+
* suitable for operations where order matters.
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const urls = ['url1', 'url2', 'url3'];
|
|
65
|
+
*
|
|
66
|
+
* await ArrayUtil.asyncForEach(urls, async (url, index) => {
|
|
67
|
+
* console.log(`Processing ${index}: ${url}`);
|
|
68
|
+
* const data = await fetch(url);
|
|
69
|
+
* await processData(data);
|
|
70
|
+
* console.log(`Completed ${index}: ${url}`);
|
|
71
|
+
* });
|
|
72
|
+
* console.log('All URLs processed sequentially');
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* @template Input - The type of elements in the input array
|
|
76
|
+
* @param elements - The readonly array to process
|
|
77
|
+
* @param closure - The asynchronous function to execute for each element
|
|
78
|
+
* @returns A Promise<void> that resolves when all operations complete
|
|
79
|
+
*/
|
|
80
|
+
const asyncForEach: <Input>(elements: readonly Input[], closure: (elem: Input, index: number, array: readonly Input[]) => Promise<any>) => Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Transforms each element of an array using an asynchronous function to
|
|
83
|
+
* create a new array.
|
|
84
|
+
*
|
|
85
|
+
* Similar to JavaScript's native map but processes asynchronous functions
|
|
86
|
+
* sequentially. Each element's transformation is completed before proceeding
|
|
87
|
+
* to the next element, ensuring order is maintained. This function still
|
|
88
|
+
* maintains the currying pattern for composition.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* const userIds = [1, 2, 3, 4, 5];
|
|
93
|
+
*
|
|
94
|
+
* const userDetails = await ArrayUtil.asyncMap(userIds)(
|
|
95
|
+
* async (id, index) => {
|
|
96
|
+
* console.log(`Fetching user ${id} (${index + 1}/${userIds.length})`);
|
|
97
|
+
* const response = await fetch(`/api/users/${id}`);
|
|
98
|
+
* return await response.json();
|
|
99
|
+
* }
|
|
100
|
+
* );
|
|
101
|
+
* console.log('All users fetched:', userDetails);
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @template Input - The type of elements in the input array
|
|
105
|
+
* @param elements - The readonly array to transform
|
|
106
|
+
* @returns A function that takes a transformation function and returns a
|
|
107
|
+
* Promise resolving to the transformed array
|
|
108
|
+
*/
|
|
109
|
+
const asyncMap: <Input, Output>(elements: readonly Input[], closure: (elem: Input, index: number, array: readonly Input[]) => Promise<Output>) => Promise<Output[]>;
|
|
110
|
+
/**
|
|
111
|
+
* Executes an asynchronous function a specified number of times sequentially.
|
|
112
|
+
*
|
|
113
|
+
* Executes the function with indices from 0 to count-1 incrementally. Each
|
|
114
|
+
* execution is performed sequentially, and all results are collected into an
|
|
115
|
+
* array.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* // Generate random data 5 times
|
|
120
|
+
* const randomData = await ArrayUtil.asyncRepeat(5, async (index) => {
|
|
121
|
+
* await new Promise(resolve => setTimeout(resolve, 100)); // Wait 0.1 seconds
|
|
122
|
+
* return {
|
|
123
|
+
* id: index,
|
|
124
|
+
* value: Math.random(),
|
|
125
|
+
* timestamp: new Date().toISOString()
|
|
126
|
+
* };
|
|
127
|
+
* });
|
|
128
|
+
* console.log('Generated data:', randomData);
|
|
129
|
+
* ```;
|
|
130
|
+
*
|
|
131
|
+
* @template T - The type of the result from each execution
|
|
132
|
+
* @param count - The number of times to repeat (non-negative integer)
|
|
133
|
+
* @param closure - The asynchronous function to execute repeatedly
|
|
134
|
+
* @returns A Promise resolving to an array of results
|
|
135
|
+
*/
|
|
136
|
+
const asyncRepeat: <T>(count: number, closure: (index: number) => Promise<T>) => Promise<T[]>;
|
|
137
|
+
/**
|
|
138
|
+
* Checks if at least one element in the array satisfies the given condition.
|
|
139
|
+
*
|
|
140
|
+
* Similar to JavaScript's native some() method. Returns true immediately when
|
|
141
|
+
* the first element satisfying the condition is found.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const numbers = [1, 3, 5, 7, 8, 9];
|
|
146
|
+
* const products = [
|
|
147
|
+
* { name: 'Apple', price: 100, inStock: true },
|
|
148
|
+
* { name: 'Banana', price: 50, inStock: false },
|
|
149
|
+
* { name: 'Orange', price: 80, inStock: true }
|
|
150
|
+
* ];
|
|
151
|
+
*
|
|
152
|
+
* const hasEvenNumber = ArrayUtil.has(numbers, num => num % 2 === 0);
|
|
153
|
+
* console.log(hasEvenNumber); // true (8 exists)
|
|
154
|
+
*
|
|
155
|
+
* const hasExpensiveItem = ArrayUtil.has(products, product => product.price > 90);
|
|
156
|
+
* console.log(hasExpensiveItem); // true (Apple costs 100)
|
|
157
|
+
*
|
|
158
|
+
* const hasOutOfStock = ArrayUtil.has(products, product => !product.inStock);
|
|
159
|
+
* console.log(hasOutOfStock); // true (Banana is out of stock)
|
|
160
|
+
* ```;
|
|
161
|
+
*
|
|
162
|
+
* @template T - The type of elements in the array
|
|
163
|
+
* @param elements - The readonly array to check
|
|
164
|
+
* @param pred - The predicate function to test elements
|
|
165
|
+
* @returns Boolean indicating if any element satisfies the condition
|
|
166
|
+
*/
|
|
167
|
+
const has: <T>(elements: readonly T[], pred: (elem: T) => boolean) => boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Executes a function a specified number of times and collects the results
|
|
170
|
+
* into an array.
|
|
171
|
+
*
|
|
172
|
+
* A synchronous repetition function that executes the given function for each
|
|
173
|
+
* index (from 0 to count-1) and collects the results into an array.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* // Generate an array of squares from 1 to 5
|
|
178
|
+
* const squares = ArrayUtil.repeat(5, index => (index + 1) ** 2);
|
|
179
|
+
* console.log(squares); // [1, 4, 9, 16, 25]
|
|
180
|
+
*
|
|
181
|
+
* // Generate an array of default user objects
|
|
182
|
+
* const users = ArrayUtil.repeat(3, index => ({
|
|
183
|
+
* id: index + 1,
|
|
184
|
+
* name: `User${index + 1}`,
|
|
185
|
+
* email: `user${index + 1}@example.com`
|
|
186
|
+
* }));
|
|
187
|
+
* console.log(users);
|
|
188
|
+
* // [
|
|
189
|
+
* // { id: 1, name: 'User1', email: 'user1@example.com' },
|
|
190
|
+
* // { id: 2, name: 'User2', email: 'user2@example.com' },
|
|
191
|
+
* // { id: 3, name: 'User3', email: 'user3@example.com' }
|
|
192
|
+
* // ]
|
|
193
|
+
* ```
|
|
194
|
+
*
|
|
195
|
+
* @template T - The type of the result from each execution
|
|
196
|
+
* @param count - The number of times to repeat (non-negative integer)
|
|
197
|
+
* @param closure - The function to execute repeatedly
|
|
198
|
+
* @returns An array of results
|
|
199
|
+
*/
|
|
200
|
+
const repeat: <T>(count: number, closure: (index: number) => T) => T[];
|
|
201
|
+
/**
|
|
202
|
+
* Generates all possible subsets of a given array.
|
|
203
|
+
*
|
|
204
|
+
* Implements the mathematical concept of power set, generating 2^n subsets
|
|
205
|
+
* from an array of n elements. Uses depth-first search (DFS) algorithm to
|
|
206
|
+
* calculate all possible combinations of including or excluding each
|
|
207
|
+
* element.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```typescript
|
|
211
|
+
* const numbers = [1, 2, 3];
|
|
212
|
+
* const allSubsets = ArrayUtil.subsets(numbers);
|
|
213
|
+
* console.log(allSubsets);
|
|
214
|
+
* // [
|
|
215
|
+
* // [], // empty set
|
|
216
|
+
* // [3], // {3}
|
|
217
|
+
* // [2], // {2}
|
|
218
|
+
* // [2, 3], // {2, 3}
|
|
219
|
+
* // [1], // {1}
|
|
220
|
+
* // [1, 3], // {1, 3}
|
|
221
|
+
* // [1, 2], // {1, 2}
|
|
222
|
+
* // [1, 2, 3] // {1, 2, 3}
|
|
223
|
+
* // ]
|
|
224
|
+
*
|
|
225
|
+
* const colors = ['red', 'blue'];
|
|
226
|
+
* const colorSubsets = ArrayUtil.subsets(colors);
|
|
227
|
+
* console.log(colorSubsets);
|
|
228
|
+
* // [
|
|
229
|
+
* // [],
|
|
230
|
+
* // ['blue'],
|
|
231
|
+
* // ['red'],
|
|
232
|
+
* // ['red', 'blue']
|
|
233
|
+
* // ]
|
|
234
|
+
*
|
|
235
|
+
* // Warning: Result size grows exponentially with array size
|
|
236
|
+
* // Example: 10 elements → 1,024 subsets, 20 elements → 1,048,576 subsets
|
|
237
|
+
* ```;
|
|
238
|
+
*
|
|
239
|
+
* @template T - The type of elements in the array
|
|
240
|
+
* @param array - The array to generate subsets from
|
|
241
|
+
* @returns An array containing all possible subsets
|
|
242
|
+
*/
|
|
243
|
+
const subsets: <T>(array: T[]) => T[][];
|
|
244
|
+
}
|
package/lib/ArrayUtil.js
ADDED
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.ArrayUtil = void 0;
|
|
13
|
+
/**
|
|
14
|
+
* A namespace providing utility functions for array manipulation.
|
|
15
|
+
*
|
|
16
|
+
* This namespace contains utility functions for array operations including
|
|
17
|
+
* asynchronous processing, filtering, mapping, and repetition tasks implemented
|
|
18
|
+
* in functional programming style. Functions use direct parameter passing for
|
|
19
|
+
* simplicity while maintaining functional programming principles.
|
|
20
|
+
*
|
|
21
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Asynchronous filtering example
|
|
25
|
+
* const numbers = [1, 2, 3, 4, 5];
|
|
26
|
+
* const evenNumbers = await ArrayUtil.asyncFilter(numbers,
|
|
27
|
+
* async (num) => num % 2 === 0
|
|
28
|
+
* );
|
|
29
|
+
* console.log(evenNumbers); // [2, 4]
|
|
30
|
+
* ```;
|
|
31
|
+
*/
|
|
32
|
+
var ArrayUtil;
|
|
33
|
+
(function (ArrayUtil) {
|
|
34
|
+
/**
|
|
35
|
+
* Filters an array by applying an asynchronous predicate function to each
|
|
36
|
+
* element.
|
|
37
|
+
*
|
|
38
|
+
* Elements are processed sequentially, ensuring order is maintained. The
|
|
39
|
+
* predicate function receives the element, index, and the full array as
|
|
40
|
+
* parameters.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const users = [
|
|
45
|
+
* { id: 1, name: 'Alice', active: true },
|
|
46
|
+
* { id: 2, name: 'Bob', active: false },
|
|
47
|
+
* { id: 3, name: 'Charlie', active: true }
|
|
48
|
+
* ];
|
|
49
|
+
*
|
|
50
|
+
* const activeUsers = await ArrayUtil.asyncFilter(users,
|
|
51
|
+
* async (user) => {
|
|
52
|
+
* // Async validation logic (e.g., API call)
|
|
53
|
+
* await new Promise(resolve => setTimeout(resolve, 100));
|
|
54
|
+
* return user.active;
|
|
55
|
+
* }
|
|
56
|
+
* );
|
|
57
|
+
* console.log(activeUsers); // [{ id: 1, name: 'Alice', active: true }, { id: 3, name: 'Charlie', active: true }]
|
|
58
|
+
* ```;
|
|
59
|
+
*
|
|
60
|
+
* @template Input - The type of elements in the input array
|
|
61
|
+
* @param elements - The readonly array to filter
|
|
62
|
+
* @param pred - The asynchronous predicate function to test each element
|
|
63
|
+
* @returns A Promise resolving to the filtered array
|
|
64
|
+
*/
|
|
65
|
+
ArrayUtil.asyncFilter = (elements, pred) => __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
const ret = [];
|
|
67
|
+
yield ArrayUtil.asyncForEach(elements, (elem, index, array) => __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
const flag = yield pred(elem, index, array);
|
|
69
|
+
if (flag === true)
|
|
70
|
+
ret.push(elem);
|
|
71
|
+
}));
|
|
72
|
+
return ret;
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* Executes an asynchronous function for each element in an array
|
|
76
|
+
* sequentially.
|
|
77
|
+
*
|
|
78
|
+
* Unlike JavaScript's native forEach, this function processes asynchronous
|
|
79
|
+
* functions sequentially and waits for all operations to complete. It
|
|
80
|
+
* performs sequential processing rather than parallel processing, making it
|
|
81
|
+
* suitable for operations where order matters.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const urls = ['url1', 'url2', 'url3'];
|
|
86
|
+
*
|
|
87
|
+
* await ArrayUtil.asyncForEach(urls, async (url, index) => {
|
|
88
|
+
* console.log(`Processing ${index}: ${url}`);
|
|
89
|
+
* const data = await fetch(url);
|
|
90
|
+
* await processData(data);
|
|
91
|
+
* console.log(`Completed ${index}: ${url}`);
|
|
92
|
+
* });
|
|
93
|
+
* console.log('All URLs processed sequentially');
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @template Input - The type of elements in the input array
|
|
97
|
+
* @param elements - The readonly array to process
|
|
98
|
+
* @param closure - The asynchronous function to execute for each element
|
|
99
|
+
* @returns A Promise<void> that resolves when all operations complete
|
|
100
|
+
*/
|
|
101
|
+
ArrayUtil.asyncForEach = (elements, closure) => __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
yield ArrayUtil.asyncRepeat(elements.length, (index) => closure(elements[index], index, elements));
|
|
103
|
+
});
|
|
104
|
+
/**
|
|
105
|
+
* Transforms each element of an array using an asynchronous function to
|
|
106
|
+
* create a new array.
|
|
107
|
+
*
|
|
108
|
+
* Similar to JavaScript's native map but processes asynchronous functions
|
|
109
|
+
* sequentially. Each element's transformation is completed before proceeding
|
|
110
|
+
* to the next element, ensuring order is maintained. This function still
|
|
111
|
+
* maintains the currying pattern for composition.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* const userIds = [1, 2, 3, 4, 5];
|
|
116
|
+
*
|
|
117
|
+
* const userDetails = await ArrayUtil.asyncMap(userIds)(
|
|
118
|
+
* async (id, index) => {
|
|
119
|
+
* console.log(`Fetching user ${id} (${index + 1}/${userIds.length})`);
|
|
120
|
+
* const response = await fetch(`/api/users/${id}`);
|
|
121
|
+
* return await response.json();
|
|
122
|
+
* }
|
|
123
|
+
* );
|
|
124
|
+
* console.log('All users fetched:', userDetails);
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* @template Input - The type of elements in the input array
|
|
128
|
+
* @param elements - The readonly array to transform
|
|
129
|
+
* @returns A function that takes a transformation function and returns a
|
|
130
|
+
* Promise resolving to the transformed array
|
|
131
|
+
*/
|
|
132
|
+
ArrayUtil.asyncMap = (elements, closure) => __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
const ret = [];
|
|
134
|
+
yield ArrayUtil.asyncForEach(elements, (elem, index, array) => __awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
const output = yield closure(elem, index, array);
|
|
136
|
+
ret.push(output);
|
|
137
|
+
}));
|
|
138
|
+
return ret;
|
|
139
|
+
});
|
|
140
|
+
/**
|
|
141
|
+
* Executes an asynchronous function a specified number of times sequentially.
|
|
142
|
+
*
|
|
143
|
+
* Executes the function with indices from 0 to count-1 incrementally. Each
|
|
144
|
+
* execution is performed sequentially, and all results are collected into an
|
|
145
|
+
* array.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* // Generate random data 5 times
|
|
150
|
+
* const randomData = await ArrayUtil.asyncRepeat(5, async (index) => {
|
|
151
|
+
* await new Promise(resolve => setTimeout(resolve, 100)); // Wait 0.1 seconds
|
|
152
|
+
* return {
|
|
153
|
+
* id: index,
|
|
154
|
+
* value: Math.random(),
|
|
155
|
+
* timestamp: new Date().toISOString()
|
|
156
|
+
* };
|
|
157
|
+
* });
|
|
158
|
+
* console.log('Generated data:', randomData);
|
|
159
|
+
* ```;
|
|
160
|
+
*
|
|
161
|
+
* @template T - The type of the result from each execution
|
|
162
|
+
* @param count - The number of times to repeat (non-negative integer)
|
|
163
|
+
* @param closure - The asynchronous function to execute repeatedly
|
|
164
|
+
* @returns A Promise resolving to an array of results
|
|
165
|
+
*/
|
|
166
|
+
ArrayUtil.asyncRepeat = (count, closure) => __awaiter(this, void 0, void 0, function* () {
|
|
167
|
+
const indexes = new Array(count).fill(1).map((_, index) => index);
|
|
168
|
+
const output = [];
|
|
169
|
+
for (const index of indexes)
|
|
170
|
+
output.push(yield closure(index));
|
|
171
|
+
return output;
|
|
172
|
+
});
|
|
173
|
+
/**
|
|
174
|
+
* Checks if at least one element in the array satisfies the given condition.
|
|
175
|
+
*
|
|
176
|
+
* Similar to JavaScript's native some() method. Returns true immediately when
|
|
177
|
+
* the first element satisfying the condition is found.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* const numbers = [1, 3, 5, 7, 8, 9];
|
|
182
|
+
* const products = [
|
|
183
|
+
* { name: 'Apple', price: 100, inStock: true },
|
|
184
|
+
* { name: 'Banana', price: 50, inStock: false },
|
|
185
|
+
* { name: 'Orange', price: 80, inStock: true }
|
|
186
|
+
* ];
|
|
187
|
+
*
|
|
188
|
+
* const hasEvenNumber = ArrayUtil.has(numbers, num => num % 2 === 0);
|
|
189
|
+
* console.log(hasEvenNumber); // true (8 exists)
|
|
190
|
+
*
|
|
191
|
+
* const hasExpensiveItem = ArrayUtil.has(products, product => product.price > 90);
|
|
192
|
+
* console.log(hasExpensiveItem); // true (Apple costs 100)
|
|
193
|
+
*
|
|
194
|
+
* const hasOutOfStock = ArrayUtil.has(products, product => !product.inStock);
|
|
195
|
+
* console.log(hasOutOfStock); // true (Banana is out of stock)
|
|
196
|
+
* ```;
|
|
197
|
+
*
|
|
198
|
+
* @template T - The type of elements in the array
|
|
199
|
+
* @param elements - The readonly array to check
|
|
200
|
+
* @param pred - The predicate function to test elements
|
|
201
|
+
* @returns Boolean indicating if any element satisfies the condition
|
|
202
|
+
*/
|
|
203
|
+
ArrayUtil.has = (elements, pred) => elements.find(pred) !== undefined;
|
|
204
|
+
/**
|
|
205
|
+
* Executes a function a specified number of times and collects the results
|
|
206
|
+
* into an array.
|
|
207
|
+
*
|
|
208
|
+
* A synchronous repetition function that executes the given function for each
|
|
209
|
+
* index (from 0 to count-1) and collects the results into an array.
|
|
210
|
+
*
|
|
211
|
+
* @example
|
|
212
|
+
* ```typescript
|
|
213
|
+
* // Generate an array of squares from 1 to 5
|
|
214
|
+
* const squares = ArrayUtil.repeat(5, index => (index + 1) ** 2);
|
|
215
|
+
* console.log(squares); // [1, 4, 9, 16, 25]
|
|
216
|
+
*
|
|
217
|
+
* // Generate an array of default user objects
|
|
218
|
+
* const users = ArrayUtil.repeat(3, index => ({
|
|
219
|
+
* id: index + 1,
|
|
220
|
+
* name: `User${index + 1}`,
|
|
221
|
+
* email: `user${index + 1}@example.com`
|
|
222
|
+
* }));
|
|
223
|
+
* console.log(users);
|
|
224
|
+
* // [
|
|
225
|
+
* // { id: 1, name: 'User1', email: 'user1@example.com' },
|
|
226
|
+
* // { id: 2, name: 'User2', email: 'user2@example.com' },
|
|
227
|
+
* // { id: 3, name: 'User3', email: 'user3@example.com' }
|
|
228
|
+
* // ]
|
|
229
|
+
* ```
|
|
230
|
+
*
|
|
231
|
+
* @template T - The type of the result from each execution
|
|
232
|
+
* @param count - The number of times to repeat (non-negative integer)
|
|
233
|
+
* @param closure - The function to execute repeatedly
|
|
234
|
+
* @returns An array of results
|
|
235
|
+
*/
|
|
236
|
+
ArrayUtil.repeat = (count, closure) => new Array(count).fill("").map((_, index) => closure(index));
|
|
237
|
+
/**
|
|
238
|
+
* Generates all possible subsets of a given array.
|
|
239
|
+
*
|
|
240
|
+
* Implements the mathematical concept of power set, generating 2^n subsets
|
|
241
|
+
* from an array of n elements. Uses depth-first search (DFS) algorithm to
|
|
242
|
+
* calculate all possible combinations of including or excluding each
|
|
243
|
+
* element.
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```typescript
|
|
247
|
+
* const numbers = [1, 2, 3];
|
|
248
|
+
* const allSubsets = ArrayUtil.subsets(numbers);
|
|
249
|
+
* console.log(allSubsets);
|
|
250
|
+
* // [
|
|
251
|
+
* // [], // empty set
|
|
252
|
+
* // [3], // {3}
|
|
253
|
+
* // [2], // {2}
|
|
254
|
+
* // [2, 3], // {2, 3}
|
|
255
|
+
* // [1], // {1}
|
|
256
|
+
* // [1, 3], // {1, 3}
|
|
257
|
+
* // [1, 2], // {1, 2}
|
|
258
|
+
* // [1, 2, 3] // {1, 2, 3}
|
|
259
|
+
* // ]
|
|
260
|
+
*
|
|
261
|
+
* const colors = ['red', 'blue'];
|
|
262
|
+
* const colorSubsets = ArrayUtil.subsets(colors);
|
|
263
|
+
* console.log(colorSubsets);
|
|
264
|
+
* // [
|
|
265
|
+
* // [],
|
|
266
|
+
* // ['blue'],
|
|
267
|
+
* // ['red'],
|
|
268
|
+
* // ['red', 'blue']
|
|
269
|
+
* // ]
|
|
270
|
+
*
|
|
271
|
+
* // Warning: Result size grows exponentially with array size
|
|
272
|
+
* // Example: 10 elements → 1,024 subsets, 20 elements → 1,048,576 subsets
|
|
273
|
+
* ```;
|
|
274
|
+
*
|
|
275
|
+
* @template T - The type of elements in the array
|
|
276
|
+
* @param array - The array to generate subsets from
|
|
277
|
+
* @returns An array containing all possible subsets
|
|
278
|
+
*/
|
|
279
|
+
ArrayUtil.subsets = (array) => {
|
|
280
|
+
const check = new Array(array.length).fill(false);
|
|
281
|
+
const output = [];
|
|
282
|
+
const dfs = (depth) => {
|
|
283
|
+
if (depth === check.length)
|
|
284
|
+
output.push(array.filter((_v, idx) => check[idx]));
|
|
285
|
+
else {
|
|
286
|
+
check[depth] = true;
|
|
287
|
+
dfs(depth + 1);
|
|
288
|
+
check[depth] = false;
|
|
289
|
+
dfs(depth + 1);
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
dfs(0);
|
|
293
|
+
return output;
|
|
294
|
+
};
|
|
295
|
+
})(ArrayUtil || (exports.ArrayUtil = ArrayUtil = {}));
|
|
296
|
+
//# sourceMappingURL=ArrayUtil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ArrayUtil.js","sourceRoot":"","sources":["../src/ArrayUtil.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Executor running prefixed functions.
|
|
3
|
+
*
|
|
4
|
+
* `DynamicExecutor` runs every (or some filtered) prefixed functions in a
|
|
5
|
+
* specific directory.
|
|
6
|
+
*
|
|
7
|
+
* For reference, it's useful for test program development of a backend server.
|
|
8
|
+
* Just write test functions under a directory, and just specify it.
|
|
9
|
+
* Furthermore, if you compose e2e test programs to utilize the `@nestia/sdk`
|
|
10
|
+
* generated API functions, you can take advantage of {@link DynamicBenchmarker}
|
|
11
|
+
* at the same time.
|
|
12
|
+
*
|
|
13
|
+
* When you want to see some utilization cases, see the below example links.
|
|
14
|
+
*
|
|
15
|
+
* @author Jeongho Nam - https://github.com/samchon
|
|
16
|
+
* @example
|
|
17
|
+
* https://github.com/samchon/nestia-start/blob/master/test/index.ts
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* https://github.com/samchon/backend/blob/master/test/index.ts
|
|
21
|
+
*/
|
|
22
|
+
export declare namespace DynamicExecutor {
|
|
23
|
+
/**
|
|
24
|
+
* Function type of a prefixed.
|
|
25
|
+
*
|
|
26
|
+
* @template Arguments Type of parameters
|
|
27
|
+
* @template Ret Type of return value
|
|
28
|
+
*/
|
|
29
|
+
interface Closure<Arguments extends any[], Ret = any> {
|
|
30
|
+
(...args: Arguments): Promise<Ret>;
|
|
31
|
+
}
|
|
32
|
+
/** Options for dynamic executor. */
|
|
33
|
+
interface IProps<Parameters extends any[], Ret = any> {
|
|
34
|
+
/**
|
|
35
|
+
* Prefix of function name.
|
|
36
|
+
*
|
|
37
|
+
* Every prefixed function will be executed.
|
|
38
|
+
*
|
|
39
|
+
* In other words, if a function name doesn't start with the prefix, then it
|
|
40
|
+
* would never be executed.
|
|
41
|
+
*/
|
|
42
|
+
prefix: string;
|
|
43
|
+
/** Location of the test functions. */
|
|
44
|
+
location: string;
|
|
45
|
+
/**
|
|
46
|
+
* Get parameters of a function.
|
|
47
|
+
*
|
|
48
|
+
* @param name Function name
|
|
49
|
+
* @returns Parameters
|
|
50
|
+
*/
|
|
51
|
+
parameters: (name: string) => Parameters;
|
|
52
|
+
/**
|
|
53
|
+
* On complete function.
|
|
54
|
+
*
|
|
55
|
+
* Listener of completion of a test function.
|
|
56
|
+
*
|
|
57
|
+
* @param exec Execution result of a test function
|
|
58
|
+
*/
|
|
59
|
+
onComplete?: (exec: IExecution) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Filter function whether to run or not.
|
|
62
|
+
*
|
|
63
|
+
* @param name Function name
|
|
64
|
+
* @returns Whether to run or not
|
|
65
|
+
*/
|
|
66
|
+
filter?: (name: string) => boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Wrapper of test function.
|
|
69
|
+
*
|
|
70
|
+
* If you specify this `wrapper` property, every dynamic functions loaded
|
|
71
|
+
* and called by this `DynamicExecutor` would be wrapped by the `wrapper`
|
|
72
|
+
* function.
|
|
73
|
+
*
|
|
74
|
+
* @param name Function name
|
|
75
|
+
* @param closure Function to be executed
|
|
76
|
+
* @param parameters Parameters, result of options.parameters function.
|
|
77
|
+
* @returns Wrapper function
|
|
78
|
+
*/
|
|
79
|
+
wrapper?: (name: string, closure: Closure<Parameters, Ret>, parameters: Parameters) => Promise<any>;
|
|
80
|
+
/**
|
|
81
|
+
* Number of simultaneous requests.
|
|
82
|
+
*
|
|
83
|
+
* The number of requests to be executed simultaneously.
|
|
84
|
+
*
|
|
85
|
+
* If you configure a value greater than one, the dynamic executor will
|
|
86
|
+
* process the functions concurrently with the given capacity value.
|
|
87
|
+
*
|
|
88
|
+
* @default 1
|
|
89
|
+
*/
|
|
90
|
+
simultaneous?: number;
|
|
91
|
+
/**
|
|
92
|
+
* Extension of dynamic functions.
|
|
93
|
+
*
|
|
94
|
+
* @default js
|
|
95
|
+
*/
|
|
96
|
+
extension?: string;
|
|
97
|
+
}
|
|
98
|
+
/** Report, result of dynamic execution. */
|
|
99
|
+
interface IReport {
|
|
100
|
+
/** Location path of dynamic functions. */
|
|
101
|
+
location: string;
|
|
102
|
+
/** Execution results of dynamic functions. */
|
|
103
|
+
executions: IExecution[];
|
|
104
|
+
/** Total elapsed time. */
|
|
105
|
+
time: number;
|
|
106
|
+
}
|
|
107
|
+
/** Execution of a test function. */
|
|
108
|
+
interface IExecution {
|
|
109
|
+
/** Name of function. */
|
|
110
|
+
name: string;
|
|
111
|
+
/** Location path of the function. */
|
|
112
|
+
location: string;
|
|
113
|
+
/** Returned value from the function. */
|
|
114
|
+
value: unknown;
|
|
115
|
+
/** Error when occurred. */
|
|
116
|
+
error: Error | null;
|
|
117
|
+
/** Elapsed time. */
|
|
118
|
+
started_at: string;
|
|
119
|
+
/** Completion time. */
|
|
120
|
+
completed_at: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Prepare dynamic executor in strict mode.
|
|
124
|
+
*
|
|
125
|
+
* In strict mode, if any error occurs, the program will be terminated
|
|
126
|
+
* directly. Otherwise, {@link validate} mode does not terminate when error
|
|
127
|
+
* occurs, but just archive the error log.
|
|
128
|
+
*
|
|
129
|
+
* @param props Properties of dynamic execution
|
|
130
|
+
* @returns Report of dynamic test functions execution
|
|
131
|
+
*/
|
|
132
|
+
const assert: <Arguments extends any[]>(props: IProps<Arguments>) => Promise<IReport>;
|
|
133
|
+
/**
|
|
134
|
+
* Prepare dynamic executor in loose mode.
|
|
135
|
+
*
|
|
136
|
+
* In loose mode, the program would not be terminated even when error occurs.
|
|
137
|
+
* Instead, the error would be archived and returns as a list. Otherwise,
|
|
138
|
+
* {@link assert} mode terminates the program directly when error occurs.
|
|
139
|
+
*
|
|
140
|
+
* @param props Properties of dynamic executor
|
|
141
|
+
* @returns Report of dynamic test functions execution
|
|
142
|
+
*/
|
|
143
|
+
const validate: <Arguments extends any[]>(props: IProps<Arguments>) => Promise<IReport>;
|
|
144
|
+
}
|