@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.
Files changed (84) hide show
  1. package/dist/{augments → cjs/augments}/ansi.d.ts +0 -0
  2. package/dist/{augments → cjs/augments}/ansi.js +0 -0
  3. package/dist/{augments → cjs/augments}/array.d.ts +1 -8
  4. package/dist/cjs/augments/array.js +25 -0
  5. package/dist/cjs/augments/async.d.ts +14 -0
  6. package/dist/cjs/augments/async.js +29 -0
  7. package/dist/{augments/number.d.ts → cjs/augments/common-number.d.ts} +8 -3
  8. package/dist/{augments/number.js → cjs/augments/common-number.js} +39 -11
  9. package/dist/{augments/string.d.ts → cjs/augments/common-string.d.ts} +14 -4
  10. package/dist/{augments/string.js → cjs/augments/common-string.js} +30 -27
  11. package/dist/{augments → cjs/augments}/date.d.ts +1 -1
  12. package/dist/{augments → cjs/augments}/date.js +2 -2
  13. package/dist/cjs/augments/environment.d.ts +1 -0
  14. package/dist/cjs/augments/environment.js +7 -0
  15. package/dist/{augments → cjs/augments}/error.d.ts +0 -0
  16. package/dist/{augments → cjs/augments}/error.js +0 -0
  17. package/dist/{augments → cjs/augments}/function.d.ts +0 -0
  18. package/dist/{augments → cjs/augments}/function.js +0 -0
  19. package/dist/{augments → cjs/augments}/object.d.ts +0 -0
  20. package/dist/{augments → cjs/augments}/object.js +0 -0
  21. package/dist/{augments → cjs/augments}/promise.d.ts +0 -0
  22. package/dist/{augments → cjs/augments}/promise.js +0 -0
  23. package/dist/{augments → cjs/augments}/regexp.d.ts +0 -0
  24. package/dist/{augments → cjs/augments}/regexp.js +0 -0
  25. package/dist/{augments → cjs/augments}/tuple.d.ts +0 -0
  26. package/dist/{augments → cjs/augments}/tuple.js +0 -0
  27. package/dist/{augments → cjs/augments}/type-of.d.ts +0 -0
  28. package/dist/{augments → cjs/augments}/type-of.js +2 -0
  29. package/dist/{augments → cjs/augments}/type.d.ts +0 -0
  30. package/dist/{augments → cjs/augments}/type.js +0 -0
  31. package/dist/{index.d.ts → cjs/index.d.ts} +4 -3
  32. package/dist/{index.js → cjs/index.js} +4 -3
  33. package/dist/esm/augments/ansi.d.ts +1 -0
  34. package/dist/esm/augments/ansi.js +24 -0
  35. package/dist/esm/augments/array.d.ts +13 -0
  36. package/dist/esm/augments/array.js +17 -0
  37. package/dist/esm/augments/async.d.ts +14 -0
  38. package/dist/esm/augments/async.js +23 -0
  39. package/dist/esm/augments/common-number.d.ts +32 -0
  40. package/dist/esm/augments/common-number.js +105 -0
  41. package/dist/esm/augments/common-string.d.ts +44 -0
  42. package/dist/esm/augments/common-string.js +180 -0
  43. package/dist/esm/augments/date.d.ts +26 -0
  44. package/dist/esm/augments/date.js +74 -0
  45. package/dist/esm/augments/environment.d.ts +1 -0
  46. package/dist/esm/augments/environment.js +3 -0
  47. package/dist/esm/augments/error.d.ts +8 -0
  48. package/dist/esm/augments/error.js +36 -0
  49. package/dist/esm/augments/function.d.ts +1 -0
  50. package/dist/esm/augments/function.js +3 -0
  51. package/dist/esm/augments/object.d.ts +63 -0
  52. package/dist/esm/augments/object.js +252 -0
  53. package/dist/esm/augments/promise.d.ts +23 -0
  54. package/dist/esm/augments/promise.js +84 -0
  55. package/dist/esm/augments/regexp.d.ts +3 -0
  56. package/dist/esm/augments/regexp.js +14 -0
  57. package/dist/esm/augments/tuple.d.ts +8 -0
  58. package/dist/esm/augments/tuple.js +3 -0
  59. package/dist/esm/augments/type-of.d.ts +17 -0
  60. package/dist/esm/augments/type-of.js +12 -0
  61. package/dist/esm/augments/type.d.ts +54 -0
  62. package/dist/esm/augments/type.js +24 -0
  63. package/dist/esm/index.d.ts +15 -0
  64. package/dist/esm/index.js +15 -0
  65. package/dist/types/augments/ansi.d.ts +1 -0
  66. package/dist/types/augments/array.d.ts +13 -0
  67. package/dist/types/augments/async.d.ts +14 -0
  68. package/dist/types/augments/common-number.d.ts +32 -0
  69. package/dist/types/augments/common-string.d.ts +44 -0
  70. package/dist/types/augments/date.d.ts +26 -0
  71. package/dist/types/augments/environment.d.ts +1 -0
  72. package/dist/types/augments/error.d.ts +8 -0
  73. package/dist/types/augments/function.d.ts +1 -0
  74. package/dist/types/augments/object.d.ts +63 -0
  75. package/dist/types/augments/promise.d.ts +23 -0
  76. package/dist/types/augments/regexp.d.ts +3 -0
  77. package/dist/types/augments/tuple.d.ts +8 -0
  78. package/dist/types/augments/type-of.d.ts +17 -0
  79. package/dist/types/augments/type.d.ts +54 -0
  80. package/dist/types/index.d.ts +15 -0
  81. package/package.json +6 -6
  82. package/dist/augments/array.js +0 -44
  83. package/dist/augments/type-test.d.ts +0 -3
  84. package/dist/augments/type-test.js +0 -2
