@augment-vir/common 4.6.1 → 5.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/dist/{augments → cjs/augments}/ansi.d.ts +0 -0
- package/dist/{augments → cjs/augments}/ansi.js +0 -0
- package/dist/{augments → cjs/augments}/array.d.ts +1 -8
- package/dist/cjs/augments/array.js +25 -0
- package/dist/cjs/augments/async.d.ts +14 -0
- package/dist/cjs/augments/async.js +29 -0
- package/dist/{augments/number.d.ts → cjs/augments/common-number.d.ts} +8 -3
- package/dist/{augments/number.js → cjs/augments/common-number.js} +39 -11
- package/dist/{augments/string.d.ts → cjs/augments/common-string.d.ts} +14 -4
- package/dist/{augments/string.js → cjs/augments/common-string.js} +30 -27
- package/dist/{augments → cjs/augments}/date.d.ts +1 -1
- package/dist/{augments → cjs/augments}/date.js +2 -2
- package/dist/cjs/augments/environment.d.ts +1 -0
- package/dist/cjs/augments/environment.js +7 -0
- package/dist/{augments → cjs/augments}/error.d.ts +0 -0
- package/dist/{augments → cjs/augments}/error.js +0 -0
- package/dist/{augments → cjs/augments}/function.d.ts +0 -0
- package/dist/{augments → cjs/augments}/function.js +0 -0
- package/dist/{augments → cjs/augments}/object.d.ts +0 -0
- package/dist/{augments → cjs/augments}/object.js +0 -0
- package/dist/{augments → cjs/augments}/promise.d.ts +0 -0
- package/dist/{augments → cjs/augments}/promise.js +0 -0
- package/dist/{augments → cjs/augments}/regexp.d.ts +0 -0
- package/dist/{augments → cjs/augments}/regexp.js +0 -0
- package/dist/{augments → cjs/augments}/tuple.d.ts +0 -0
- package/dist/{augments → cjs/augments}/tuple.js +0 -0
- package/dist/{augments → cjs/augments}/type-of.d.ts +0 -0
- package/dist/{augments → cjs/augments}/type-of.js +2 -0
- package/dist/{augments → cjs/augments}/type.d.ts +0 -0
- package/dist/{augments → cjs/augments}/type.js +0 -0
- package/dist/{index.d.ts → cjs/index.d.ts} +4 -3
- package/dist/{index.js → cjs/index.js} +4 -3
- package/dist/esm/augments/ansi.d.ts +1 -0
- package/dist/esm/augments/ansi.js +24 -0
- package/dist/esm/augments/array.d.ts +13 -0
- package/dist/esm/augments/array.js +17 -0
- package/dist/esm/augments/async.d.ts +14 -0
- package/dist/esm/augments/async.js +23 -0
- package/dist/esm/augments/common-number.d.ts +32 -0
- package/dist/esm/augments/common-number.js +105 -0
- package/dist/esm/augments/common-string.d.ts +44 -0
- package/dist/esm/augments/common-string.js +180 -0
- package/dist/esm/augments/date.d.ts +26 -0
- package/dist/esm/augments/date.js +74 -0
- package/dist/esm/augments/environment.d.ts +1 -0
- package/dist/esm/augments/environment.js +3 -0
- package/dist/esm/augments/error.d.ts +8 -0
- package/dist/esm/augments/error.js +36 -0
- package/dist/esm/augments/function.d.ts +1 -0
- package/dist/esm/augments/function.js +3 -0
- package/dist/esm/augments/object.d.ts +63 -0
- package/dist/esm/augments/object.js +252 -0
- package/dist/esm/augments/promise.d.ts +23 -0
- package/dist/esm/augments/promise.js +84 -0
- package/dist/esm/augments/regexp.d.ts +3 -0
- package/dist/esm/augments/regexp.js +14 -0
- package/dist/esm/augments/tuple.d.ts +8 -0
- package/dist/esm/augments/tuple.js +3 -0
- package/dist/esm/augments/type-of.d.ts +17 -0
- package/dist/esm/augments/type-of.js +12 -0
- package/dist/esm/augments/type.d.ts +54 -0
- package/dist/esm/augments/type.js +24 -0
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.js +15 -0
- package/dist/types/augments/ansi.d.ts +1 -0
- package/dist/types/augments/array.d.ts +13 -0
- package/dist/types/augments/async.d.ts +14 -0
- package/dist/types/augments/common-number.d.ts +32 -0
- package/dist/types/augments/common-string.d.ts +44 -0
- package/dist/types/augments/date.d.ts +26 -0
- package/dist/types/augments/environment.d.ts +1 -0
- package/dist/types/augments/error.d.ts +8 -0
- package/dist/types/augments/function.d.ts +1 -0
- package/dist/types/augments/object.d.ts +63 -0
- package/dist/types/augments/promise.d.ts +23 -0
- package/dist/types/augments/regexp.d.ts +3 -0
- package/dist/types/augments/tuple.d.ts +8 -0
- package/dist/types/augments/type-of.d.ts +17 -0
- package/dist/types/augments/type.d.ts +54 -0
- package/dist/types/index.d.ts +15 -0
- package/package.json +6 -6
- package/dist/augments/array.js +0 -44
- package/dist/augments/type-test.d.ts +0 -3
- package/dist/augments/type-test.js +0 -2
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { extractErrorMessage } from './error';
|
|
2
|
+
import { isTruthy } from './function';
|
|
3
|
+
export function getEnumTypedKeys(input) {
|
|
4
|
+
// enum keys are always strings
|
|
5
|
+
return getObjectTypedKeys(input).filter((key) => isNaN(Number(key)));
|
|
6
|
+
}
|
|
7
|
+
export function getEnumTypedValues(input) {
|
|
8
|
+
const keys = getEnumTypedKeys(input);
|
|
9
|
+
return keys.map((key) => input[key]);
|
|
10
|
+
}
|
|
11
|
+
export function isEnumValue(input, checkEnum) {
|
|
12
|
+
return getEnumTypedValues(checkEnum).includes(input);
|
|
13
|
+
}
|
|
14
|
+
export function isKeyof(key, object) {
|
|
15
|
+
return typedHasProperty(object, key);
|
|
16
|
+
}
|
|
17
|
+
export function filterToEnumValues(inputs, checkEnum, caseInsensitive = false) {
|
|
18
|
+
if (caseInsensitive) {
|
|
19
|
+
return inputs.reduce((accum, currentInput) => {
|
|
20
|
+
const matchedEnumValue = getEnumTypedValues(checkEnum).find((actualEnumValue) => {
|
|
21
|
+
return String(actualEnumValue).toUpperCase() === String(currentInput).toUpperCase();
|
|
22
|
+
});
|
|
23
|
+
if (matchedEnumValue) {
|
|
24
|
+
return accum.concat(matchedEnumValue);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
return accum;
|
|
28
|
+
}
|
|
29
|
+
}, []);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return inputs.filter((input) => isEnumValue(input, checkEnum));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function getObjectTypedKeys(input) {
|
|
36
|
+
let reflectKeys;
|
|
37
|
+
try {
|
|
38
|
+
reflectKeys = Reflect.ownKeys(input);
|
|
39
|
+
}
|
|
40
|
+
catch (error) { }
|
|
41
|
+
return (reflectKeys !== null && reflectKeys !== void 0 ? reflectKeys : [
|
|
42
|
+
...Object.keys(input),
|
|
43
|
+
...Object.getOwnPropertySymbols(input),
|
|
44
|
+
]);
|
|
45
|
+
}
|
|
46
|
+
export function getObjectTypedValues(input) {
|
|
47
|
+
return getObjectTypedKeys(input).map((key) => input[key]);
|
|
48
|
+
}
|
|
49
|
+
const hasPropertyAttempts = [
|
|
50
|
+
(object, key) => {
|
|
51
|
+
return key in object;
|
|
52
|
+
},
|
|
53
|
+
(object, key) => {
|
|
54
|
+
/** This handles cases where the input object can't use `in` directly, like string literals */
|
|
55
|
+
return key in object.constructor.prototype;
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
export function typedHasProperty(inputObject, inputKey) {
|
|
59
|
+
if (!inputObject) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return hasPropertyAttempts.some((attemptCallback) => {
|
|
63
|
+
try {
|
|
64
|
+
return attemptCallback(inputObject, inputKey);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
export function typedHasProperties(inputObject, inputKeys) {
|
|
72
|
+
return inputObject && inputKeys.every((key) => typedHasProperty(inputObject, key));
|
|
73
|
+
}
|
|
74
|
+
export function isObject(input) {
|
|
75
|
+
return !!input && typeof input === 'object';
|
|
76
|
+
}
|
|
77
|
+
export function getEntriesSortedByKey(input) {
|
|
78
|
+
return Object.entries(input).sort((tupleA, tupleB) => tupleA[0].localeCompare(tupleB[0]));
|
|
79
|
+
}
|
|
80
|
+
export function areJsonEqual(a, b) {
|
|
81
|
+
try {
|
|
82
|
+
const sortedAEntries = getEntriesSortedByKey(a);
|
|
83
|
+
const sortedBEntries = getEntriesSortedByKey(b);
|
|
84
|
+
return JSON.stringify(sortedAEntries) === JSON.stringify(sortedBEntries);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.error(`Failed to compare objects using JSON.stringify`);
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Creates a new object with the same properties as the input object, but with values set to the
|
|
93
|
+
* result of mapCallback for each property.
|
|
94
|
+
*/
|
|
95
|
+
export function mapObjectValues(inputObject, mapCallback) {
|
|
96
|
+
let gotAPromise = false;
|
|
97
|
+
const mappedObject = getObjectTypedKeys(inputObject).reduce((accum, currentKey) => {
|
|
98
|
+
const mappedValue = mapCallback(currentKey, inputObject[currentKey], inputObject);
|
|
99
|
+
if (mappedValue instanceof Promise) {
|
|
100
|
+
gotAPromise = true;
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
...accum,
|
|
104
|
+
[currentKey]: mappedValue,
|
|
105
|
+
};
|
|
106
|
+
}, {});
|
|
107
|
+
if (gotAPromise) {
|
|
108
|
+
return new Promise(async (resolve, reject) => {
|
|
109
|
+
try {
|
|
110
|
+
await Promise.all(getObjectTypedKeys(mappedObject).map(async (key) => {
|
|
111
|
+
const value = await mappedObject[key];
|
|
112
|
+
mappedObject[key] = value;
|
|
113
|
+
}));
|
|
114
|
+
resolve(mappedObject);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
reject(error);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
return mappedObject;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
export function filterObject(inputObject, callback) {
|
|
126
|
+
const filteredKeys = getObjectTypedKeys(inputObject).filter((key) => {
|
|
127
|
+
const value = inputObject[key];
|
|
128
|
+
return callback(key, value, inputObject);
|
|
129
|
+
});
|
|
130
|
+
return filteredKeys.reduce((accum, key) => {
|
|
131
|
+
accum[key] = inputObject[key];
|
|
132
|
+
return accum;
|
|
133
|
+
}, {});
|
|
134
|
+
}
|
|
135
|
+
/** The input here must be serializable otherwise JSON parsing errors will be thrown */
|
|
136
|
+
export function copyThroughJson(input) {
|
|
137
|
+
try {
|
|
138
|
+
return JSON.parse(JSON.stringify(input));
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
console.error(`Failed to JSON copy for`, input);
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Checks that the first input, testThisOne, matches the object shape of the second input,
|
|
147
|
+
* compareToThisOne. Does not compare exact values of properties, only types.
|
|
148
|
+
*
|
|
149
|
+
* To allow the test input, the first input, to have additional keys that the compare input, the
|
|
150
|
+
* second input, does not have, pass in a third argument set to true.
|
|
151
|
+
*
|
|
152
|
+
* This function REQUIRES a generic to be assigned to it: it cannot infer it from the inputs.
|
|
153
|
+
*
|
|
154
|
+
* The compare input, the second input, is required to have at least one entry in every array value
|
|
155
|
+
* that exists. If more array values are present, they will be considered other possible types for
|
|
156
|
+
* entries in that array.
|
|
157
|
+
*/
|
|
158
|
+
export function matchesObjectShape(testThisOne, compareToThisOne, allowExtraProps = false, shouldLogWhy = false) {
|
|
159
|
+
try {
|
|
160
|
+
assertMatchesObjectShape(testThisOne, compareToThisOne, allowExtraProps);
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
if (shouldLogWhy) {
|
|
165
|
+
console.error(error);
|
|
166
|
+
}
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Asserts that the first input, testThisOne, matches the object shape of the second input,
|
|
172
|
+
* compareToThisOne. Does not compare exact values of properties, only types.
|
|
173
|
+
*
|
|
174
|
+
* To allow the test input, the first input, to have additional keys that the compare input, the
|
|
175
|
+
* second input, does not have, pass in a third argument set to true.
|
|
176
|
+
*
|
|
177
|
+
* This function REQUIRES a generic to be assigned to it: it cannot infer it from the inputs.
|
|
178
|
+
*
|
|
179
|
+
* The compare input, the second input, is required to have at least one entry in every array value
|
|
180
|
+
* that exists. If more array values are present, they will be considered other possible types for
|
|
181
|
+
* entries in that array.
|
|
182
|
+
*/
|
|
183
|
+
export function assertMatchesObjectShape(testThisOne, compareToThisOne, allowExtraProps = false) {
|
|
184
|
+
const testKeys = getObjectTypedKeys(testThisOne);
|
|
185
|
+
const matchKeys = new Set(getObjectTypedKeys(compareToThisOne));
|
|
186
|
+
if (!allowExtraProps) {
|
|
187
|
+
const extraKeys = testKeys.filter((testKey) => !matchKeys.has(testKey));
|
|
188
|
+
if (extraKeys.length) {
|
|
189
|
+
throw new Error(`Test object has extra keys: ${extraKeys.join(', ')}`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
matchKeys.forEach((key) => {
|
|
193
|
+
if (!typedHasProperty(testThisOne, key)) {
|
|
194
|
+
throw new Error(`test object does not have key "${String(key)}" from expected shape.`);
|
|
195
|
+
}
|
|
196
|
+
function throwKeyError(reason) {
|
|
197
|
+
throw new Error(`test object value at key "${String(key)}" did not match expected shape: ${reason}`);
|
|
198
|
+
}
|
|
199
|
+
const testValue = testThisOne[key];
|
|
200
|
+
const shouldMatch = compareToThisOne[key];
|
|
201
|
+
compareInnerValue(testValue, shouldMatch, throwKeyError);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
function compareInnerValue(testValue, matchValue, throwKeyError) {
|
|
205
|
+
var _a;
|
|
206
|
+
const testType = typeof testValue;
|
|
207
|
+
const shouldMatchType = typeof matchValue;
|
|
208
|
+
if (testType !== shouldMatchType) {
|
|
209
|
+
throwKeyError(`type "${testType}" did not match expected type "${shouldMatchType}"`);
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
if (typedHasProperty(matchValue, 'constructor')) {
|
|
213
|
+
if (!typedHasProperty(testValue, 'constructor') ||
|
|
214
|
+
testValue.constructor !== matchValue.constructor) {
|
|
215
|
+
throwKeyError(`constructor "${(_a = testValue === null || testValue === void 0 ? void 0 : testValue.constructor) === null || _a === void 0 ? void 0 : _a.name}" did not match expected constructor "${matchValue.constructor}"`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
catch (error) {
|
|
220
|
+
// ignore errors from trying to find the constructor
|
|
221
|
+
if (error instanceof throwKeyError) {
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (Array.isArray(matchValue)) {
|
|
226
|
+
if (!Array.isArray(testValue)) {
|
|
227
|
+
throwKeyError(`expected an array`);
|
|
228
|
+
}
|
|
229
|
+
testValue.forEach((testValueEntry, index) => {
|
|
230
|
+
const errors = matchValue
|
|
231
|
+
.map((matchValue) => {
|
|
232
|
+
try {
|
|
233
|
+
compareInnerValue(testValueEntry, matchValue, throwKeyError);
|
|
234
|
+
return undefined;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
return new Error(`entry at index "${index}" did not match expected shape: ${extractErrorMessage(error)}`);
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
.filter(isTruthy);
|
|
241
|
+
if (errors.length === matchValue.length) {
|
|
242
|
+
throw new Error(`entry at index "${index}" did not match any of the possible types from "${matchValue.join(', ')}"`);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
else if (isObject(matchValue)) {
|
|
247
|
+
assertMatchesObjectShape(testValue, matchValue);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
export function typedObjectFromEntries(entries) {
|
|
251
|
+
return Object.fromEntries(entries);
|
|
252
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare function wait(delayMs: number): Promise<void>;
|
|
2
|
+
export declare function isPromiseLike<T>(input: T | unknown): input is T extends PromiseLike<infer ValueType> ? PromiseLike<ValueType> : PromiseLike<unknown>;
|
|
3
|
+
export declare class PromiseTimeoutError extends Error {
|
|
4
|
+
readonly durationMs: number;
|
|
5
|
+
readonly message: string;
|
|
6
|
+
readonly name = "PromiseTimeoutError";
|
|
7
|
+
constructor(durationMs: number, message?: string);
|
|
8
|
+
}
|
|
9
|
+
export declare function wrapPromiseInTimeout<PromiseValueType>(durationMs: number, originalPromise: PromiseLike<PromiseValueType>): Promise<PromiseValueType>;
|
|
10
|
+
/** A promise which can be resolved or rejected by external code. */
|
|
11
|
+
export declare type DeferredPromiseWrapper<T> = {
|
|
12
|
+
promise: Promise<T>;
|
|
13
|
+
resolve: (value: T | PromiseLike<T>) => void;
|
|
14
|
+
reject: (reason?: any) => void;
|
|
15
|
+
};
|
|
16
|
+
export declare function createDeferredPromiseWrapper<T = void>(): DeferredPromiseWrapper<T>;
|
|
17
|
+
export declare type WaitForConditionInputs = {
|
|
18
|
+
conditionCallback: () => boolean | Promise<boolean>;
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
intervalMs?: number;
|
|
21
|
+
timeoutMessage?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function waitForCondition({ conditionCallback, timeoutMs, intervalMs, timeoutMessage, }: WaitForConditionInputs): Promise<void>;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { extractErrorMessage } from './error';
|
|
2
|
+
import { typedHasProperty } from './object';
|
|
3
|
+
export function wait(delayMs) {
|
|
4
|
+
const deferredPromiseWrapper = createDeferredPromiseWrapper();
|
|
5
|
+
if (delayMs === Infinity || delayMs < 0) {
|
|
6
|
+
return deferredPromiseWrapper.promise;
|
|
7
|
+
}
|
|
8
|
+
setTimeout(() => {
|
|
9
|
+
deferredPromiseWrapper.resolve();
|
|
10
|
+
}, delayMs);
|
|
11
|
+
return deferredPromiseWrapper.promise;
|
|
12
|
+
}
|
|
13
|
+
export function isPromiseLike(input) {
|
|
14
|
+
if (typedHasProperty(input, 'then') && typeof input.then === 'function') {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export class PromiseTimeoutError extends Error {
|
|
22
|
+
constructor(durationMs, message = `Promised timed out after ${durationMs} ms.`) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.durationMs = durationMs;
|
|
25
|
+
this.message = message;
|
|
26
|
+
this.name = 'PromiseTimeoutError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
export function wrapPromiseInTimeout(durationMs, originalPromise) {
|
|
30
|
+
return new Promise(async (resolve, reject) => {
|
|
31
|
+
const timeoutId = setTimeout(() => {
|
|
32
|
+
reject(new PromiseTimeoutError(durationMs));
|
|
33
|
+
}, durationMs);
|
|
34
|
+
try {
|
|
35
|
+
const result = await originalPromise;
|
|
36
|
+
resolve(result);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
reject(error);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
clearTimeout(timeoutId);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function createDeferredPromiseWrapper() {
|
|
47
|
+
let resolve;
|
|
48
|
+
let reject;
|
|
49
|
+
const promise = new Promise((resolveCallback, rejectCallback) => {
|
|
50
|
+
resolve = resolveCallback;
|
|
51
|
+
reject = rejectCallback;
|
|
52
|
+
});
|
|
53
|
+
if (!resolve || !reject) {
|
|
54
|
+
throw new Error(`Reject and resolve callbacks were not set by the promise constructor for ${createDeferredPromiseWrapper.name}.`);
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
promise,
|
|
58
|
+
resolve,
|
|
59
|
+
reject,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export async function waitForCondition({ conditionCallback, timeoutMs = 10000, intervalMs = 100, timeoutMessage = '', }) {
|
|
63
|
+
let condition = false;
|
|
64
|
+
let lastError;
|
|
65
|
+
async function checkCondition() {
|
|
66
|
+
try {
|
|
67
|
+
condition = !!(await conditionCallback());
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
condition = false;
|
|
71
|
+
lastError = error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const startTime = Date.now();
|
|
75
|
+
await checkCondition();
|
|
76
|
+
while (!condition) {
|
|
77
|
+
await wait(intervalMs);
|
|
78
|
+
if (Date.now() - startTime >= timeoutMs) {
|
|
79
|
+
const message = timeoutMessage ? `${timeoutMessage}: ` : '';
|
|
80
|
+
throw new Error(`${message}Timeout of "${timeoutMs}" exceeded waiting for condition to be true${extractErrorMessage(lastError)}`);
|
|
81
|
+
}
|
|
82
|
+
await checkCondition();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function deDupeRegExFlags(flags) {
|
|
2
|
+
const deDuped = new Set(Array.from(flags.toLowerCase()));
|
|
3
|
+
return Array.from(deDuped).join('');
|
|
4
|
+
}
|
|
5
|
+
export function addRegExpFlags(originalRegExp, flags) {
|
|
6
|
+
return new RegExp(originalRegExp.source, deDupeRegExFlags([
|
|
7
|
+
originalRegExp.flags,
|
|
8
|
+
flags,
|
|
9
|
+
].join('')));
|
|
10
|
+
}
|
|
11
|
+
export function safeMatch(input, regExp) {
|
|
12
|
+
const match = input.match(regExp);
|
|
13
|
+
return match !== null && match !== void 0 ? match : [];
|
|
14
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare type Tuple<ArrayElementGeneric, LengthGeneric extends number> = LengthGeneric extends LengthGeneric ? number extends LengthGeneric ? ArrayElementGeneric[] : _TupleOf<ArrayElementGeneric, LengthGeneric, []> : never;
|
|
2
|
+
declare type _TupleOf<ArrayElementGeneric, LengthGeneric extends number, FullArrayGeneric extends unknown[]> = FullArrayGeneric['length'] extends LengthGeneric ? FullArrayGeneric : _TupleOf<ArrayElementGeneric, LengthGeneric, [ArrayElementGeneric, ...FullArrayGeneric]>;
|
|
3
|
+
export declare type AtLeastTuple<ArrayElementGeneric, LengthGeneric extends number> = readonly [
|
|
4
|
+
...Tuple<ArrayElementGeneric, LengthGeneric>,
|
|
5
|
+
...ArrayElementGeneric[]
|
|
6
|
+
];
|
|
7
|
+
export declare function isLengthAtLeast<ArrayElementGeneric, LengthGeneric extends number>(array: ReadonlyArray<ArrayElementGeneric>, length: LengthGeneric): array is AtLeastTuple<ArrayElementGeneric, LengthGeneric>;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
declare function getTypeOf(x: any): "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
|
|
2
|
+
export declare type TypeOf = ReturnType<typeof getTypeOf>;
|
|
3
|
+
export declare type TypeOfWithArray = TypeOf | 'array';
|
|
4
|
+
export declare type TypeOfMapping = {
|
|
5
|
+
array: any[];
|
|
6
|
+
bigint: bigint;
|
|
7
|
+
boolean: boolean;
|
|
8
|
+
function: (...args: any[]) => any;
|
|
9
|
+
number: number;
|
|
10
|
+
object: object;
|
|
11
|
+
string: string;
|
|
12
|
+
symbol: symbol;
|
|
13
|
+
undefined: undefined;
|
|
14
|
+
};
|
|
15
|
+
export declare function typeOfWithArray(input: unknown): TypeOfWithArray;
|
|
16
|
+
export declare function isTypeOfWithArray<T extends TypeOfWithArray>(input: unknown, testType: T): input is TypeOfMapping[T];
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// this function is not used at run time, it's only here for types
|
|
2
|
+
// istanbul ignore next
|
|
3
|
+
function getTypeOf(x) {
|
|
4
|
+
return typeof x;
|
|
5
|
+
}
|
|
6
|
+
export function typeOfWithArray(input) {
|
|
7
|
+
return Array.isArray(input) ? 'array' : typeof input;
|
|
8
|
+
}
|
|
9
|
+
export function isTypeOfWithArray(input, testType) {
|
|
10
|
+
const inputType = typeOfWithArray(input);
|
|
11
|
+
return inputType === testType;
|
|
12
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Makes all properties in an object writable. This is the opposite of Readonly<> */
|
|
2
|
+
export declare type Writeable<T> = {
|
|
3
|
+
-readonly [P in keyof T]: T[P];
|
|
4
|
+
};
|
|
5
|
+
/** Makes all property values in an object also readonly. Can cause issues on primitive. */
|
|
6
|
+
export declare type DeepWriteable<T> = {
|
|
7
|
+
-readonly [P in keyof T]: DeepWriteable<T[P]>;
|
|
8
|
+
};
|
|
9
|
+
/** Replace properties in T with properties in U. */
|
|
10
|
+
export declare type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U;
|
|
11
|
+
/** Extract the element type out of an array type. */
|
|
12
|
+
export declare type ArrayElement<ArrayType extends ReadonlyArray<any>> = ArrayType[number];
|
|
13
|
+
/**
|
|
14
|
+
* Same as the Required<> built-in type helper but this requires that each property be present and
|
|
15
|
+
* be not null.
|
|
16
|
+
*/
|
|
17
|
+
export declare type RequiredAndNotNull<T> = {
|
|
18
|
+
[P in keyof T]-?: NonNullable<T[P]>;
|
|
19
|
+
};
|
|
20
|
+
/** Require only a subset of object properties. */
|
|
21
|
+
export declare type RequiredBy<T, K extends keyof T> = Overwrite<T, Required<Pick<T, K>>>;
|
|
22
|
+
/**
|
|
23
|
+
* Require only a subset of object properties and require that they be not null. This is
|
|
24
|
+
* particularly useful in conjunction with the "exactOptionalPropertyTypes" tsconfig flag.
|
|
25
|
+
*/
|
|
26
|
+
export declare type RequiredAndNotNullBy<T, K extends keyof T> = Omit<T, K> & Required<{
|
|
27
|
+
[PropertyName in K]: NonNullable<T[PropertyName]>;
|
|
28
|
+
}>;
|
|
29
|
+
/** If type T = type U, then type Y. Else type N. */
|
|
30
|
+
export declare type IfEquals<T, U, Y = unknown, N = never> = (<G>() => G extends T ? 1 : 2) extends <G>() => G extends U ? 1 : 2 ? Y : N;
|
|
31
|
+
export declare type UnPromise<T> = T extends PromiseLike<infer PromiseType> ? Awaited<PromiseType> : T;
|
|
32
|
+
/**
|
|
33
|
+
* This function returns another function that simply returns whatever input it's given. However, it
|
|
34
|
+
* also checks that the input matches the original wrapNarrowTypeWithTypeCheck's generic, while
|
|
35
|
+
* maintaining strict "const" like typing.
|
|
36
|
+
*
|
|
37
|
+
* Use like this: wrapNarrowTypeWithTypeCheck<EnforcedTypeHere>()(valueToEnforceTypeOn as const)
|
|
38
|
+
*
|
|
39
|
+
* Sometimes "as const" isn't required, usually it is for any object or array though.
|
|
40
|
+
*/
|
|
41
|
+
export declare function wrapNarrowTypeWithTypeCheck<P>(): <T extends P>(input: T) => Readonly<T>;
|
|
42
|
+
/**
|
|
43
|
+
* This type helper is useful for forcing function generics to be explicitly provided, rather than
|
|
44
|
+
* inferring them from the given inputs. See the test file for examples.
|
|
45
|
+
*/
|
|
46
|
+
export declare type NoInfer<T> = [T][T extends any ? 0 : never];
|
|
47
|
+
/**
|
|
48
|
+
* This is a type helper that ensures the given input matches the given generic type. The generic is
|
|
49
|
+
* setup in such a way that if it is omitted (which is typically allowed in TypeScript, resulting in
|
|
50
|
+
* the generic being inferred from the inputs), there will actually be a type error. This forces
|
|
51
|
+
* each usage of this function to explicitly specify the generic, thus giving us type safety for the
|
|
52
|
+
* input.
|
|
53
|
+
*/
|
|
54
|
+
export declare function ensureType<ExpectedType = never>(input: NoInfer<ExpectedType>): NoInfer<ExpectedType>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This function returns another function that simply returns whatever input it's given. However, it
|
|
3
|
+
* also checks that the input matches the original wrapNarrowTypeWithTypeCheck's generic, while
|
|
4
|
+
* maintaining strict "const" like typing.
|
|
5
|
+
*
|
|
6
|
+
* Use like this: wrapNarrowTypeWithTypeCheck<EnforcedTypeHere>()(valueToEnforceTypeOn as const)
|
|
7
|
+
*
|
|
8
|
+
* Sometimes "as const" isn't required, usually it is for any object or array though.
|
|
9
|
+
*/
|
|
10
|
+
export function wrapNarrowTypeWithTypeCheck() {
|
|
11
|
+
return (input) => {
|
|
12
|
+
return input;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* This is a type helper that ensures the given input matches the given generic type. The generic is
|
|
17
|
+
* setup in such a way that if it is omitted (which is typically allowed in TypeScript, resulting in
|
|
18
|
+
* the generic being inferred from the inputs), there will actually be a type error. This forces
|
|
19
|
+
* each usage of this function to explicitly specify the generic, thus giving us type safety for the
|
|
20
|
+
* input.
|
|
21
|
+
*/
|
|
22
|
+
export function ensureType(input) {
|
|
23
|
+
return input;
|
|
24
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './augments/ansi';
|
|
2
|
+
export * from './augments/array';
|
|
3
|
+
export * from './augments/async';
|
|
4
|
+
export * from './augments/common-number';
|
|
5
|
+
export * from './augments/common-string';
|
|
6
|
+
export * from './augments/date';
|
|
7
|
+
export * from './augments/environment';
|
|
8
|
+
export * from './augments/error';
|
|
9
|
+
export * from './augments/function';
|
|
10
|
+
export * from './augments/object';
|
|
11
|
+
export * from './augments/promise';
|
|
12
|
+
export * from './augments/regexp';
|
|
13
|
+
export * from './augments/tuple';
|
|
14
|
+
export * from './augments/type';
|
|
15
|
+
export * from './augments/type-of';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from './augments/ansi';
|
|
2
|
+
export * from './augments/array';
|
|
3
|
+
export * from './augments/async';
|
|
4
|
+
export * from './augments/common-number';
|
|
5
|
+
export * from './augments/common-string';
|
|
6
|
+
export * from './augments/date';
|
|
7
|
+
export * from './augments/environment';
|
|
8
|
+
export * from './augments/error';
|
|
9
|
+
export * from './augments/function';
|
|
10
|
+
export * from './augments/object';
|
|
11
|
+
export * from './augments/promise';
|
|
12
|
+
export * from './augments/regexp';
|
|
13
|
+
export * from './augments/tuple';
|
|
14
|
+
export * from './augments/type';
|
|
15
|
+
export * from './augments/type-of';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const ansiRegex: RegExp;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AtLeastTuple } from './tuple';
|
|
2
|
+
import { ArrayElement } from './type';
|
|
3
|
+
export declare function filterOutIndexes<T>(array: ReadonlyArray<T>, indexes: ReadonlyArray<number>): T[];
|
|
4
|
+
export declare function flatten2dArray<T>(array2d: ReadonlyArray<ReadonlyArray<T>>): T[];
|
|
5
|
+
export declare type AtLeastOneEntryArray<ArrayGeneric extends ReadonlyArray<any>> = AtLeastTuple<ArrayElement<ArrayGeneric>, 1>;
|
|
6
|
+
export declare function trimArrayStrings(input: ReadonlyArray<string>): string[];
|
|
7
|
+
export declare function typedArrayIncludes<T>(array: ReadonlyArray<T>, input: unknown): input is T;
|
|
8
|
+
declare type MapCallbackType<ArrayType extends ReadonlyArray<any>, OutputType> = (value: ArrayElement<ArrayType>, index: number, array: ArrayType) => OutputType;
|
|
9
|
+
/** Preserves tuple types. */
|
|
10
|
+
export declare function typedMap<InputArrayGeneric extends ReadonlyArray<any>, OutputType>(arrayToMap: InputArrayGeneric, mapCallback: MapCallbackType<InputArrayGeneric, OutputType>): {
|
|
11
|
+
[Index in keyof InputArrayGeneric]: OutputType;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Acts like calling Array.prototype.forEach in that all elements are executed upon in order, and
|
|
3
|
+
* each execution is blocking. Meaning, the callback won't be called on element 2 until the callback
|
|
4
|
+
* has finished its call on element 1.
|
|
5
|
+
*/
|
|
6
|
+
export declare function awaitedForEach<OriginalGeneric>(input: ReadonlyArray<OriginalGeneric>, callback: (arrayElement: OriginalGeneric, index: number, wholeArray: ReadonlyArray<OriginalGeneric>) => void | PromiseLike<void>): Promise<void>;
|
|
7
|
+
export declare function awaitedBlockingMap<OriginalGeneric, MappedGeneric>(input: ReadonlyArray<OriginalGeneric>, callback: (arrayElement: OriginalGeneric, index: number, wholeArray: ReadonlyArray<OriginalGeneric>) => MappedGeneric | PromiseLike<MappedGeneric>): Promise<Awaited<MappedGeneric>[]>;
|
|
8
|
+
export declare function awaitedFilter<OriginalGeneric>(arrayInput: ReadonlyArray<OriginalGeneric>, filterCallback: (arrayElement: OriginalGeneric, index: number, wholeArray: ReadonlyArray<OriginalGeneric>) => Promise<unknown>, options?: {
|
|
9
|
+
/**
|
|
10
|
+
* Each call to the filter callback is blocking, meaning the next one won't start until the
|
|
11
|
+
* current one finishes. By default this is false.
|
|
12
|
+
*/
|
|
13
|
+
blocking?: boolean | undefined;
|
|
14
|
+
}): Promise<OriginalGeneric[]>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export declare function addCommasToNumber(input: number): string;
|
|
2
|
+
export declare function clamp(
|
|
3
|
+
/**
|
|
4
|
+
* This uses a destructured object so that consumers cannot get confused as to which input is
|
|
5
|
+
* which (which would be easy to do since they're all of the same type).
|
|
6
|
+
*/
|
|
7
|
+
{ value, min, max, }: {
|
|
8
|
+
value: number;
|
|
9
|
+
min: number;
|
|
10
|
+
max: number;
|
|
11
|
+
}): number;
|
|
12
|
+
/**
|
|
13
|
+
* This truncates a number such that is will at a max have 6 characters including suffix, decimal
|
|
14
|
+
* point, or comma.
|
|
15
|
+
*
|
|
16
|
+
* Default suffixes are:
|
|
17
|
+
*
|
|
18
|
+
* '', // no suffix, numbers below 1000
|
|
19
|
+
* 'k', // thousand
|
|
20
|
+
* 'M', // million
|
|
21
|
+
* 'B', // billion
|
|
22
|
+
* 'T', // trillion
|
|
23
|
+
* 'P', // peta-, quadrillion
|
|
24
|
+
* 'E', // exa- quintillion
|
|
25
|
+
* 'Z', // zetta- sextillion
|
|
26
|
+
* 'Y', // yotta- septillion
|
|
27
|
+
*/
|
|
28
|
+
export declare function truncateNumber(originalValue: unknown, { customSuffixes, suppressErrorLogging, customErrorLogCallback, }?: {
|
|
29
|
+
customSuffixes?: ReadonlyArray<string>;
|
|
30
|
+
suppressErrorLogging?: boolean;
|
|
31
|
+
customErrorLogCallback?: (...args: any) => void;
|
|
32
|
+
}): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { AtLeastTuple } from './tuple';
|
|
2
|
+
/**
|
|
3
|
+
* Join elements into a string with commas separating each value. Add a conjunction before the final
|
|
4
|
+
* item in the list. If the array has a length < 2, the conjunction is not added. If the list is
|
|
5
|
+
* only of length 2, then no commas are added.
|
|
6
|
+
*
|
|
7
|
+
* @param list Array of items to be converted into strings. Works best if these are simply strings
|
|
8
|
+
* to begin with.
|
|
9
|
+
* @param conjunction Defaults to 'and'. The conjunction to be used before the final element.
|
|
10
|
+
*/
|
|
11
|
+
export declare function joinWithFinalConjunction(list: ReadonlyArray<any>, conjunction?: string): string;
|
|
12
|
+
export declare function removeAnsiEscapeCodes(input: string): string;
|
|
13
|
+
export declare const removeColor: typeof removeAnsiEscapeCodes;
|
|
14
|
+
export declare function removeCommasFromNumberString(numberString: string): string;
|
|
15
|
+
/** Collapse all consecutive white space into just one space and trim surrounding whitespace. */
|
|
16
|
+
export declare function collapseWhiteSpace(input: string): string;
|
|
17
|
+
/** Same as String.prototype.split but includes the delimiter to split by in the output array. */
|
|
18
|
+
export declare function splitIncludeSplit(original: string, splitterInput: string | RegExp, caseSensitive: boolean): readonly string[];
|
|
19
|
+
export declare type CasingOptions = {
|
|
20
|
+
capitalizeFirstLetter: boolean;
|
|
21
|
+
};
|
|
22
|
+
export declare function capitalizeFirstLetter<InputGeneric extends string>(input: InputGeneric): Capitalize<InputGeneric>;
|
|
23
|
+
export declare function kebabCaseToCamelCase(rawKebabCase: string, casingOptions?: Partial<CasingOptions> | undefined): string;
|
|
24
|
+
export declare function camelCaseToKebabCase(rawCamelCase: string): string;
|
|
25
|
+
export declare function replaceStringAtIndex(originalString: string, start: number, newString: string, length?: number): string;
|
|
26
|
+
/**
|
|
27
|
+
* Escapes characters from the given string so that it can be used within a RegExp without being
|
|
28
|
+
* parsed as RegExp syntax.
|
|
29
|
+
*/
|
|
30
|
+
export declare function escapeStringForRegExp(input: string): string;
|
|
31
|
+
export declare function getAllIndexesOf<IncludeLength extends boolean | undefined>({ searchIn, searchFor, caseSensitive, includeLength, }: {
|
|
32
|
+
searchIn: string;
|
|
33
|
+
searchFor: string | RegExp;
|
|
34
|
+
/**
|
|
35
|
+
* CaseSensitive only applies when the input is a string. Otherwise, the RegExp's "i" flag is
|
|
36
|
+
* used to determine case sensitivity.
|
|
37
|
+
*/
|
|
38
|
+
caseSensitive: boolean;
|
|
39
|
+
includeLength?: IncludeLength;
|
|
40
|
+
}): IncludeLength extends true ? {
|
|
41
|
+
index: number;
|
|
42
|
+
length: number;
|
|
43
|
+
}[] : number[];
|
|
44
|
+
export declare function typedSplit(input: string, splitString: string): AtLeastTuple<string, 1>;
|