@nestia/e2e 8.1.0 → 9.0.0-dev.20251107

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/src/ArrayUtil.ts CHANGED
@@ -1,320 +1,320 @@
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 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
- export const asyncFilter = async <Input>(
53
- elements: readonly Input[],
54
- pred: (
55
- elem: Input,
56
- index: number,
57
- array: readonly Input[],
58
- ) => Promise<boolean>,
59
- ): Promise<Input[]> => {
60
- const ret: Input[] = [];
61
- await asyncForEach(elements, async (elem, index, array) => {
62
- const flag: boolean = await pred(elem, index, array);
63
- if (flag === true) ret.push(elem);
64
- });
65
- return ret;
66
- };
67
-
68
- /**
69
- * Executes an asynchronous function for each element in an array
70
- * sequentially.
71
- *
72
- * Unlike JavaScript's native forEach, this function processes asynchronous
73
- * functions sequentially and waits for all operations to complete. It
74
- * performs sequential processing rather than parallel processing, making it
75
- * suitable for operations where order matters.
76
- *
77
- * @example
78
- * ```typescript
79
- * const urls = ['url1', 'url2', 'url3'];
80
- *
81
- * await ArrayUtil.asyncForEach(urls, async (url, index) => {
82
- * console.log(`Processing ${index}: ${url}`);
83
- * const data = await fetch(url);
84
- * await processData(data);
85
- * console.log(`Completed ${index}: ${url}`);
86
- * });
87
- * console.log('All URLs processed sequentially');
88
- * ```
89
- *
90
- * @template Input - The type of elements in the input array
91
- * @param elements - The readonly array to process
92
- * @param closure - The asynchronous function to execute for each element
93
- * @returns A Promise<void> that resolves when all operations complete
94
- */
95
- export const asyncForEach = async <Input>(
96
- elements: readonly Input[],
97
- closure: (
98
- elem: Input,
99
- index: number,
100
- array: readonly Input[],
101
- ) => Promise<any>,
102
- ): Promise<void> => {
103
- await asyncRepeat(elements.length, (index) =>
104
- closure(elements[index], index, elements),
105
- );
106
- };
107
-
108
- /**
109
- * Transforms each element of an array using an asynchronous function to
110
- * create a new array.
111
- *
112
- * Similar to JavaScript's native map but processes asynchronous functions
113
- * sequentially. Each element's transformation is completed before proceeding
114
- * to the next element, ensuring order is maintained. This function still
115
- * maintains the currying pattern for composition.
116
- *
117
- * @example
118
- * ```typescript
119
- * const userIds = [1, 2, 3, 4, 5];
120
- *
121
- * const userDetails = await ArrayUtil.asyncMap(userIds)(
122
- * async (id, index) => {
123
- * console.log(`Fetching user ${id} (${index + 1}/${userIds.length})`);
124
- * const response = await fetch(`/api/users/${id}`);
125
- * return await response.json();
126
- * }
127
- * );
128
- * console.log('All users fetched:', userDetails);
129
- * ```
130
- *
131
- * @template Input - The type of elements in the input array
132
- * @param elements - The readonly array to transform
133
- * @returns A function that takes a transformation function and returns a
134
- * Promise resolving to the transformed array
135
- */
136
- export const asyncMap = async <Input, Output>(
137
- elements: readonly Input[],
138
- closure: (
139
- elem: Input,
140
- index: number,
141
- array: readonly Input[],
142
- ) => Promise<Output>,
143
- ): Promise<Output[]> => {
144
- const ret: Output[] = [];
145
- await asyncForEach(elements, async (elem, index, array) => {
146
- const output: Output = await closure(elem, index, array);
147
- ret.push(output);
148
- });
149
- return ret;
150
- };
151
-
152
- /**
153
- * Executes an asynchronous function a specified number of times sequentially.
154
- *
155
- * Executes the function with indices from 0 to count-1 incrementally. Each
156
- * execution is performed sequentially, and all results are collected into an
157
- * array.
158
- *
159
- * @example
160
- * ```typescript
161
- * // Generate random data 5 times
162
- * const randomData = await ArrayUtil.asyncRepeat(5, async (index) => {
163
- * await new Promise(resolve => setTimeout(resolve, 100)); // Wait 0.1 seconds
164
- * return {
165
- * id: index,
166
- * value: Math.random(),
167
- * timestamp: new Date().toISOString()
168
- * };
169
- * });
170
- * console.log('Generated data:', randomData);
171
- * ```;
172
- *
173
- * @template T - The type of the result from each execution
174
- * @param count - The number of times to repeat (non-negative integer)
175
- * @param closure - The asynchronous function to execute repeatedly
176
- * @returns A Promise resolving to an array of results
177
- */
178
- export const asyncRepeat = async <T>(
179
- count: number,
180
- closure: (index: number) => Promise<T>,
181
- ): Promise<T[]> => {
182
- const indexes: number[] = new Array(count).fill(1).map((_, index) => index);
183
- const output: T[] = [];
184
- for (const index of indexes) output.push(await closure(index));
185
- return output;
186
- };
187
-
188
- /**
189
- * Checks if at least one element in the array satisfies the given condition.
190
- *
191
- * Similar to JavaScript's native some() method. Returns true immediately when
192
- * the first element satisfying the condition is found.
193
- *
194
- * @example
195
- * ```typescript
196
- * const numbers = [1, 3, 5, 7, 8, 9];
197
- * const products = [
198
- * { name: 'Apple', price: 100, inStock: true },
199
- * { name: 'Banana', price: 50, inStock: false },
200
- * { name: 'Orange', price: 80, inStock: true }
201
- * ];
202
- *
203
- * const hasEvenNumber = ArrayUtil.has(numbers, num => num % 2 === 0);
204
- * console.log(hasEvenNumber); // true (8 exists)
205
- *
206
- * const hasExpensiveItem = ArrayUtil.has(products, product => product.price > 90);
207
- * console.log(hasExpensiveItem); // true (Apple costs 100)
208
- *
209
- * const hasOutOfStock = ArrayUtil.has(products, product => !product.inStock);
210
- * console.log(hasOutOfStock); // true (Banana is out of stock)
211
- * ```;
212
- *
213
- * @template T - The type of elements in the array
214
- * @param elements - The readonly array to check
215
- * @param pred - The predicate function to test elements
216
- * @returns Boolean indicating if any element satisfies the condition
217
- */
218
- export const has = <T>(
219
- elements: readonly T[],
220
- pred: (elem: T) => boolean,
221
- ): boolean => elements.find(pred) !== undefined;
222
-
223
- /**
224
- * Executes a function a specified number of times and collects the results
225
- * into an array.
226
- *
227
- * A synchronous repetition function that executes the given function for each
228
- * index (from 0 to count-1) and collects the results into an array.
229
- *
230
- * @example
231
- * ```typescript
232
- * // Generate an array of squares from 1 to 5
233
- * const squares = ArrayUtil.repeat(5, index => (index + 1) ** 2);
234
- * console.log(squares); // [1, 4, 9, 16, 25]
235
- *
236
- * // Generate an array of default user objects
237
- * const users = ArrayUtil.repeat(3, index => ({
238
- * id: index + 1,
239
- * name: `User${index + 1}`,
240
- * email: `user${index + 1}@example.com`
241
- * }));
242
- * console.log(users);
243
- * // [
244
- * // { id: 1, name: 'User1', email: 'user1@example.com' },
245
- * // { id: 2, name: 'User2', email: 'user2@example.com' },
246
- * // { id: 3, name: 'User3', email: 'user3@example.com' }
247
- * // ]
248
- * ```
249
- *
250
- * @template T - The type of the result from each execution
251
- * @param count - The number of times to repeat (non-negative integer)
252
- * @param closure - The function to execute repeatedly
253
- * @returns An array of results
254
- */
255
- export const repeat = <T>(
256
- count: number,
257
- closure: (index: number) => T,
258
- ): T[] => new Array(count).fill("").map((_, index) => closure(index));
259
-
260
- /**
261
- * Generates all possible subsets of a given array.
262
- *
263
- * Implements the mathematical concept of power set, generating 2^n subsets
264
- * from an array of n elements. Uses depth-first search (DFS) algorithm to
265
- * calculate all possible combinations of including or excluding each
266
- * element.
267
- *
268
- * @example
269
- * ```typescript
270
- * const numbers = [1, 2, 3];
271
- * const allSubsets = ArrayUtil.subsets(numbers);
272
- * console.log(allSubsets);
273
- * // [
274
- * // [], // empty set
275
- * // [3], // {3}
276
- * // [2], // {2}
277
- * // [2, 3], // {2, 3}
278
- * // [1], // {1}
279
- * // [1, 3], // {1, 3}
280
- * // [1, 2], // {1, 2}
281
- * // [1, 2, 3] // {1, 2, 3}
282
- * // ]
283
- *
284
- * const colors = ['red', 'blue'];
285
- * const colorSubsets = ArrayUtil.subsets(colors);
286
- * console.log(colorSubsets);
287
- * // [
288
- * // [],
289
- * // ['blue'],
290
- * // ['red'],
291
- * // ['red', 'blue']
292
- * // ]
293
- *
294
- * // Warning: Result size grows exponentially with array size
295
- * // Example: 10 elements → 1,024 subsets, 20 elements → 1,048,576 subsets
296
- * ```;
297
- *
298
- * @template T - The type of elements in the array
299
- * @param array - The array to generate subsets from
300
- * @returns An array containing all possible subsets
301
- */
302
- export const subsets = <T>(array: T[]): T[][] => {
303
- const check: boolean[] = new Array(array.length).fill(false);
304
- const output: T[][] = [];
305
-
306
- const dfs = (depth: number): void => {
307
- if (depth === check.length)
308
- output.push(array.filter((_v, idx) => check[idx]));
309
- else {
310
- check[depth] = true;
311
- dfs(depth + 1);
312
-
313
- check[depth] = false;
314
- dfs(depth + 1);
315
- }
316
- };
317
- dfs(0);
318
- return output;
319
- };
320
- }
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 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
+ export const asyncFilter = async <Input>(
53
+ elements: readonly Input[],
54
+ pred: (
55
+ elem: Input,
56
+ index: number,
57
+ array: readonly Input[],
58
+ ) => Promise<boolean>,
59
+ ): Promise<Input[]> => {
60
+ const ret: Input[] = [];
61
+ await asyncForEach(elements, async (elem, index, array) => {
62
+ const flag: boolean = await pred(elem, index, array);
63
+ if (flag === true) ret.push(elem);
64
+ });
65
+ return ret;
66
+ };
67
+
68
+ /**
69
+ * Executes an asynchronous function for each element in an array
70
+ * sequentially.
71
+ *
72
+ * Unlike JavaScript's native forEach, this function processes asynchronous
73
+ * functions sequentially and waits for all operations to complete. It
74
+ * performs sequential processing rather than parallel processing, making it
75
+ * suitable for operations where order matters.
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const urls = ['url1', 'url2', 'url3'];
80
+ *
81
+ * await ArrayUtil.asyncForEach(urls, async (url, index) => {
82
+ * console.log(`Processing ${index}: ${url}`);
83
+ * const data = await fetch(url);
84
+ * await processData(data);
85
+ * console.log(`Completed ${index}: ${url}`);
86
+ * });
87
+ * console.log('All URLs processed sequentially');
88
+ * ```
89
+ *
90
+ * @template Input - The type of elements in the input array
91
+ * @param elements - The readonly array to process
92
+ * @param closure - The asynchronous function to execute for each element
93
+ * @returns A Promise<void> that resolves when all operations complete
94
+ */
95
+ export const asyncForEach = async <Input>(
96
+ elements: readonly Input[],
97
+ closure: (
98
+ elem: Input,
99
+ index: number,
100
+ array: readonly Input[],
101
+ ) => Promise<any>,
102
+ ): Promise<void> => {
103
+ await asyncRepeat(elements.length, (index) =>
104
+ closure(elements[index], index, elements),
105
+ );
106
+ };
107
+
108
+ /**
109
+ * Transforms each element of an array using an asynchronous function to
110
+ * create a new array.
111
+ *
112
+ * Similar to JavaScript's native map but processes asynchronous functions
113
+ * sequentially. Each element's transformation is completed before proceeding
114
+ * to the next element, ensuring order is maintained. This function still
115
+ * maintains the currying pattern for composition.
116
+ *
117
+ * @example
118
+ * ```typescript
119
+ * const userIds = [1, 2, 3, 4, 5];
120
+ *
121
+ * const userDetails = await ArrayUtil.asyncMap(userIds)(
122
+ * async (id, index) => {
123
+ * console.log(`Fetching user ${id} (${index + 1}/${userIds.length})`);
124
+ * const response = await fetch(`/api/users/${id}`);
125
+ * return await response.json();
126
+ * }
127
+ * );
128
+ * console.log('All users fetched:', userDetails);
129
+ * ```
130
+ *
131
+ * @template Input - The type of elements in the input array
132
+ * @param elements - The readonly array to transform
133
+ * @returns A function that takes a transformation function and returns a
134
+ * Promise resolving to the transformed array
135
+ */
136
+ export const asyncMap = async <Input, Output>(
137
+ elements: readonly Input[],
138
+ closure: (
139
+ elem: Input,
140
+ index: number,
141
+ array: readonly Input[],
142
+ ) => Promise<Output>,
143
+ ): Promise<Output[]> => {
144
+ const ret: Output[] = [];
145
+ await asyncForEach(elements, async (elem, index, array) => {
146
+ const output: Output = await closure(elem, index, array);
147
+ ret.push(output);
148
+ });
149
+ return ret;
150
+ };
151
+
152
+ /**
153
+ * Executes an asynchronous function a specified number of times sequentially.
154
+ *
155
+ * Executes the function with indices from 0 to count-1 incrementally. Each
156
+ * execution is performed sequentially, and all results are collected into an
157
+ * array.
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * // Generate random data 5 times
162
+ * const randomData = await ArrayUtil.asyncRepeat(5, async (index) => {
163
+ * await new Promise(resolve => setTimeout(resolve, 100)); // Wait 0.1 seconds
164
+ * return {
165
+ * id: index,
166
+ * value: Math.random(),
167
+ * timestamp: new Date().toISOString()
168
+ * };
169
+ * });
170
+ * console.log('Generated data:', randomData);
171
+ * ```;
172
+ *
173
+ * @template T - The type of the result from each execution
174
+ * @param count - The number of times to repeat (non-negative integer)
175
+ * @param closure - The asynchronous function to execute repeatedly
176
+ * @returns A Promise resolving to an array of results
177
+ */
178
+ export const asyncRepeat = async <T>(
179
+ count: number,
180
+ closure: (index: number) => Promise<T>,
181
+ ): Promise<T[]> => {
182
+ const indexes: number[] = new Array(count).fill(1).map((_, index) => index);
183
+ const output: T[] = [];
184
+ for (const index of indexes) output.push(await closure(index));
185
+ return output;
186
+ };
187
+
188
+ /**
189
+ * Checks if at least one element in the array satisfies the given condition.
190
+ *
191
+ * Similar to JavaScript's native some() method. Returns true immediately when
192
+ * the first element satisfying the condition is found.
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * const numbers = [1, 3, 5, 7, 8, 9];
197
+ * const products = [
198
+ * { name: 'Apple', price: 100, inStock: true },
199
+ * { name: 'Banana', price: 50, inStock: false },
200
+ * { name: 'Orange', price: 80, inStock: true }
201
+ * ];
202
+ *
203
+ * const hasEvenNumber = ArrayUtil.has(numbers, num => num % 2 === 0);
204
+ * console.log(hasEvenNumber); // true (8 exists)
205
+ *
206
+ * const hasExpensiveItem = ArrayUtil.has(products, product => product.price > 90);
207
+ * console.log(hasExpensiveItem); // true (Apple costs 100)
208
+ *
209
+ * const hasOutOfStock = ArrayUtil.has(products, product => !product.inStock);
210
+ * console.log(hasOutOfStock); // true (Banana is out of stock)
211
+ * ```;
212
+ *
213
+ * @template T - The type of elements in the array
214
+ * @param elements - The readonly array to check
215
+ * @param pred - The predicate function to test elements
216
+ * @returns Boolean indicating if any element satisfies the condition
217
+ */
218
+ export const has = <T>(
219
+ elements: readonly T[],
220
+ pred: (elem: T) => boolean,
221
+ ): boolean => elements.find(pred) !== undefined;
222
+
223
+ /**
224
+ * Executes a function a specified number of times and collects the results
225
+ * into an array.
226
+ *
227
+ * A synchronous repetition function that executes the given function for each
228
+ * index (from 0 to count-1) and collects the results into an array.
229
+ *
230
+ * @example
231
+ * ```typescript
232
+ * // Generate an array of squares from 1 to 5
233
+ * const squares = ArrayUtil.repeat(5, index => (index + 1) ** 2);
234
+ * console.log(squares); // [1, 4, 9, 16, 25]
235
+ *
236
+ * // Generate an array of default user objects
237
+ * const users = ArrayUtil.repeat(3, index => ({
238
+ * id: index + 1,
239
+ * name: `User${index + 1}`,
240
+ * email: `user${index + 1}@example.com`
241
+ * }));
242
+ * console.log(users);
243
+ * // [
244
+ * // { id: 1, name: 'User1', email: 'user1@example.com' },
245
+ * // { id: 2, name: 'User2', email: 'user2@example.com' },
246
+ * // { id: 3, name: 'User3', email: 'user3@example.com' }
247
+ * // ]
248
+ * ```
249
+ *
250
+ * @template T - The type of the result from each execution
251
+ * @param count - The number of times to repeat (non-negative integer)
252
+ * @param closure - The function to execute repeatedly
253
+ * @returns An array of results
254
+ */
255
+ export const repeat = <T>(
256
+ count: number,
257
+ closure: (index: number) => T,
258
+ ): T[] => new Array(count).fill("").map((_, index) => closure(index));
259
+
260
+ /**
261
+ * Generates all possible subsets of a given array.
262
+ *
263
+ * Implements the mathematical concept of power set, generating 2^n subsets
264
+ * from an array of n elements. Uses depth-first search (DFS) algorithm to
265
+ * calculate all possible combinations of including or excluding each
266
+ * element.
267
+ *
268
+ * @example
269
+ * ```typescript
270
+ * const numbers = [1, 2, 3];
271
+ * const allSubsets = ArrayUtil.subsets(numbers);
272
+ * console.log(allSubsets);
273
+ * // [
274
+ * // [], // empty set
275
+ * // [3], // {3}
276
+ * // [2], // {2}
277
+ * // [2, 3], // {2, 3}
278
+ * // [1], // {1}
279
+ * // [1, 3], // {1, 3}
280
+ * // [1, 2], // {1, 2}
281
+ * // [1, 2, 3] // {1, 2, 3}
282
+ * // ]
283
+ *
284
+ * const colors = ['red', 'blue'];
285
+ * const colorSubsets = ArrayUtil.subsets(colors);
286
+ * console.log(colorSubsets);
287
+ * // [
288
+ * // [],
289
+ * // ['blue'],
290
+ * // ['red'],
291
+ * // ['red', 'blue']
292
+ * // ]
293
+ *
294
+ * // Warning: Result size grows exponentially with array size
295
+ * // Example: 10 elements → 1,024 subsets, 20 elements → 1,048,576 subsets
296
+ * ```;
297
+ *
298
+ * @template T - The type of elements in the array
299
+ * @param array - The array to generate subsets from
300
+ * @returns An array containing all possible subsets
301
+ */
302
+ export const subsets = <T>(array: T[]): T[][] => {
303
+ const check: boolean[] = new Array(array.length).fill(false);
304
+ const output: T[][] = [];
305
+
306
+ const dfs = (depth: number): void => {
307
+ if (depth === check.length)
308
+ output.push(array.filter((_v, idx) => check[idx]));
309
+ else {
310
+ check[depth] = true;
311
+ dfs(depth + 1);
312
+
313
+ check[depth] = false;
314
+ dfs(depth + 1);
315
+ }
316
+ };
317
+ dfs(0);
318
+ return output;
319
+ };
320
+ }