@@ -0,0 +1,105 @@
1
+ import { removeCommasFromNumberString, typedSplit } from './common-string';
2
+ import { safeMatch } from './regexp';
3
+ export function addCommasToNumber(input) {
4
+ const stringValue = String(input);
5
+ const [digits, decimalValues,] = stringValue.split('.');
6
+ const decimalString = decimalValues ? `.${decimalValues}` : '';
7
+ const separated = safeMatch(digits.split('').reverse().join(''), /.{1,3}/g)
8
+ .reverse()
9
+ .map((entry) => entry.split('').reverse().join(''));
10
+ const withCommas = separated.join(',');
11
+ return `${withCommas}${decimalString}`;
12
+ }
13
+ export function clamp(
14
+ /**
15
+ * This uses a destructured object so that consumers cannot get confused as to which input is
16
+ * which (which would be easy to do since they're all of the same type).
17
+ */
18
+ { value, min, max, }) {
19
+ return Math.max(Math.min(value, max), min);
20
+ }
21
+ const defaultTruncationSuffixes = [
22
+ '',
23
+ 'k',
24
+ 'M',
25
+ 'B',
26
+ 'T',
27
+ 'P',
28
+ 'E',
29
+ 'Z',
30
+ 'Y', // yotta- septillion
31
+ ];
32
+ function recursiveTruncation(value, recursionDepth = 0, decimalValues = '') {
33
+ var _a;
34
+ if (value.includes('e+')) {
35
+ throw new Error(`Number is too large, it cannot be truncated: ${value}`);
36
+ }
37
+ else if (value.includes('e-')) {
38
+ throw new Error(`Number is too small, it cannot be truncated: ${value}`);
39
+ }
40
+ const split = typedSplit(value, '.');
41
+ decimalValues = (_a = split[1]) !== null && _a !== void 0 ? _a : decimalValues;
42
+ const amount = split[0];
43
+ if (amount.length > 3) {
44
+ decimalValues = amount.slice(-3);
45
+ return recursiveTruncation(amount.slice(0, -3), recursionDepth + 1, decimalValues);
46
+ }
47
+ return {
48
+ value: amount,
49
+ decimalValues,
50
+ recursionDepth,
51
+ };
52
+ }
53
+ const maxDecimals = 4;
54
+ /**
55
+ * This truncates a number such that is will at a max have 6 characters including suffix, decimal
56
+ * point, or comma.
57
+ *
58
+ * Default suffixes are:
59
+ *
60
+ * '', // no suffix, numbers below 1000
61
+ * 'k', // thousand
62
+ * 'M', // million
63
+ * 'B', // billion
64
+ * 'T', // trillion
65
+ * 'P', // peta-, quadrillion
66
+ * 'E', // exa- quintillion
67
+ * 'Z', // zetta- sextillion
68
+ * 'Y', // yotta- septillion
69
+ */
70
+ export function truncateNumber(originalValue, { customSuffixes, suppressErrorLogging, customErrorLogCallback, } = {}) {
71
+ try {
72
+ const value = typeof originalValue === 'number'
73
+ ? originalValue
74
+ : typeof originalValue === 'string'
75
+ ? Number(removeCommasFromNumberString(originalValue))
76
+ : Number(originalValue);
77
+ if (isNaN(value)) {
78
+ throw new Error(`${originalValue} could not be converted into a number.`);
79
+ }
80
+ const stringValue = String(value);
81
+ const results = recursiveTruncation(stringValue);
82
+ const suffixes = customSuffixes !== null && customSuffixes !== void 0 ? customSuffixes : defaultTruncationSuffixes;
83
+ const suffix = suffixes[results.recursionDepth];
84
+ if (suffix === undefined) {
85
+ throw new Error(`Number is too large, could not truncate: ${value}`);
86
+ }
87
+ const decimalPlaces = maxDecimals - (results.value.length - 1) - suffix.length;
88
+ const decimalValues = results.decimalValues.replace(/0+$/, '').slice(0, decimalPlaces);
89
+ const withDecimal = decimalValues.length ? `.${decimalValues}` : '';
90
+ const combined = `${results.value}${withDecimal}${suffix}`;
91
+ if (combined.length > stringValue.length + 1) {
92
+ return addCommasToNumber(value);
93
+ }
94
+ else {
95
+ return combined;
96
+ }
97
+ }
98
+ catch (error) {
99
+ const errorCallback = customErrorLogCallback ? customErrorLogCallback : console.error;
100
+ if (!suppressErrorLogging) {
101
+ errorCallback(error);
102
+ }
103
+ return String(originalValue);
104
+ }
105
+ }
@@ -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>;
@@ -0,0 +1,180 @@
1
+ import { ansiRegex } from './ansi';
2
+ import { deDupeRegExFlags } from './regexp';
3
+ /**
4
+ * Join elements into a string with commas separating each value. Add a conjunction before the final
5
+ * item in the list. If the array has a length < 2, the conjunction is not added. If the list is
6
+ * only of length 2, then no commas are added.
7
+ *
8
+ * @param list Array of items to be converted into strings. Works best if these are simply strings
9
+ * to begin with.
10
+ * @param conjunction Defaults to 'and'. The conjunction to be used before the final element.
11
+ */
12
+ export function joinWithFinalConjunction(list, conjunction = 'and') {
13
+ if (list.length < 2) {
14
+ /**
15
+ * If there are not multiple things in the list to join, just turn the list into a string
16
+ * for an empty list, this will be '', for a single item list, this will just be the first
17
+ * item as a string.
18
+ */
19
+ return list.join('');
20
+ }
21
+ /** When there are only two items in the list, we don't want any commas. */
22
+ const commaSep = list.length > 2 ? ', ' : ' ';
23
+ const commaJoined = list.slice(0, -1).join(commaSep);
24
+ const fullyJoined = `${commaJoined}${commaSep}${conjunction} ${list[list.length - 1]}`;
25
+ return fullyJoined;
26
+ }
27
+ export function removeAnsiEscapeCodes(input) {
28
+ return input.replace(ansiRegex, '');
29
+ }
30
+ export const removeColor = removeAnsiEscapeCodes;
31
+ export function removeCommasFromNumberString(numberString) {
32
+ return numberString.replace(/,/g, '');
33
+ }
34
+ /** Collapse all consecutive white space into just one space and trim surrounding whitespace. */
35
+ export function collapseWhiteSpace(input) {
36
+ return (input
37
+ // sometimes \n isn't included in \s
38
+ .replace(/\n/g, ' ')
39
+ .trim()
40
+ .replace(/\s{2,}/g, ' '));
41
+ }
42
+ /** Same as String.prototype.split but includes the delimiter to split by in the output array. */
43
+ export function splitIncludeSplit(original, splitterInput, caseSensitive) {
44
+ const indexLengths = getAllIndexesOf({
45
+ searchIn: original,
46
+ searchFor: splitterInput,
47
+ caseSensitive,
48
+ includeLength: true,
49
+ });
50
+ const splitter = makeCaseInsensitiveRegExp(splitterInput, caseSensitive);
51
+ const splits = original.split(splitter);
52
+ const splitterIncluded = splits.reduce((accum, current, index) => {
53
+ // this will be undefined on the last index
54
+ const splitterLength = indexLengths[index];
55
+ const includeCurrent = accum.concat(current);
56
+ if (splitterLength) {
57
+ const splitterMatch = original.slice(splitterLength.index, splitterLength.index + splitterLength.length);
58
+ return includeCurrent.concat(splitterMatch);
59
+ }
60
+ else {
61
+ return includeCurrent;
62
+ }
63
+ }, []);
64
+ return splitterIncluded;
65
+ }
66
+ const defaultCasingOptions = {
67
+ capitalizeFirstLetter: false,
68
+ };
69
+ export function capitalizeFirstLetter(input) {
70
+ if (!input.length) {
71
+ return '';
72
+ }
73
+ const firstLetter = input[0];
74
+ return (firstLetter.toUpperCase() + input.slice(1));
75
+ }
76
+ function maybeCapitalize(input, casingOptions) {
77
+ return casingOptions.capitalizeFirstLetter ? capitalizeFirstLetter(input) : input;
78
+ }
79
+ export function kebabCaseToCamelCase(rawKebabCase, casingOptions = defaultCasingOptions) {
80
+ const kebabCase = rawKebabCase.toLowerCase();
81
+ if (!kebabCase.length) {
82
+ return '';
83
+ }
84
+ const camelCase = kebabCase
85
+ .replace(/^-+/, '')
86
+ .replace(/-{2,}/g, '-')
87
+ .replace(/-(?:.|$)/g, (dashMatch) => {
88
+ const letter = dashMatch[1];
89
+ if (letter) {
90
+ return letter.toUpperCase();
91
+ }
92
+ else {
93
+ return '';
94
+ }
95
+ });
96
+ return maybeCapitalize(camelCase, casingOptions);
97
+ }
98
+ function isLowerCase(input) {
99
+ // this excludes letters that are identical between lower and upper case like punctuation
100
+ return input !== input.toUpperCase();
101
+ }
102
+ export function camelCaseToKebabCase(rawCamelCase) {
103
+ const kebabCase = rawCamelCase
104
+ .split('')
105
+ .reduce((accum, currentLetter, index, originalString) => {
106
+ const previousLetter = index > 0 ? originalString[index - 1] : '';
107
+ const nextLetter = index < originalString.length - 1 ? originalString[index + 1] : '';
108
+ const possibleWordBoundary = isLowerCase(previousLetter) || isLowerCase(nextLetter);
109
+ if (currentLetter === currentLetter.toLowerCase() ||
110
+ index === 0 ||
111
+ !possibleWordBoundary) {
112
+ accum += currentLetter;
113
+ }
114
+ else {
115
+ accum += `-${currentLetter.toLowerCase()}`;
116
+ }
117
+ return accum;
118
+ }, '')
119
+ .toLowerCase();
120
+ return kebabCase;
121
+ }
122
+ export function replaceStringAtIndex(originalString, start, newString, length = newString.length) {
123
+ const before = originalString.substring(0, start);
124
+ const after = originalString.substring(start + length);
125
+ return `${before}${newString}${after}`;
126
+ }
127
+ /**
128
+ * Escapes characters from the given string so that it can be used within a RegExp without being
129
+ * parsed as RegExp syntax.
130
+ */
131
+ export function escapeStringForRegExp(input) {
132
+ return input.replace(/[\^$\\.*+?()[\]{}|]/g, '\\$&');
133
+ }
134
+ function makeCaseInsensitiveRegExp(searchForInput, caseSensitive) {
135
+ const regExpFlags = `g${!caseSensitive && typeof searchForInput === 'string' ? 'i' : ''}`;
136
+ const searchFor = searchForInput instanceof RegExp
137
+ ? new RegExp(searchForInput.source, deDupeRegExFlags(`${searchForInput.flags}${regExpFlags}`))
138
+ : new RegExp(escapeStringForRegExp(searchForInput), regExpFlags);
139
+ return searchFor;
140
+ }
141
+ export function getAllIndexesOf({ searchIn, searchFor, caseSensitive, includeLength, }) {
142
+ const searchRegExp = makeCaseInsensitiveRegExp(searchFor, caseSensitive);
143
+ const indexes = [];
144
+ const indexesAndLengths = [];
145
+ searchIn.replace(searchRegExp, (...matchResults) => {
146
+ /**
147
+ * Grabbing the second to last entry in the array (rather than the second) takes capture
148
+ * groups into account.
149
+ */
150
+ const matchIndex = matchResults[matchResults.length - 2];
151
+ // this is used as a type safety catch and cannot actually be triggered on purpose
152
+ // istanbul ignore next
153
+ if (typeof matchIndex !== 'number') {
154
+ throw new Error(`Match index "${matchIndex}" is not a number. Searching for "${searchFor}" in "${searchIn}".`);
155
+ }
156
+ const regExpMatch = matchResults[0];
157
+ // this is used as a type safety catch and cannot actually be triggered on purpose
158
+ // istanbul ignore next
159
+ if (typeof regExpMatch !== 'string') {
160
+ throw new Error(`regExpMatch should've been a string but was ${typeof regExpMatch}!`);
161
+ }
162
+ indexesAndLengths.push({ index: matchIndex, length: regExpMatch.length });
163
+ indexes.push(matchIndex);
164
+ const originalMatch = matchResults[0];
165
+ // this is used as a type safety catch and cannot actually be triggered on purpose
166
+ // istanbul ignore next
167
+ if (typeof originalMatch !== 'string') {
168
+ throw new Error(`Original match when searching for "${searchFor}" in "${searchIn}" at index ${matchIndex} is not a string.`);
169
+ }
170
+ /**
171
+ * Don't actually change any text. What we do here doesn't matter because we're not
172
+ * using the output of the .replace method, we're just producing side effects.
173
+ */
174
+ return originalMatch;
175
+ });
176
+ return (includeLength ? indexesAndLengths : indexes);
177
+ }
178
+ export function typedSplit(input, splitString) {
179
+ return input.split(splitString);
180
+ }
@@ -0,0 +1,26 @@
1
+ export declare const englishFullMonthNames: readonly ["january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"];
2
+ export declare const englishShortMonthNames: string[];
3
+ export declare class InvalidDateError extends Error {
4
+ readonly name = "InvalidDateError";
5
+ }
6
+ /**
7
+ * @param slashFormatString String that should be of format "MM/DD/YY", "MM/DD/YYYY". When the year
8
+ * portion only contains 2 numbers ("MM/DD/YY") the century must be provided in the form of the
9
+ * yearPrefix input.
10
+ * @param yearPrefix String or number that is used to prefix slash format strings that only contain
11
+ * 2 digits ("MM/DD/YY"). If the year is entirely missing form the given slash format string, the
12
+ * year will default to year 00 of the given century. See test file for examples.
13
+ */
14
+ export declare function createDateFromSlashFormat(slashFormatString: string, yearPrefix?: number | string): Date;
15
+ /**
16
+ * @param commaFormatString Should be at string of the form "monthName dayNumber, fullYear" Example:
17
+ * "May 19, 2005"
18
+ * @param ignoreInvalidMonth Set to true to ignore invalid months and just use the current UTC month
19
+ */
20
+ export declare function createDateFromNamedCommaFormat(commaFormatString: string, ignoreInvalidMonth?: boolean): Date;
21
+ /**
22
+ * Converts an iso-formatted string to a UTC date object. The time is nulled out to all zeros.
23
+ *
24
+ * @param isoFormatString Should be a date in the format YYYY-MM-DD.
25
+ */
26
+ export declare function createDateFromUtcIsoFormat(isoFormatString: string): Date;
@@ -0,0 +1,74 @@
1
+ export const englishFullMonthNames = [
2
+ 'january',
3
+ 'february',
4
+ 'march',
5
+ 'april',
6
+ 'may',
7
+ 'june',
8
+ 'july',
9
+ 'august',
10
+ 'september',
11
+ 'october',
12
+ 'november',
13
+ 'december',
14
+ ];
15
+ export const englishShortMonthNames = englishFullMonthNames.map((longMonthName) => longMonthName.slice(0, 3));
16
+ export class InvalidDateError extends Error {
17
+ constructor() {
18
+ super(...arguments);
19
+ this.name = 'InvalidDateError';
20
+ }
21
+ }
22
+ /**
23
+ * @param slashFormatString String that should be of format "MM/DD/YY", "MM/DD/YYYY". When the year
24
+ * portion only contains 2 numbers ("MM/DD/YY") the century must be provided in the form of the
25
+ * yearPrefix input.
26
+ * @param yearPrefix String or number that is used to prefix slash format strings that only contain
27
+ * 2 digits ("MM/DD/YY"). If the year is entirely missing form the given slash format string, the
28
+ * year will default to year 00 of the given century. See test file for examples.
29
+ */
30
+ export function createDateFromSlashFormat(slashFormatString, yearPrefix = '') {
31
+ const [month, day, rawYearEnding = '',] = slashFormatString.split('/');
32
+ if (!month || !day) {
33
+ throw new Error(`Unable to extract month or day from "${slashFormatString}"`);
34
+ }
35
+ const yearEnding = rawYearEnding.length < 4 ? `${yearPrefix}${rawYearEnding.padStart(2, '0')}` : rawYearEnding;
36
+ const returnDate = createDateFromUtcIsoFormat(`${yearEnding.padStart(4, '0')}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`);
37
+ return returnDate;
38
+ }
39
+ /**
40
+ * @param commaFormatString Should be at string of the form "monthName dayNumber, fullYear" Example:
41
+ * "May 19, 2005"
42
+ * @param ignoreInvalidMonth Set to true to ignore invalid months and just use the current UTC month
43
+ */
44
+ export function createDateFromNamedCommaFormat(commaFormatString, ignoreInvalidMonth = false) {
45
+ const [monthName, dayNumber, fullYear,] = commaFormatString.replace(',', '').split(' ');
46
+ if (!monthName || !dayNumber || !fullYear) {
47
+ throw new InvalidDateError(`Invalid ${createDateFromNamedCommaFormat.name} input: ${commaFormatString}`);
48
+ }
49
+ const longMonthIndex = englishFullMonthNames.indexOf(monthName.toLowerCase());
50
+ const shortMonthIndex = englishShortMonthNames.indexOf(monthName.toLowerCase());
51
+ let monthIndex = longMonthIndex === -1 ? shortMonthIndex : longMonthIndex;
52
+ if (monthIndex === -1) {
53
+ if (ignoreInvalidMonth) {
54
+ monthIndex = new Date().getUTCMonth();
55
+ }
56
+ else {
57
+ throw new InvalidDateError(`Month name ${monthName} was not found.`);
58
+ }
59
+ }
60
+ const returnDate = createDateFromUtcIsoFormat(`${fullYear.padStart(4, '0')}-${String(monthIndex + 1).padStart(2, '0')}-${dayNumber.padStart(2, '0')}`);
61
+ return returnDate;
62
+ }
63
+ /**
64
+ * Converts an iso-formatted string to a UTC date object. The time is nulled out to all zeros.
65
+ *
66
+ * @param isoFormatString Should be a date in the format YYYY-MM-DD.
67
+ */
68
+ export function createDateFromUtcIsoFormat(isoFormatString) {
69
+ const utcDate = new Date(isoFormatString + 'T00:00:00.000Z');
70
+ if (isNaN(Number(utcDate))) {
71
+ throw new InvalidDateError(`Invalid utc date formed from input "${isoFormatString}"`);
72
+ }
73
+ return utcDate;
74
+ }
@@ -0,0 +1 @@
1
+ export declare function isBrowser(): boolean;
@@ -0,0 +1,3 @@
1
+ export function isBrowser() {
2
+ return typeof window !== 'undefined';
3
+ }
@@ -0,0 +1,8 @@
1
+ import { AtLeastTuple } from './tuple';
2
+ export declare function combineErrors(errors: AtLeastTuple<Error, 1>): Error;
3
+ export declare function combineErrors(errors: ReadonlyArray<never>): undefined;
4
+ export declare function combineErrors(errors: ReadonlyArray<Error>): Error | undefined;
5
+ export declare function combineErrors(errors?: undefined): undefined;
6
+ export declare function combineErrorMessages(errors?: ReadonlyArray<Error | string | undefined> | undefined): string;
7
+ export declare function extractErrorMessage(error: unknown): string;
8
+ export declare function ensureError(input: unknown): Error;
@@ -0,0 +1,36 @@
1
+ import { isTruthy } from './function';
2
+ export function combineErrors(errors) {
3
+ if (!errors || errors.length === 0) {
4
+ return undefined;
5
+ }
6
+ const firstError = errors[0];
7
+ if (errors.length === 1 && firstError) {
8
+ return firstError;
9
+ }
10
+ return new Error(errors.map((error) => extractErrorMessage(error).trim()).join('\n'));
11
+ }
12
+ export function combineErrorMessages(errors) {
13
+ if (!errors) {
14
+ return '';
15
+ }
16
+ return errors.map(extractErrorMessage).filter(isTruthy).join('\n');
17
+ }
18
+ export function extractErrorMessage(error) {
19
+ if (!error) {
20
+ return '';
21
+ }
22
+ if (error instanceof Error) {
23
+ return error.message;
24
+ }
25
+ else {
26
+ return String(error);
27
+ }
28
+ }
29
+ export function ensureError(input) {
30
+ if (input instanceof Error) {
31
+ return input;
32
+ }
33
+ else {
34
+ return new Error(extractErrorMessage(input));
35
+ }
36
+ }
@@ -0,0 +1 @@
1
+ export declare function isTruthy<T>(input: T): input is NonNullable<T>;
@@ -0,0 +1,3 @@
1
+ export function isTruthy(input) {
2
+ return !!input;
3
+ }
@@ -0,0 +1,63 @@
1
+ import { AtLeastOneEntryArray } from './array';
2
+ import { NoInfer, RequiredBy, UnPromise } from './type';
3
+ export declare function getEnumTypedKeys<T extends object>(input: T): (keyof T)[];
4
+ export declare function getEnumTypedValues<T extends object>(input: T): T[keyof T][];
5
+ export declare function isEnumValue<T extends object>(input: unknown, checkEnum: T): input is T[keyof T];
6
+ export declare function isKeyof<ObjectGeneric>(key: PropertyKey, object: ObjectGeneric): key is keyof object;
7
+ export declare function filterToEnumValues<T extends object>(inputs: ReadonlyArray<unknown>, checkEnum: T, caseInsensitive?: boolean): T[keyof T][];
8
+ export declare function getObjectTypedKeys<ObjectGeneric extends unknown>(input: ObjectGeneric): ReadonlyArray<keyof ObjectGeneric>;
9
+ export declare function getObjectTypedValues<ObjectGeneric extends unknown>(input: ObjectGeneric): ObjectGeneric[keyof ObjectGeneric][];
10
+ declare type ExtractValue<KeyGeneric extends PropertyKey, ParentGeneric> = KeyGeneric extends keyof ParentGeneric ? RequiredBy<ParentGeneric, KeyGeneric>[KeyGeneric] : KeyGeneric extends keyof Extract<ParentGeneric, Record<KeyGeneric, any>> ? RequiredBy<Extract<ParentGeneric, Record<KeyGeneric, any>>, KeyGeneric>[KeyGeneric] : never;
11
+ declare type CombinedParentValue<KeyGeneric extends PropertyKey, ParentGeneric> = ExtractValue<KeyGeneric, ParentGeneric> extends never ? unknown : ExtractValue<KeyGeneric, ParentGeneric>;
12
+ declare type CombineTypeWithKey<KeyGeneric extends PropertyKey, ParentGeneric> = ParentGeneric & Record<KeyGeneric, CombinedParentValue<KeyGeneric, ParentGeneric>>;
13
+ export declare function typedHasProperty<KeyGeneric extends PropertyKey, ParentGeneric>(inputObject: ParentGeneric, inputKey: KeyGeneric): inputObject is CombineTypeWithKey<KeyGeneric, ParentGeneric>;
14
+ export declare function typedHasProperties<KeyGeneric extends PropertyKey, ParentGeneric>(inputObject: ParentGeneric, inputKeys: ReadonlyArray<KeyGeneric>): inputObject is CombineTypeWithKey<KeyGeneric, ParentGeneric>;
15
+ export declare function isObject(input: any): input is NonNullable<object>;
16
+ export declare function getEntriesSortedByKey(input: object): [string, unknown][];
17
+ export declare function areJsonEqual(a: object, b: object): boolean;
18
+ export declare type InnerMappedValues<EntireInputGeneric extends object, MappedValueGeneric> = {
19
+ [MappedProp in keyof EntireInputGeneric]: MappedValueGeneric;
20
+ };
21
+ export declare type MappedValues<EntireInputGeneric extends object, MappedValueGeneric> = MappedValueGeneric extends PromiseLike<unknown> ? Promise<InnerMappedValues<EntireInputGeneric, UnPromise<MappedValueGeneric>>> : InnerMappedValues<EntireInputGeneric, UnPromise<MappedValueGeneric>>;
22
+ /**
23
+ * Creates a new object with the same properties as the input object, but with values set to the
24
+ * result of mapCallback for each property.
25
+ */
26
+ export declare function mapObjectValues<EntireInputGeneric extends object, MappedValueGeneric>(inputObject: EntireInputGeneric, mapCallback: (inputKey: keyof EntireInputGeneric, keyValue: EntireInputGeneric[typeof inputKey], fullObject: EntireInputGeneric) => MappedValueGeneric): MappedValues<EntireInputGeneric, MappedValueGeneric>;
27
+ export declare function filterObject<ObjectGeneric extends object>(inputObject: ObjectGeneric, callback: (key: keyof ObjectGeneric, value: ObjectValueType<ObjectGeneric>, fullObject: ObjectGeneric) => boolean): Partial<ObjectGeneric>;
28
+ /** The input here must be serializable otherwise JSON parsing errors will be thrown */
29
+ export declare function copyThroughJson<T>(input: T): T;
30
+ export declare type ObjectValueType<T extends object> = T[keyof T];
31
+ /**
32
+ * Checks that the first input, testThisOne, matches the object shape of the second input,
33
+ * compareToThisOne. Does not compare exact values of properties, only types.
34
+ *
35
+ * To allow the test input, the first input, to have additional keys that the compare input, the
36
+ * second input, does not have, pass in a third argument set to true.
37
+ *
38
+ * This function REQUIRES a generic to be assigned to it: it cannot infer it from the inputs.
39
+ *
40
+ * The compare input, the second input, is required to have at least one entry in every array value
41
+ * that exists. If more array values are present, they will be considered other possible types for
42
+ * entries in that array.
43
+ */
44
+ export declare function matchesObjectShape<MatchThisGeneric extends object>(testThisOne: unknown, compareToThisOne: NoInfer<ObjectWithAtLeastSingleEntryArrays<MatchThisGeneric>>, allowExtraProps?: boolean, shouldLogWhy?: boolean): testThisOne is MatchThisGeneric;
45
+ export declare type ObjectWithAtLeastSingleEntryArrays<BaseObject extends object> = {
46
+ [Prop in keyof BaseObject]: BaseObject[Prop] extends ReadonlyArray<any> ? AtLeastOneEntryArray<BaseObject[Prop]> : BaseObject[Prop] extends object ? ObjectWithAtLeastSingleEntryArrays<BaseObject[Prop]> : BaseObject[Prop];
47
+ };
48
+ /**
49
+ * Asserts that the first input, testThisOne, matches the object shape of the second input,
50
+ * compareToThisOne. Does not compare exact values of properties, only types.
51
+ *
52
+ * To allow the test input, the first input, to have additional keys that the compare input, the
53
+ * second input, does not have, pass in a third argument set to true.
54
+ *
55
+ * This function REQUIRES a generic to be assigned to it: it cannot infer it from the inputs.
56
+ *
57
+ * The compare input, the second input, is required to have at least one entry in every array value
58
+ * that exists. If more array values are present, they will be considered other possible types for
59
+ * entries in that array.
60
+ */
61
+ export declare function assertMatchesObjectShape<MatchThisGeneric extends object = never>(testThisOne: unknown, compareToThisOne: NoInfer<ObjectWithAtLeastSingleEntryArrays<MatchThisGeneric>>, allowExtraProps?: boolean): asserts testThisOne is MatchThisGeneric;
62
+ export declare function typedObjectFromEntries<KeyType extends PropertyKey, ValueType>(entries: ReadonlyArray<Readonly<[KeyType, ValueType]>>): Record<KeyType, ValueType>;
63
+ export {};