@nestia/e2e 14.0.0 → 14.0.2
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/README.md +1 -1
- package/lib/ArrayUtil.d.ts +152 -70
- package/lib/ArrayUtil.js +169 -75
- package/lib/ArrayUtil.js.map +1 -1
- package/lib/DynamicExecutor.d.ts +139 -11
- package/lib/DynamicExecutor.js +98 -10
- package/lib/DynamicExecutor.js.map +1 -1
- package/lib/GaffComparator.d.ts +176 -73
- package/lib/GaffComparator.js +196 -77
- package/lib/GaffComparator.js.map +1 -1
- package/lib/MapUtil.d.ts +37 -6
- package/lib/MapUtil.js +37 -6
- package/lib/MapUtil.js.map +1 -1
- package/lib/RandomGenerator.d.ts +157 -84
- package/lib/RandomGenerator.js +173 -89
- package/lib/RandomGenerator.js.map +1 -1
- package/lib/TestValidator.d.ts +253 -74
- package/lib/TestValidator.js +274 -97
- package/lib/TestValidator.js.map +1 -1
- package/lib/internal/json_equal_to.d.ts +21 -0
- package/lib/internal/json_equal_to.js +35 -6
- package/lib/internal/json_equal_to.js.map +1 -1
- package/package.json +3 -2
- package/src/ArrayUtil.ts +173 -77
- package/src/DynamicExecutor.ts +158 -15
- package/src/GaffComparator.ts +195 -77
- package/src/MapUtil.ts +37 -6
- package/src/RandomGenerator.ts +172 -89
- package/src/TestValidator.ts +302 -107
- package/src/internal/json_equal_to.ts +36 -4
package/lib/GaffComparator.js
CHANGED
|
@@ -25,27 +25,40 @@ exports.GaffComparator = void 0;
|
|
|
25
25
|
* - Return > 0 if first element should come after second
|
|
26
26
|
* - Return 0 if elements are equal
|
|
27
27
|
*
|
|
28
|
+
* Processing cost: Each comparison extracts both key lists and visits their
|
|
29
|
+
* common prefix until the first difference; date keys additionally parse all
|
|
30
|
+
* supplied strings once per comparison. No sort or repeated scan is performed
|
|
31
|
+
* inside a comparison.
|
|
32
|
+
*
|
|
28
33
|
* @author Jeongho Nam - https://github.com/samchon
|
|
29
34
|
* @example
|
|
30
|
-
* ```typescript
|
|
31
35
|
* // Basic usage with single fields
|
|
32
|
-
* users.sort(GaffComparator.strings(user => user.name));
|
|
33
|
-
* posts.sort(GaffComparator.dates(post => post.createdAt));
|
|
34
|
-
* products.sort(GaffComparator.numbers(product => product.price));
|
|
36
|
+
* users.sort(GaffComparator.strings((user) => user.name));
|
|
37
|
+
* posts.sort(GaffComparator.dates((post) => post.createdAt));
|
|
38
|
+
* products.sort(GaffComparator.numbers((product) => product.price));
|
|
35
39
|
*
|
|
36
40
|
* // Multi-field sorting with arrays
|
|
37
|
-
* users.sort(
|
|
38
|
-
*
|
|
41
|
+
* users.sort(
|
|
42
|
+
* GaffComparator.strings((user) => [user.lastName, user.firstName]),
|
|
43
|
+
* );
|
|
44
|
+
* events.sort(
|
|
45
|
+
* GaffComparator.dates((event) => [event.startDate, event.endDate]),
|
|
46
|
+
* );
|
|
39
47
|
*
|
|
40
48
|
* // Integration with TestValidator's currying pattern
|
|
41
|
-
* const validator = TestValidator.sort("user sorting",
|
|
42
|
-
*
|
|
43
|
-
* )(
|
|
44
|
-
*
|
|
45
|
-
*
|
|
49
|
+
* const validator = TestValidator.sort("user sorting", (sortable) =>
|
|
50
|
+
* api.getUsers({ sort: sortable }),
|
|
51
|
+
* )(
|
|
52
|
+
* "name",
|
|
53
|
+
* "email",
|
|
54
|
+
* )(GaffComparator.strings((user) => [user.name, user.email]));
|
|
46
55
|
* await validator("+"); // ascending
|
|
47
56
|
* await validator("-"); // descending
|
|
48
|
-
*
|
|
57
|
+
*
|
|
58
|
+
* @evidence contracts/common.md#principled-implementation Each comparator maps both operands to arrays of comparable values and decides by the first position where they differ, then by array length, which is a lexicographic order that satisfies the sort contract for well-defined values; it is used to check server-side sorting from the client.
|
|
59
|
+
* @evidence contracts/common.md#clear-and-simple-design Three comparators share scalar-to-array wrapping. Strings compare each key by collation; dates and numbers use a shared strict mismatch search over their numeric keys.
|
|
60
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The ordering rule is generic in the getter, with no field, entity, or locale special case.
|
|
61
|
+
* @evidence contracts/common.md#meaningful-documentation The namespace prose lists the features and the sort contract with an example.
|
|
49
62
|
*/
|
|
50
63
|
var GaffComparator;
|
|
51
64
|
(function (GaffComparator) {
|
|
@@ -60,58 +73,99 @@ var GaffComparator;
|
|
|
60
73
|
*
|
|
61
74
|
* When comparing arrays, performs lexicographic ordering: compares the first
|
|
62
75
|
* elements, then the second elements if the first are equal, and so on. This
|
|
63
|
-
* enables complex sorting like "sort by last name, then by first name".
|
|
76
|
+
* enables complex sorting like "sort by last name, then by first name". Keys
|
|
77
|
+
* that compare equal under the runtime's collation, including different
|
|
78
|
+
* canonically equivalent Unicode spellings, continue to the next key. If the
|
|
79
|
+
* whole common prefix compares equal, the shorter key list sorts first.
|
|
80
|
+
*
|
|
81
|
+
* Processing cost: Both getters run once and a bounded loop visits only
|
|
82
|
+
* common keys until the first collation difference. Work depends on examined
|
|
83
|
+
* keys and string comparison cost; scalar wrapping adds constant space.
|
|
64
84
|
*
|
|
65
85
|
* @example
|
|
66
|
-
* ```typescript
|
|
67
86
|
* interface User {
|
|
68
87
|
* id: string;
|
|
69
88
|
* firstName: string;
|
|
70
89
|
* lastName: string;
|
|
71
90
|
* email: string;
|
|
72
|
-
* status:
|
|
91
|
+
* status: "active" | "inactive";
|
|
73
92
|
* }
|
|
74
93
|
*
|
|
75
94
|
* const users: User[] = [
|
|
76
|
-
* {
|
|
77
|
-
*
|
|
78
|
-
*
|
|
95
|
+
* {
|
|
96
|
+
* id: "1",
|
|
97
|
+
* firstName: "John",
|
|
98
|
+
* lastName: "Doe",
|
|
99
|
+
* email: "john@example.com",
|
|
100
|
+
* status: "active",
|
|
101
|
+
* },
|
|
102
|
+
* {
|
|
103
|
+
* id: "2",
|
|
104
|
+
* firstName: "Jane",
|
|
105
|
+
* lastName: "Doe",
|
|
106
|
+
* email: "jane@example.com",
|
|
107
|
+
* status: "inactive",
|
|
108
|
+
* },
|
|
109
|
+
* {
|
|
110
|
+
* id: "3",
|
|
111
|
+
* firstName: "Bob",
|
|
112
|
+
* lastName: "Smith",
|
|
113
|
+
* email: "bob@example.com",
|
|
114
|
+
* status: "active",
|
|
115
|
+
* },
|
|
79
116
|
* ];
|
|
80
117
|
*
|
|
81
118
|
* // Single field sorting
|
|
82
|
-
* users.sort(GaffComparator.strings(user => user.lastName));
|
|
119
|
+
* users.sort(GaffComparator.strings((user) => user.lastName));
|
|
83
120
|
* // Result: Doe, Doe, Smith
|
|
84
121
|
*
|
|
85
122
|
* // Multi-field sorting: last name, then first name
|
|
86
|
-
* users.sort(
|
|
123
|
+
* users.sort(
|
|
124
|
+
* GaffComparator.strings((user) => [user.lastName, user.firstName]),
|
|
125
|
+
* );
|
|
87
126
|
* // Result: Doe Jane, Doe John, Smith Bob
|
|
88
127
|
*
|
|
89
128
|
* // Status-based sorting
|
|
90
|
-
* users.sort(GaffComparator.strings(user => user.status));
|
|
129
|
+
* users.sort(GaffComparator.strings((user) => user.status));
|
|
91
130
|
* // Result: active users first, then inactive
|
|
92
131
|
*
|
|
93
132
|
* // Complex multi-field: status, then last name, then first name
|
|
94
|
-
* users.sort(
|
|
133
|
+
* users.sort(
|
|
134
|
+
* GaffComparator.strings((user) => [
|
|
135
|
+
* user.status,
|
|
136
|
+
* user.lastName,
|
|
137
|
+
* user.firstName,
|
|
138
|
+
* ]),
|
|
139
|
+
* );
|
|
95
140
|
*
|
|
96
141
|
* // Integration with TestValidator sorting validation
|
|
97
|
-
* const sortValidator = TestValidator.sort(
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
142
|
+
* const sortValidator = TestValidator.sort(
|
|
143
|
+
* "user name sorting",
|
|
144
|
+
* (sortFields) => userApi.getUsers({ sort: sortFields }),
|
|
145
|
+
* )(
|
|
146
|
+
* "lastName",
|
|
147
|
+
* "firstName",
|
|
148
|
+
* )(GaffComparator.strings((user) => [user.lastName, user.firstName]));
|
|
102
149
|
* await sortValidator("+"); // test ascending order
|
|
103
150
|
* await sortValidator("-"); // test descending order
|
|
104
|
-
* ```;
|
|
105
151
|
*
|
|
106
152
|
* @template T - The type of objects being compared
|
|
107
153
|
* @param getter - Function that extracts string value(s) from input objects
|
|
108
154
|
* @returns A comparator function suitable for Array.sort()
|
|
155
|
+
* @evidence contracts/common.md#principled-implementation Each common key position is compared once with localeCompare; a nonzero result decides the order, while collation-equal spellings continue to later keys. Only an entirely equal common prefix falls through to array length, establishing lexicographic order under the runtime's actual collation without assuming strict string equality.
|
|
156
|
+
* @evidence contracts/common.md#clear-and-simple-design Shared wrapping accepts scalar or array keys; one bounded loop returns the first nonzero collation result or the length difference.
|
|
157
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The comparison is the platform's locale collation, not a hand-written ordering.
|
|
158
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the locale sensitivity, the multi-value rule, and the arguments, with examples.
|
|
109
159
|
*/
|
|
110
160
|
GaffComparator.strings = (getter) => (x, y) => {
|
|
111
161
|
const a = wrap(getter(x));
|
|
112
162
|
const b = wrap(getter(y));
|
|
113
|
-
|
|
114
|
-
|
|
163
|
+
for (let index = 0; index < Math.min(a.length, b.length); ++index) {
|
|
164
|
+
const result = compare(a[index], b[index]);
|
|
165
|
+
if (result !== 0)
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
return a.length - b.length;
|
|
115
169
|
};
|
|
116
170
|
/**
|
|
117
171
|
* Creates a comparator function for date-based sorting with automatic string
|
|
@@ -127,8 +181,11 @@ var GaffComparator;
|
|
|
127
181
|
* The comparison is performed on millisecond timestamps for precise
|
|
128
182
|
* ordering.
|
|
129
183
|
*
|
|
184
|
+
* Processing cost: Both getters run once, each returned string is parsed
|
|
185
|
+
* once, and the bounded mismatch search visits at most the common key count.
|
|
186
|
+
* Numeric key arrays require space proportional to the two lists.
|
|
187
|
+
*
|
|
130
188
|
* @example
|
|
131
|
-
* ```typescript
|
|
132
189
|
* interface Event {
|
|
133
190
|
* id: string;
|
|
134
191
|
* title: string;
|
|
@@ -140,59 +197,65 @@ var GaffComparator;
|
|
|
140
197
|
*
|
|
141
198
|
* const events: Event[] = [
|
|
142
199
|
* {
|
|
143
|
-
* id:
|
|
144
|
-
* title:
|
|
145
|
-
* startDate:
|
|
146
|
-
* endDate:
|
|
147
|
-
* createdAt:
|
|
148
|
-
* updatedAt:
|
|
200
|
+
* id: "1",
|
|
201
|
+
* title: "Conference",
|
|
202
|
+
* startDate: "2024-03-15T09:00:00Z",
|
|
203
|
+
* endDate: "2024-03-15T17:00:00Z",
|
|
204
|
+
* createdAt: "2024-01-10T10:00:00Z",
|
|
205
|
+
* updatedAt: "2024-02-01T15:30:00Z",
|
|
149
206
|
* },
|
|
150
207
|
* {
|
|
151
|
-
* id:
|
|
152
|
-
* title:
|
|
153
|
-
* startDate:
|
|
154
|
-
* endDate:
|
|
155
|
-
* createdAt:
|
|
156
|
-
* updatedAt:
|
|
157
|
-
* }
|
|
208
|
+
* id: "2",
|
|
209
|
+
* title: "Workshop",
|
|
210
|
+
* startDate: "2024-03-10T14:00:00Z",
|
|
211
|
+
* endDate: "2024-03-10T16:00:00Z",
|
|
212
|
+
* createdAt: "2024-01-15T11:00:00Z",
|
|
213
|
+
* updatedAt: "2024-01-20T09:15:00Z",
|
|
214
|
+
* },
|
|
158
215
|
* ];
|
|
159
216
|
*
|
|
160
217
|
* // Sort by start date (chronological order)
|
|
161
|
-
* events.sort(GaffComparator.dates(event => event.startDate));
|
|
218
|
+
* events.sort(GaffComparator.dates((event) => event.startDate));
|
|
162
219
|
*
|
|
163
220
|
* // Sort by creation date (oldest first)
|
|
164
|
-
* events.sort(GaffComparator.dates(event => event.createdAt));
|
|
221
|
+
* events.sort(GaffComparator.dates((event) => event.createdAt));
|
|
165
222
|
*
|
|
166
223
|
* // Multi-field: start date, then end date
|
|
167
|
-
* events.sort(
|
|
224
|
+
* events.sort(
|
|
225
|
+
* GaffComparator.dates((event) => [event.startDate, event.endDate]),
|
|
226
|
+
* );
|
|
168
227
|
*
|
|
169
228
|
* // Sort by modification history: created date, then updated date
|
|
170
|
-
* events.sort(
|
|
229
|
+
* events.sort(
|
|
230
|
+
* GaffComparator.dates((event) => [event.createdAt, event.updatedAt]),
|
|
231
|
+
* );
|
|
171
232
|
*
|
|
172
233
|
* // Validate API date sorting with TestValidator
|
|
173
|
-
* const dateValidator = TestValidator.sort(
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* );
|
|
234
|
+
* const dateValidator = TestValidator.sort(
|
|
235
|
+
* "event chronological sorting",
|
|
236
|
+
* (sortFields) => eventApi.getEvents({ sort: sortFields }),
|
|
237
|
+
* )("startDate")(GaffComparator.dates((event) => event.startDate));
|
|
178
238
|
* await dateValidator("+", true); // ascending with trace logging
|
|
179
239
|
*
|
|
180
240
|
* // Test complex date-based sorting
|
|
181
|
-
* const sortByEventSchedule = GaffComparator.dates(event => [
|
|
241
|
+
* const sortByEventSchedule = GaffComparator.dates((event) => [
|
|
182
242
|
* event.startDate,
|
|
183
|
-
* event.endDate
|
|
243
|
+
* event.endDate,
|
|
184
244
|
* ]);
|
|
185
|
-
* ```;
|
|
186
245
|
*
|
|
187
246
|
* @template T - The type of objects being compared
|
|
188
247
|
* @param getter - Function that extracts date string(s) from input objects
|
|
189
248
|
* @returns A comparator function suitable for Array.sort()
|
|
249
|
+
* @evidence contracts/common.md#principled-implementation Each value is parsed by the `Date` constructor and compared by its millisecond timestamp, so ISO 8601 and the other formats the constructor accepts order correctly; a string the constructor cannot parse yields NaN, and the comparator then returns NaN, which a sort treats as equality, a limit the caller must respect by giving valid dates.
|
|
250
|
+
* @evidence contracts/common.md#clear-and-simple-design It uses the shared `wrap` and `mismatch`, and adds only the parsing.
|
|
251
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts Parsing is the standard constructor with no format special cases.
|
|
252
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the accepted formats and the millisecond comparison, with examples.
|
|
190
253
|
*/
|
|
191
254
|
GaffComparator.dates = (getter) => (x, y) => {
|
|
192
255
|
const take = (v) => wrap(getter(v)).map((str) => new Date(str).getTime());
|
|
193
256
|
const a = take(x);
|
|
194
257
|
const b = take(y);
|
|
195
|
-
const idx = a
|
|
258
|
+
const idx = mismatch(a, b);
|
|
196
259
|
return idx !== -1 ? a[idx] - b[idx] : a.length - b.length;
|
|
197
260
|
};
|
|
198
261
|
/**
|
|
@@ -209,8 +272,11 @@ var GaffComparator;
|
|
|
209
272
|
* on. This enables sophisticated sorting like "sort by price ascending, then
|
|
210
273
|
* by rating descending".
|
|
211
274
|
*
|
|
275
|
+
* Processing cost: Both getters run once and mismatch visits only the common
|
|
276
|
+
* prefix until the first unequal key. Existing key arrays are reused, and
|
|
277
|
+
* scalar wrapping takes constant auxiliary space.
|
|
278
|
+
*
|
|
212
279
|
* @example
|
|
213
|
-
* ```typescript
|
|
214
280
|
* interface Product {
|
|
215
281
|
* id: string;
|
|
216
282
|
* name: string;
|
|
@@ -222,57 +288,110 @@ var GaffComparator;
|
|
|
222
288
|
* }
|
|
223
289
|
*
|
|
224
290
|
* const products: Product[] = [
|
|
225
|
-
* {
|
|
226
|
-
*
|
|
227
|
-
*
|
|
291
|
+
* {
|
|
292
|
+
* id: "1",
|
|
293
|
+
* name: "Laptop",
|
|
294
|
+
* price: 999.99,
|
|
295
|
+
* rating: 4.5,
|
|
296
|
+
* stock: 15,
|
|
297
|
+
* categoryId: 1,
|
|
298
|
+
* salesCount: 150,
|
|
299
|
+
* },
|
|
300
|
+
* {
|
|
301
|
+
* id: "2",
|
|
302
|
+
* name: "Mouse",
|
|
303
|
+
* price: 29.99,
|
|
304
|
+
* rating: 4.2,
|
|
305
|
+
* stock: 50,
|
|
306
|
+
* categoryId: 1,
|
|
307
|
+
* salesCount: 300,
|
|
308
|
+
* },
|
|
309
|
+
* {
|
|
310
|
+
* id: "3",
|
|
311
|
+
* name: "Keyboard",
|
|
312
|
+
* price: 79.99,
|
|
313
|
+
* rating: 4.8,
|
|
314
|
+
* stock: 25,
|
|
315
|
+
* categoryId: 1,
|
|
316
|
+
* salesCount: 200,
|
|
317
|
+
* },
|
|
228
318
|
* ];
|
|
229
319
|
*
|
|
230
320
|
* // Sort by price (ascending)
|
|
231
|
-
* products.sort(GaffComparator.numbers(product => product.price));
|
|
321
|
+
* products.sort(GaffComparator.numbers((product) => product.price));
|
|
232
322
|
* // Result: Mouse ($29.99), Keyboard ($79.99), Laptop ($999.99)
|
|
233
323
|
*
|
|
234
324
|
* // Sort by rating (descending requires negation)
|
|
235
|
-
* products.sort(GaffComparator.numbers(product => -product.rating));
|
|
325
|
+
* products.sort(GaffComparator.numbers((product) => -product.rating));
|
|
236
326
|
* // Result: Keyboard (4.8), Laptop (4.5), Mouse (4.2)
|
|
237
327
|
*
|
|
238
328
|
* // Multi-field: category, then price
|
|
239
|
-
* products.sort(
|
|
329
|
+
* products.sort(
|
|
330
|
+
* GaffComparator.numbers((product) => [
|
|
331
|
+
* product.categoryId,
|
|
332
|
+
* product.price,
|
|
333
|
+
* ]),
|
|
334
|
+
* );
|
|
240
335
|
*
|
|
241
336
|
* // Complex business logic: popularity (sales) then rating
|
|
242
|
-
* products.sort(
|
|
337
|
+
* products.sort(
|
|
338
|
+
* GaffComparator.numbers((product) => [
|
|
339
|
+
* -product.salesCount,
|
|
340
|
+
* -product.rating,
|
|
341
|
+
* ]),
|
|
342
|
+
* );
|
|
243
343
|
* // Negative values for descending order
|
|
244
344
|
*
|
|
245
345
|
* // Sort by inventory priority: low stock first, then by sales
|
|
246
|
-
* products.sort(
|
|
346
|
+
* products.sort(
|
|
347
|
+
* GaffComparator.numbers((product) => [
|
|
348
|
+
* product.stock,
|
|
349
|
+
* -product.salesCount,
|
|
350
|
+
* ]),
|
|
351
|
+
* );
|
|
247
352
|
*
|
|
248
353
|
* // Validate API numerical sorting with TestValidator
|
|
249
|
-
* const priceValidator = TestValidator.sort(
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
* );
|
|
354
|
+
* const priceValidator = TestValidator.sort(
|
|
355
|
+
* "product price sorting",
|
|
356
|
+
* (sortFields) => productApi.getProducts({ sort: sortFields }),
|
|
357
|
+
* )("price")(GaffComparator.numbers((product) => product.price));
|
|
254
358
|
* await priceValidator("+"); // test ascending order
|
|
255
359
|
* await priceValidator("-"); // test descending order
|
|
256
360
|
*
|
|
257
361
|
* // Test multi-criteria sorting
|
|
258
|
-
* const sortByBusinessValue = GaffComparator.numbers(product => [
|
|
259
|
-
* -product.salesCount,
|
|
260
|
-
* -product.rating,
|
|
261
|
-
* product.price
|
|
362
|
+
* const sortByBusinessValue = GaffComparator.numbers((product) => [
|
|
363
|
+
* -product.salesCount, // High sales first
|
|
364
|
+
* -product.rating, // High rating first
|
|
365
|
+
* product.price, // Low price first (for tie-breaking)
|
|
262
366
|
* ]);
|
|
263
|
-
* ```;
|
|
264
367
|
*
|
|
265
368
|
* @template T - The type of objects being compared
|
|
266
369
|
* @param closure - Function that extracts number value(s) from input objects
|
|
267
370
|
* @returns A comparator function suitable for Array.sort()
|
|
371
|
+
* @evidence contracts/common.md#principled-implementation The sign of subtraction at the first differing position orders finite numeric values, and a shorter equal prefix sorts first. Subtraction can round or overflow, so the result's magnitude is not an exact-distance guarantee; callers must supply ordered numeric values rather than NaN.
|
|
372
|
+
* @evidence contracts/common.md#clear-and-simple-design It uses the shared `wrap` and `mismatch`, and adds only the subtraction.
|
|
373
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The comparison is the arithmetic difference, with no rounding or thresholds.
|
|
374
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the multi-value rule and the arguments, with examples.
|
|
268
375
|
*/
|
|
269
376
|
GaffComparator.numbers = (closure) => (x, y) => {
|
|
270
377
|
const a = wrap(closure(x));
|
|
271
378
|
const b = wrap(closure(y));
|
|
272
|
-
const idx = a
|
|
379
|
+
const idx = mismatch(a, b);
|
|
273
380
|
return idx !== -1 ? a[idx] - b[idx] : a.length - b.length;
|
|
274
381
|
};
|
|
275
382
|
const compare = (x, y) => x.localeCompare(y);
|
|
383
|
+
/**
|
|
384
|
+
* The first index where the two key lists differ within their common length,
|
|
385
|
+
* or -1; beyond it a proper prefix orders before its extension, in both
|
|
386
|
+
* argument orders.
|
|
387
|
+
*/
|
|
388
|
+
const mismatch = (a, b) => {
|
|
389
|
+
const length = Math.min(a.length, b.length);
|
|
390
|
+
for (let index = 0; index < length; ++index)
|
|
391
|
+
if (a[index] !== b[index])
|
|
392
|
+
return index;
|
|
393
|
+
return -1;
|
|
394
|
+
};
|
|
276
395
|
const wrap = (elem) => (Array.isArray(elem) ? elem : [elem]);
|
|
277
396
|
})(GaffComparator || (exports.GaffComparator = GaffComparator = {}));
|
|
278
397
|
//# sourceMappingURL=GaffComparator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GaffComparator.js","sourceRoot":"","sources":["../src/GaffComparator.ts"],"names":[],"mappings":";;;AAAA
|
|
1
|
+
{"version":3,"file":"GaffComparator.js","sourceRoot":"","sources":["../src/GaffComparator.ts"],"names":[],"mappings":"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"}
|
package/lib/MapUtil.d.ts
CHANGED
|
@@ -5,9 +5,21 @@
|
|
|
5
5
|
* objects, providing convenient methods for common Map operations like
|
|
6
6
|
* retrieving values with lazy initialization.
|
|
7
7
|
*
|
|
8
|
+
* Processing cost: The get-or-create operation uses native Map membership and
|
|
9
|
+
* lookup, and calls the factory only for an absent key; its dominant extra cost
|
|
10
|
+
* is the caller factory.
|
|
11
|
+
*
|
|
12
|
+
* Reuse: Stored values, including promises and undefined, are reused while the
|
|
13
|
+
* supplied Map retains the key. The caller must key every relevant dependency
|
|
14
|
+
* and remove stale or rejected entries; this helper cannot establish
|
|
15
|
+
* external-data freshness or prevent reentrant factory calls.
|
|
16
|
+
*
|
|
17
|
+
* Resource ownership: New values are transferred into the caller-owned Map,
|
|
18
|
+
* whose growth and eviction remain the caller responsibility; the helper
|
|
19
|
+
* acquires no external handle or background task.
|
|
20
|
+
*
|
|
8
21
|
* @author Jeongho Nam - https://github.com/samchon
|
|
9
22
|
* @example
|
|
10
|
-
* ```typescript
|
|
11
23
|
* // Create a cache with lazy initialization
|
|
12
24
|
* const cache = new Map<string, ExpensiveObject>();
|
|
13
25
|
*
|
|
@@ -19,7 +31,11 @@
|
|
|
19
31
|
* // Subsequent calls return cached value without re-creating
|
|
20
32
|
* const sameObj = MapUtil.take(cache, "key1", () => new ExpensiveObject());
|
|
21
33
|
* console.log(obj === sameObj); // true
|
|
22
|
-
*
|
|
34
|
+
*
|
|
35
|
+
* @evidence contracts/common.md#principled-implementation The namespace offers the get-or-create pattern over the native `Map`, whose `has` distinguishes an absent key from a stored `undefined`.
|
|
36
|
+
* @evidence contracts/common.md#clear-and-simple-design One function, without options or state.
|
|
37
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It uses only the public Map methods.
|
|
38
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the lazy initialization pattern with an example.
|
|
23
39
|
*/
|
|
24
40
|
export declare namespace MapUtil {
|
|
25
41
|
/**
|
|
@@ -32,8 +48,20 @@ export declare namespace MapUtil {
|
|
|
32
48
|
* returns it. The factory function is only called when the key doesn't exist,
|
|
33
49
|
* enabling lazy initialization and caching patterns.
|
|
34
50
|
*
|
|
51
|
+
* Processing cost: One membership test and lookup, or one factory invocation
|
|
52
|
+
* and insertion, avoid a map scan; native Map access is sublinear on average
|
|
53
|
+
* and factory cost belongs to the supplied computation.
|
|
54
|
+
*
|
|
55
|
+
* Reuse: Stored values, including promises and undefined, are reused while
|
|
56
|
+
* the supplied Map retains the key. The caller must key every relevant
|
|
57
|
+
* dependency and remove stale or rejected entries; this helper cannot
|
|
58
|
+
* establish external-data freshness or prevent reentrant factory calls.
|
|
59
|
+
*
|
|
60
|
+
* Resource ownership: New values are transferred into the caller-owned Map,
|
|
61
|
+
* whose growth and eviction remain the caller responsibility; the helper
|
|
62
|
+
* acquires no external handle or background task.
|
|
63
|
+
*
|
|
35
64
|
* @example
|
|
36
|
-
* ```typescript
|
|
37
65
|
* // Simple caching example
|
|
38
66
|
* const userCache = new Map<number, User>();
|
|
39
67
|
*
|
|
@@ -48,7 +76,7 @@ export declare namespace MapUtil {
|
|
|
48
76
|
* const dbConfig = MapUtil.take(configs, "database", () => ({
|
|
49
77
|
* host: "localhost",
|
|
50
78
|
* port: 5432,
|
|
51
|
-
* database: "myapp"
|
|
79
|
+
* database: "myapp",
|
|
52
80
|
* }));
|
|
53
81
|
*
|
|
54
82
|
* // Lazy computation results
|
|
@@ -64,9 +92,8 @@ export declare namespace MapUtil {
|
|
|
64
92
|
* const key: [number, number] = [rows, cols];
|
|
65
93
|
*
|
|
66
94
|
* const matrix = MapUtil.take(cache, key, () =>
|
|
67
|
-
* generateIdentityMatrix(rows, cols)
|
|
95
|
+
* generateIdentityMatrix(rows, cols),
|
|
68
96
|
* );
|
|
69
|
-
* ```;
|
|
70
97
|
*
|
|
71
98
|
* @template K - The type of keys in the Map
|
|
72
99
|
* @template V - The type of values in the Map
|
|
@@ -75,6 +102,10 @@ export declare namespace MapUtil {
|
|
|
75
102
|
* @param value - A factory function that creates the value if key doesn't
|
|
76
103
|
* exist
|
|
77
104
|
* @returns The existing value if found, or the newly created value
|
|
105
|
+
* @evidence contracts/common.md#principled-implementation The key is looked up with `has`, so an existing value, even `undefined`, is returned without calling the factory; otherwise the factory is called once, its value is stored, and the same value is returned.
|
|
106
|
+
* @evidence contracts/common.md#clear-and-simple-design A single check, one factory call, and one store.
|
|
107
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The factory result is stored as returned, with no copying or expiry.
|
|
108
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states when the factory runs and documents the parameters with several examples.
|
|
78
109
|
*/
|
|
79
110
|
function take<K, V>(map: Map<K, V>, key: K, value: () => V): V;
|
|
80
111
|
}
|
package/lib/MapUtil.js
CHANGED
|
@@ -8,9 +8,21 @@ exports.MapUtil = void 0;
|
|
|
8
8
|
* objects, providing convenient methods for common Map operations like
|
|
9
9
|
* retrieving values with lazy initialization.
|
|
10
10
|
*
|
|
11
|
+
* Processing cost: The get-or-create operation uses native Map membership and
|
|
12
|
+
* lookup, and calls the factory only for an absent key; its dominant extra cost
|
|
13
|
+
* is the caller factory.
|
|
14
|
+
*
|
|
15
|
+
* Reuse: Stored values, including promises and undefined, are reused while the
|
|
16
|
+
* supplied Map retains the key. The caller must key every relevant dependency
|
|
17
|
+
* and remove stale or rejected entries; this helper cannot establish
|
|
18
|
+
* external-data freshness or prevent reentrant factory calls.
|
|
19
|
+
*
|
|
20
|
+
* Resource ownership: New values are transferred into the caller-owned Map,
|
|
21
|
+
* whose growth and eviction remain the caller responsibility; the helper
|
|
22
|
+
* acquires no external handle or background task.
|
|
23
|
+
*
|
|
11
24
|
* @author Jeongho Nam - https://github.com/samchon
|
|
12
25
|
* @example
|
|
13
|
-
* ```typescript
|
|
14
26
|
* // Create a cache with lazy initialization
|
|
15
27
|
* const cache = new Map<string, ExpensiveObject>();
|
|
16
28
|
*
|
|
@@ -22,7 +34,11 @@ exports.MapUtil = void 0;
|
|
|
22
34
|
* // Subsequent calls return cached value without re-creating
|
|
23
35
|
* const sameObj = MapUtil.take(cache, "key1", () => new ExpensiveObject());
|
|
24
36
|
* console.log(obj === sameObj); // true
|
|
25
|
-
*
|
|
37
|
+
*
|
|
38
|
+
* @evidence contracts/common.md#principled-implementation The namespace offers the get-or-create pattern over the native `Map`, whose `has` distinguishes an absent key from a stored `undefined`.
|
|
39
|
+
* @evidence contracts/common.md#clear-and-simple-design One function, without options or state.
|
|
40
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts It uses only the public Map methods.
|
|
41
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states the lazy initialization pattern with an example.
|
|
26
42
|
*/
|
|
27
43
|
var MapUtil;
|
|
28
44
|
(function (MapUtil) {
|
|
@@ -36,8 +52,20 @@ var MapUtil;
|
|
|
36
52
|
* returns it. The factory function is only called when the key doesn't exist,
|
|
37
53
|
* enabling lazy initialization and caching patterns.
|
|
38
54
|
*
|
|
55
|
+
* Processing cost: One membership test and lookup, or one factory invocation
|
|
56
|
+
* and insertion, avoid a map scan; native Map access is sublinear on average
|
|
57
|
+
* and factory cost belongs to the supplied computation.
|
|
58
|
+
*
|
|
59
|
+
* Reuse: Stored values, including promises and undefined, are reused while
|
|
60
|
+
* the supplied Map retains the key. The caller must key every relevant
|
|
61
|
+
* dependency and remove stale or rejected entries; this helper cannot
|
|
62
|
+
* establish external-data freshness or prevent reentrant factory calls.
|
|
63
|
+
*
|
|
64
|
+
* Resource ownership: New values are transferred into the caller-owned Map,
|
|
65
|
+
* whose growth and eviction remain the caller responsibility; the helper
|
|
66
|
+
* acquires no external handle or background task.
|
|
67
|
+
*
|
|
39
68
|
* @example
|
|
40
|
-
* ```typescript
|
|
41
69
|
* // Simple caching example
|
|
42
70
|
* const userCache = new Map<number, User>();
|
|
43
71
|
*
|
|
@@ -52,7 +80,7 @@ var MapUtil;
|
|
|
52
80
|
* const dbConfig = MapUtil.take(configs, "database", () => ({
|
|
53
81
|
* host: "localhost",
|
|
54
82
|
* port: 5432,
|
|
55
|
-
* database: "myapp"
|
|
83
|
+
* database: "myapp",
|
|
56
84
|
* }));
|
|
57
85
|
*
|
|
58
86
|
* // Lazy computation results
|
|
@@ -68,9 +96,8 @@ var MapUtil;
|
|
|
68
96
|
* const key: [number, number] = [rows, cols];
|
|
69
97
|
*
|
|
70
98
|
* const matrix = MapUtil.take(cache, key, () =>
|
|
71
|
-
* generateIdentityMatrix(rows, cols)
|
|
99
|
+
* generateIdentityMatrix(rows, cols),
|
|
72
100
|
* );
|
|
73
|
-
* ```;
|
|
74
101
|
*
|
|
75
102
|
* @template K - The type of keys in the Map
|
|
76
103
|
* @template V - The type of values in the Map
|
|
@@ -79,6 +106,10 @@ var MapUtil;
|
|
|
79
106
|
* @param value - A factory function that creates the value if key doesn't
|
|
80
107
|
* exist
|
|
81
108
|
* @returns The existing value if found, or the newly created value
|
|
109
|
+
* @evidence contracts/common.md#principled-implementation The key is looked up with `has`, so an existing value, even `undefined`, is returned without calling the factory; otherwise the factory is called once, its value is stored, and the same value is returned.
|
|
110
|
+
* @evidence contracts/common.md#clear-and-simple-design A single check, one factory call, and one store.
|
|
111
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts The factory result is stored as returned, with no copying or expiry.
|
|
112
|
+
* @evidence contracts/common.md#meaningful-documentation The comment states when the factory runs and documents the parameters with several examples.
|
|
82
113
|
*/
|
|
83
114
|
function take(map, key, value) {
|
|
84
115
|
if (map.has(key)) {
|
package/lib/MapUtil.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapUtil.js","sourceRoot":"","sources":["../src/MapUtil.ts"],"names":[],"mappings":";;;AAAA
|
|
1
|
+
{"version":3,"file":"MapUtil.js","sourceRoot":"","sources":["../src/MapUtil.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,IAAiB,OAAO,CA8EvB;AA9ED,WAAiB,OAAO;IACtB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoEG;IACH,SAAgB,IAAI,CAAO,GAAc,EAAE,GAAM,EAAE,KAAc;QAC/D,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAM,CAAC;QAC3B,CAAC;QACD,MAAM,QAAQ,GAAG,KAAK,EAAE,CAAC;QACzB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACvB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAPe,QAAA,IAAI,OAOnB,CAAA;AACH,CAAC,EA9EgB,OAAO,aAAP,OAAO,GAAP,OAAO,QA8EvB"}
|