@knime/utils 1.12.1 → 2.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/CHANGELOG.md +17 -0
- package/README.md +0 -9
- package/dist/index.js +947 -745
- package/dist/index.js.map +1 -1
- package/dist/test-utils/index.js +41 -38
- package/dist/test-utils/index.js.map +1 -1
- package/package.json +8 -17
- package/audit/README.md +0 -118
- package/audit/bulkAudit.js +0 -671
- package/audit/cli.js +0 -117
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/capitalize.ts","../src/updateDate.ts","../src/updateTime.ts","../src/dateMinMaxCheck.ts","../src/debounce.ts","../src/filters.ts","../src/localTimezone.ts","../src/format.ts","../src/getDeepActiveElement.ts","../src/getWrappedAroundIndex.ts","../src/intervalUtils.ts","../src/numIntegerDigits.ts","../src/promise/createAbortablePromise.ts","../src/promise/createUnwrappedPromise.ts","../src/sleep.ts","../src/promise/retryPromise.ts","../src/sanitization.ts","../src/truncateString.ts","../src/fileExtensions.ts","../src/hotkeys/enums.ts","../src/platform/navigator.ts","../src/hotkeys/format.ts","../src/hotkeys/match.ts","../src/hotkeys/modifiers.ts","../src/hotkeys/index.ts"],"sourcesContent":["/**\n * Uppercases first letter of string\n * @param string to be capitalized first string, e.g. \"workflow\"\n * @return Capitalized String, e.g. \"Workflow\"\n */\nexport const capitalize = (input: string) =>\n input.charAt(0).toUpperCase() + input.substring(1);\n\nconst formats = {\n customFormat: (input: string, delimiter: string) =>\n capitalize(input.replace(delimiter, \" \").toLowerCase()),\n\n kebabFormat: (input: string) => formats.customFormat(input, \"-\"),\n snakeFormat: (input: string) => formats.customFormat(input, \"_\"),\n\n camelPascalCase: (input: string) =>\n capitalize(\n (input.match(/([A-Z]?[^A-Z]*)/g) ?? [])\n .slice(0, -1)\n .join(\" \")\n .toLowerCase(),\n ),\n} as const;\n\ntype CaseFormatterOptions = {\n string: string;\n delimiter?: string;\n format?: keyof typeof formats;\n};\n\nexport const caseFormatter = ({\n string,\n delimiter,\n format,\n}: CaseFormatterOptions) => {\n if (delimiter) {\n return formats.customFormat(string, delimiter);\n }\n\n if (format) {\n return formats[format](string, delimiter ?? \"\");\n }\n\n return capitalize(string);\n};\n","import { getDate, getMonth, getYear, isValid, set } from \"date-fns\";\n/**\n * Updates the date part (year, day and month) of a date object (base)\n * time, offset (timezone) and so on will be left untouched.\n *\n * @param base - Date which will be used (copied) to set day, month and year.\n * @param date - Extract day, month and year from this date object.\n * @returns Copy of base with day, month and year of date.\n */\nexport default (base: Date, date: Date | null) => {\n // ignore falsy dates\n if (date) {\n // allow invalid base and set time to 0\n base = isValid(base) ? base : new Date(Date.UTC(0, 0));\n return set(base, {\n year: getYear(date),\n month: getMonth(date),\n date: getDate(date),\n });\n }\n\n return base;\n};\n","/**\n * Updates the time part (hour, minute, second and millisecond) of a date object (base)\n * date, offset (timezone) and so on will be left untouched.\n *\n * @param base - Date which will be used (copied) to set day, month and year.\n * @param date - Extract hour, minute, second and millisecond from this date object.\n * @returns Copy of base with hour, minute, second and millisecond changed.\n */\nexport default (base: Date, date: Date | null) => {\n const d = new Date(base);\n // ignore falsy dates\n if (date) {\n d.setHours(date.getHours());\n d.setMinutes(date.getMinutes());\n d.setSeconds(date.getSeconds());\n d.setMilliseconds(date.getMilliseconds());\n }\n return d;\n};\n","import { isAfter, isBefore } from \"date-fns\";\n\nimport updateDate from \"./updateDate\";\nimport updateTime from \"./updateTime\";\n\n/**\n * Check if date is before min.\n * @param date\n * @param min\n * @param checkDate - check date part (year, day, month).\n * @param checkTime - check time part (hour, minutes etc.).\n * @returns whether limit is kept or not.\n */\nexport const isBeforeMinDate = (\n date: Date,\n min: Date | null,\n checkDate: boolean,\n checkTime: boolean,\n) => {\n if (min) {\n if (checkTime && checkDate) {\n return isBefore(date, min);\n }\n if (checkTime) {\n // only time is visible so ignore date: use same datre as base\n const base = new Date(0);\n return isBefore(updateTime(base, date), updateTime(base, min));\n }\n if (checkDate) {\n // only date is visible so ignore time: use same time as base\n const base = new Date(0);\n return isBefore(updateDate(base, date), updateDate(base, min));\n }\n }\n return false;\n};\n\n/**\n * Check\n * @param date - date to check.\n * @param max - maximum date.\n * @param checkDate - check date part (year, day, month).\n * @param checkTime - check time part (hour, minutes etc.).\n * @returns whether limit is kept or not.\n */\nexport const isAfterMaxDate = (\n date: Date,\n max: Date | null,\n checkDate: boolean,\n checkTime: boolean,\n) => {\n if (max) {\n if (checkTime && checkDate) {\n return isAfter(date, max);\n }\n if (checkTime) {\n // only time is visible so ignore date: use same datre as base\n const base = new Date(0);\n return isAfter(updateTime(base, date), updateTime(base, max));\n }\n if (checkDate) {\n // use same time base\n const base = new Date(0);\n return isAfter(updateDate(base, date), updateDate(base, max));\n }\n }\n return false;\n};\n","// Use this method to reduce many method calls to a few.\n// It's an 'immediate' implementation, so it will call the callbackindex: number once immediately an then again after the given wait.\n\ntype CallbackFunc<T> = (value: T, index: number) => void;\n\nconst debounce = <T>(callback: CallbackFunc<T>, wait: number) => {\n let timer: ReturnType<typeof setTimeout>;\n let lastCall = 0;\n\n return (...args: Parameters<typeof callback>) => {\n const [value, index] = args;\n clearTimeout(timer);\n const now = Date.now();\n const timeFromLastCall = now - lastCall;\n\n if (timeFromLastCall > wait) {\n lastCall = now;\n callback(value, index);\n } else {\n timer = setTimeout(() => {\n lastCall = now;\n callback(value, index);\n }, wait);\n }\n };\n};\n\nexport default debounce;\n","/**\n * These definitions can be used to filter an array. Each entry should contain a method normalize which can be used to\n * compile any filter settings and a method \"test\" which takes the compiled result, additional settings and the item to\n * be matched/filtered\n * */\ninterface FilterDefinition<SearchTerm, Normalized, Testable> {\n id: string;\n normalize: (\n searchTerm: SearchTerm,\n caseSensitiveSearch: boolean,\n ) => Normalized;\n test: (\n text: Testable,\n normalizedSearchTerm: Normalized,\n caseSensitiveSearch: boolean,\n inverseSearch: boolean,\n ) => boolean;\n}\n\ninterface StringTest {\n test(str: string): boolean;\n}\n\ntype SearchFilterDefinition = FilterDefinition<string, string, string>;\ntype PatternFilterDefinition = FilterDefinition<\n string,\n RegExp | StringTest,\n string\n>;\ntype TypeFilterDefinition = FilterDefinition<\n string[],\n StringTest,\n string | undefined\n>;\n\nconst modeDefinitions = [\n {\n id: \"search\",\n normalize(searchTerm, caseSensitiveSearch) {\n return caseSensitiveSearch ? searchTerm : searchTerm.toLowerCase();\n },\n test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {\n const testText = caseSensitiveSearch ? text : text.toLowerCase();\n const matches = testText.includes(normalizedSearchTerm);\n return inverseSearch ? !matches : matches;\n },\n } satisfies SearchFilterDefinition,\n {\n id: \"wildcard\",\n normalize(searchTerm, caseSensitiveSearch) {\n // Do a regex search, explicitly matching start and end of the search term.\n // All regex special character except from \"* and ?\" (wildcards) are escaped.\n if (searchTerm.length > 0) {\n const escapedSearchTerm = searchTerm.replace(\n /[-[\\]{}()+.,\\\\^$|#\\s]/g,\n \"\\\\$&\",\n );\n const wildcardSearchTerm = escapedSearchTerm\n .replace(/\\*/g, \".*\")\n .replace(/\\?/g, \".?\");\n searchTerm = `^${wildcardSearchTerm}$`;\n } else {\n return { test: () => false };\n }\n try {\n const flags = caseSensitiveSearch ? \"\" : \"i\";\n return new RegExp(searchTerm, flags);\n } catch (_error) {\n // In case of an invalid regular expression, an impossible\n // regex is returned, not matching anything.\n return /$^/;\n }\n },\n test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {\n const matches = normalizedSearchTerm.test(text);\n return inverseSearch ? !matches : matches;\n },\n } satisfies PatternFilterDefinition,\n {\n id: \"regex\",\n normalize(searchTerm, caseSensitiveSearch) {\n try {\n const flags = caseSensitiveSearch ? \"\" : \"i\";\n return new RegExp(`^(${searchTerm})$`, flags);\n } catch (_error) {\n // In case of an invalid regular expression, an impossible\n // regex is returned, not matching anything.\n return /$^/;\n }\n },\n test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {\n const matches = normalizedSearchTerm.test(text);\n return inverseSearch ? !matches : matches;\n },\n } satisfies PatternFilterDefinition,\n {\n id: \"type\",\n normalize(selectedTypes) {\n return { test: (type: string) => selectedTypes.includes(type) };\n },\n test(type, normalizedSearchTerm) {\n if (typeof type === \"undefined\") {\n return false;\n }\n return normalizedSearchTerm.test(type);\n },\n } satisfies TypeFilterDefinition,\n];\n\n// convert [{id: \"key1\", text: \"asdf\"}, ...] to {\"key1\": {id:\"key1\", text: \"asdf\"} ... }\nexport const filters: Record<\n string,\n FilterDefinition<unknown, unknown, unknown>\n> = Object.assign({}, ...modeDefinitions.map((obj) => ({ [obj.id]: obj })));\n","/**\n * Get the users local timezone.\n *\n * @returns current users timezone (browser based) tz db string (e. g. Europe/Berlin).\n */\n// eslint-disable-next-line new-cap\nexport default () => Intl.DateTimeFormat().resolvedOptions().timeZone;\n","import prettyBytes from \"pretty-bytes\";\n\nimport getLocalTimeZone from \"./localTimezone\";\n/**\n * Converts the specified date String to human readable text containing the day, month, and year.\n * Example: '2018-07-31T09:44:31+00:00' => 'Jul 31, 2018'\n *\n * @param dateString String representation of the Date to format\n * @param useTimeZone to set the timeZone where the user is located, and display local date and time\n * @returns human readable date String\n */\nexport const formatDateString = (\n dateString: string | number,\n useTimeZone = false,\n) => {\n const date = new Date(dateString);\n\n // @ts-expect-error Argument of type 'Date' is not assignable to parameter of type 'number'\n if (isNaN(date)) {\n throw Error(\"Invalid Date format\");\n }\n\n const baseDateOptions: Intl.DateTimeFormatOptions = {\n day: \"numeric\",\n month: \"short\",\n year: \"numeric\",\n };\n\n // This only works for the default locale of en-US, as support of other locals in node js might not be available\n // See for example this issue https://github.com/nodejs/node/issues/8500\n const dateOptions: Intl.DateTimeFormatOptions = useTimeZone\n ? { ...baseDateOptions, timeZone: getLocalTimeZone() }\n : baseDateOptions;\n\n return date.toLocaleDateString(\"en-US\", dateOptions);\n};\n\n/**\n * Converts the specified time String to human readable text containing the hour (12-hour) and minute.\n * Example: '2018-07-31T09:44:31+00:00' => '9:44 AM'\n *\n * @param timeString String representation of the Date (including time) to format\n * @param useTimeZone to set the timeZone where the user is located, and display local date and time\n * @returns human readable time String\n */\nexport const formatTimeString = (\n timeString: string | number,\n useTimeZone = false,\n) => {\n const time = new Date(timeString);\n\n // @ts-expect-error Argument of type 'Date' is not assignable to parameter of type 'number'\n if (isNaN(time)) {\n throw Error(\"Invalid Date format\");\n }\n\n // This only works for the default locale of en-US, as support of other locals in node js might not be available\n // See for example this issue https://github.com/nodejs/node/issues/8500\n const baseTimeOptions: Intl.DateTimeFormatOptions = {\n hour: \"numeric\",\n minute: \"2-digit\",\n };\n\n const timeOptions: Intl.DateTimeFormatOptions = useTimeZone\n ? { ...baseTimeOptions, timeZone: getLocalTimeZone() }\n : baseTimeOptions;\n\n return time.toLocaleTimeString(\"en-US\", timeOptions);\n};\n\n/**\n * Converts the specified time String to human readable text containing the date (day, month, year) and time (hour,\n * minute; 12-hour).\n * Example: '2018-07-31T09:44:31+00:00' => 'Jul 31, 2018 9:44 AM'\n *\n * @param dateTimeString String representation of the Date (including time and date) to format\n * @param useTimeZone to set the timeZone where the user is located, and display local date and time\n * @returns human readable date/time String\n */\nexport const formatDateTimeString = (\n dateTimeString: string | number,\n useTimeZone = false,\n) => {\n return `${formatDateString(dateTimeString, useTimeZone)} ${formatTimeString(\n dateTimeString,\n useTimeZone,\n )}`;\n};\n\n/**\n * Converts the specified date and time to the user time zone with option to display (day, month, year) only or with time (hour,\n * minute; 12-hour).\n *\n * @param showTime String representation of the Date to convert and format\n * @param String | number} date String representation of the Date to convert and format\n * @returns human readable date/time String converted to user time zone\n */\nexport const formatLocalDateTimeString = (date: string, showTime: boolean) =>\n showTime ? formatDateTimeString(date, true) : formatDateString(date, true);\n\nexport const formatFileSize = (bytes: number): string => {\n const safeBytes = Number.isFinite(bytes) && bytes >= 0 ? bytes : 0;\n\n return prettyBytes(safeBytes);\n};\n","const getDeepActiveElement = () => {\n let element = document?.activeElement;\n while (element?.shadowRoot) {\n element = element?.shadowRoot?.activeElement;\n }\n return element;\n};\n\nexport default getDeepActiveElement;\n","/**\n * Since (a % b) yields a negative outcome for negative a, we need this method in order\n * to correctly compute wrapped around indices in lists\n * @param {number} index an arbitrary integer\n * @param {number} length a positive integer\n * @returns {number} the non-negative modulo outcome\n */\nexport default (index: number, length: number) =>\n ((index % length) + length) % length;\n","export type Period = {\n negative: boolean;\n years: number;\n months: number;\n weeks: number;\n days: number;\n};\n\nexport type Duration = {\n negative: boolean;\n hours: number;\n minutes: number;\n seconds: number;\n milliseconds: number;\n};\n\ntype AllowedIntervalTypes = \"DATE\" | \"TIME\";\ntype AllowedIntervalTypesOrEither = AllowedIntervalTypes | \"DATE_OR_TIME\";\n\ntype IntervalStringValidationResult =\n | {\n valid: true;\n type: AllowedIntervalTypes;\n negative: boolean;\n }\n | { valid: false };\n\nexport type PeriodOrDuration =\n | {\n interval: Period;\n type: \"DATE\";\n }\n | {\n interval: Duration;\n type: \"TIME\";\n };\n\nconst extractPeriodFromRegexMatch = (\n negative: boolean,\n match: RegExpExecArray,\n): Period => {\n return {\n negative,\n years: parseInt(match[1] ?? \"0\", 10),\n months: parseInt(match[2] ?? \"0\", 10),\n weeks: parseInt(match[3] ?? \"0\", 10),\n days: parseInt(match[4] ?? \"0\", 10),\n };\n};\n\nconst extractDurationFromRegexMatch = (\n negative: boolean,\n match: RegExpExecArray,\n): Duration => {\n // eslint-disable-next-line no-magic-numbers\n const milliseconds = parseInt(match[4]?.padEnd(3, \"0\") ?? \"0\", 10);\n\n return {\n negative,\n hours: parseInt(match[1] ?? \"0\", 10),\n minutes: parseInt(match[2] ?? \"0\", 10),\n seconds: parseInt(match[3] ?? \"0\", 10),\n milliseconds,\n };\n};\n\nexport const isZero = (interval: PeriodOrDuration): boolean => {\n if (interval.type === \"DATE\") {\n return (\n interval.interval.years === 0 &&\n interval.interval.months === 0 &&\n interval.interval.weeks === 0 &&\n interval.interval.days === 0\n );\n } else {\n return (\n interval.interval.hours === 0 &&\n interval.interval.minutes === 0 &&\n interval.interval.seconds === 0 &&\n interval.interval.milliseconds === 0\n );\n }\n};\n\n/**\n * Take an interval object and convert it to an ISO duration or period string. All parts of the\n * relevant part of the Interval object are included in the output, even if they are zero.\n *\n * Technically the ISO standard allows to mix period and duration parts, but we don't support that\n * here because it's incredibly hard to deal with all the edge cases. Maybe in a future ticket.\n *\n * The output here is allowed to be negative, in which case the minus sign is prepended to the\n * output.\n *\n * @param toFormat The PeriodOrDuration object to format\n */\nexport const formatIntervalToISOIntervalString = (\n toFormat: PeriodOrDuration,\n): string => {\n let output = \"P\";\n\n if (toFormat.type === \"DATE\") {\n output += `${toFormat.interval.years}Y${toFormat.interval.months}M${toFormat.interval.weeks}W${toFormat.interval.days}D`;\n } else {\n output += `T${toFormat.interval.hours}H${toFormat.interval.minutes}M${toFormat.interval.seconds}.${toFormat.interval.milliseconds\n .toString()\n // eslint-disable-next-line no-magic-numbers\n .padStart(3, \"0\")}S`;\n }\n\n if (toFormat.interval.negative) {\n output = `-${output}`;\n }\n return output;\n};\n\n/**\n * Take an interval object and convert it to a human readable string. Only non-zero parts are\n * included in the output (unless all parts are 0).\n *\n * The output here is allowed to be negative, in which case the minus sign is prepended to the\n * output and we wrap the whole thing in brackets e.g. -(1 year 2 days).\n *\n * @param toFormat The PeriodOrDuration object to format\n */\nexport const formatIntervalToHumanReadableIntervalString = (\n toFormat: PeriodOrDuration,\n): string => {\n const formatPart = (value: number, unit: string): string => {\n if (value === 0) {\n return \"\";\n } else if (value === 1) {\n return `${value} ${unit} `;\n } else {\n return `${value} ${unit}s `;\n }\n };\n\n let output = \"\";\n\n if (toFormat.type === \"DATE\") {\n if (isZero(toFormat)) {\n return \"0 days\";\n }\n\n output += formatPart(toFormat.interval.years, \"year\");\n output += formatPart(toFormat.interval.months, \"month\");\n output += formatPart(toFormat.interval.weeks, \"week\");\n output += formatPart(toFormat.interval.days, \"day\");\n } else {\n if (isZero(toFormat)) {\n return \"0 seconds\";\n }\n\n output += formatPart(toFormat.interval.hours, \"hour\");\n output += formatPart(toFormat.interval.minutes, \"minute\");\n\n const milliSecondsZero = toFormat.interval.milliseconds === 0;\n if (toFormat.interval.seconds !== 0 || !milliSecondsZero) {\n if (milliSecondsZero) {\n output += formatPart(toFormat.interval.seconds, \"second\");\n } else {\n output += `${toFormat.interval.seconds}.${toFormat.interval.milliseconds.toString().padStart(3, \"0\")} seconds `; // eslint-disable-line no-magic-numbers\n }\n }\n }\n\n if (toFormat.interval.negative) {\n output = `-(${output.trim()})`;\n }\n\n return output.trim();\n};\n\nconst yearsPart = \"(\\\\d+)\\\\s*y(?:ears?)?\";\nconst monthsPart = \"(\\\\d+)\\\\s*m(?:o(?:nths?)?)?\";\nconst weeksPart = \"(\\\\d+)\\\\s*w(?:eeks?)?\";\nconst daysPart = \"(\\\\d+)\\\\s*d(?:ays?)?\";\nconst hoursPart = \"(\\\\d+)\\\\s*h(?:ours?)?\";\nconst minutesPart = \"(\\\\d+)\\\\s*m(?:in(?:s|utes?)?)?\";\nconst secondsPart = \"(\\\\d+)(?:[,.](\\\\d{1,3}))?\\\\s*s(?:ec(?:s|onds?)?)?\";\n\n/**\n * Matches a human readable period string, e.g. \"1y 2mo 3weeks 4day\" (each part is optional)\n */\nconst humanReadablePeriodRegex = new RegExp(\n `^(?:${yearsPart})?\\\\s*(?:${monthsPart})?\\\\s*(?:${weeksPart})?\\\\s*(?:${daysPart})?\\\\s*$`,\n \"i\",\n);\n\n/**\n * Matches a human readable duration string, e.g. \"1h 2m 3.456s\" (each part is optional)\n */\nconst humanReadableDurationRegex = new RegExp(\n `^(?:${hoursPart})?\\\\s*(?:${minutesPart})?\\\\s*(?:${secondsPart})?$`,\n \"i\",\n);\n\n/**\n * Matches a negative human readable period string, e.g. \"-(1y 2mo 3weeks 4day)\" (each part is optional)\n */\nconst negativeHumanReadablePeriodRegex = new RegExp(\n `^\\\\s*-\\\\s*\\\\(\\\\s*${humanReadablePeriodRegex.source.replace(/[$^]/g, \"\")}\\\\s*\\\\)\\\\s*$`,\n \"i\",\n);\n\n/**\n * Matches a negative human readable period string with one field like \"-1y\" or \"-1w\"\n */\nconst negativeHumanReadablePeriodRegexWithSingleField = new RegExp(\n `^\\\\s*-\\\\s*(?:\\\\s*${yearsPart}|${monthsPart}|${weeksPart}|${daysPart})\\\\s*$`,\n \"i\",\n);\n\n/**\n * Matches a negative human readable duration string, e.g. \"-(1h 2m 3.456s)\" (each part is optional)\n */\nconst negativeHumanReadableDurationRegex = new RegExp(\n `^\\\\s*-\\\\s*\\\\(\\\\s*${humanReadableDurationRegex.source.replace(/[$^]/g, \"\")}\\\\s*\\\\)\\\\s*$`,\n \"i\",\n);\n\n/**\n * Matches a negative human readable duration string with one field like \"-1h\" or \"-1.5s\"\n */\nconst negativeHumanReadableDurationRegexWithSingleField = new RegExp(\n `^\\\\s*-\\\\s*(?:\\\\s*${hoursPart}|${minutesPart}|${secondsPart})\\\\s*$`,\n \"i\",\n);\n\n/**\n * Try to parse a human readable interval string into an Interval object. Any parts not specified\n * are assumed to be zero. Note that the string must be either a period or a duration, not a mix of\n * both. So for example, \"1y 2mo 3weeks 4day\" is fine, as is \"1h 2m 3.456s\". However, \"1y 2mo 1sec\"\n * is not, since it's a mix of both.\n *\n * Negative intervals are allowed, although if multiple fields are provided the string must include\n * brackets, so \"-(1y 2mo)\" is also valid, as is \"-5 seconds\".\n *\n * The string is required to have at least some content, any string that is blank will throw an error.\n *\n * @param intervalString The human readable time string\n */\nexport const parseHumanReadableIntervalString = (\n intervalString: string,\n): PeriodOrDuration => {\n intervalString = intervalString?.trim();\n\n if (!intervalString) {\n throw new Error(\"Empty interval string\");\n }\n\n const matchPositivePeriod = humanReadablePeriodRegex.exec(intervalString);\n const matchNegativePeriod =\n negativeHumanReadablePeriodRegex.exec(intervalString) ??\n negativeHumanReadablePeriodRegexWithSingleField.exec(intervalString);\n const matchPositiveDuration = humanReadableDurationRegex.exec(intervalString);\n const matchNegativeDuration =\n negativeHumanReadableDurationRegex.exec(intervalString) ??\n negativeHumanReadableDurationRegexWithSingleField.exec(intervalString);\n\n const matchPeriod = matchPositivePeriod ?? matchNegativePeriod;\n const matchDuration = matchPositiveDuration ?? matchNegativeDuration;\n const negative = (matchNegativePeriod ?? matchNegativeDuration) !== null;\n\n // I think this will happen only for the string \"1M\" or similar\n if (matchDuration && matchPeriod) {\n throw new Error(\"Ambiguous time format\");\n }\n\n if (matchPeriod) {\n return {\n type: \"DATE\",\n interval: extractPeriodFromRegexMatch(negative, matchPeriod),\n };\n } else if (matchDuration) {\n return {\n type: \"TIME\",\n interval: extractDurationFromRegexMatch(negative, matchDuration),\n };\n } else {\n throw new Error(`Invalid human readable time: ${intervalString}`);\n }\n};\n\n/**\n * Check if the given string can be understood as a human readable duration or period string. The\n * type parameter specifies whether the string should be a date, time, or either.\n *\n * @param time the string to check\n * @param expectedType the type of the string - either \"DATE\", \"TIME\", or \"ANY\"\n */\nexport const isValidHumanReadableIntervalString = (\n time: string,\n expectedType: AllowedIntervalTypesOrEither,\n): IntervalStringValidationResult => {\n try {\n const validationResult = parseHumanReadableIntervalString(time);\n const actualType = validationResult.type;\n const negative = validationResult.interval.negative;\n\n if (actualType === expectedType || expectedType === \"DATE_OR_TIME\") {\n return {\n valid: true,\n type: actualType,\n negative,\n };\n } else {\n return { valid: false };\n }\n } catch (_e) {\n return { valid: false };\n }\n};\n\n/**\n * Convert an ISO duration OR period string to an Interval object. So for example,\n * \"P1Y2M3W4D\" is fine, as is \"PT1H2M3.456S\". However, \"P1Y2M3W4D1H2M3.456S\" is not, since\n * it's a mix of both. We're more forgiving than the ISO standard, so we allow for missing parts.\n * Also, the string is allowed to be negative, so \"-P1Y2M3W4D\" is also valid.\n *\n * The string is required to have at least some content, so the strings \"\", \"P\", and \"PT\" are\n * considered invalid (also if they start with a -).\n *\n * @param isoString The ISO duration or period string.\n */\nexport const parseISOIntervalString = (isoString: string): PeriodOrDuration => {\n isoString = isoString?.trim();\n\n if ([\"\", \"P\", \"PT\", \"-\", \"-P\", \"-PT\"].includes(isoString)) {\n throw new Error(\"Empty ISO duration\");\n }\n\n const periodRegex = /^-?P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)W)?(?:(\\d+)D)?$/;\n const durationRegex =\n /^-?PT(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)(?:[,.](\\d{1,3}))?S)?$/;\n\n const matchPeriod = periodRegex.exec(isoString);\n const matchDuration = durationRegex.exec(isoString);\n\n if (matchPeriod) {\n return {\n type: \"DATE\",\n interval: extractPeriodFromRegexMatch(\n isoString.startsWith(\"-\"),\n matchPeriod,\n ),\n };\n } else if (matchDuration) {\n return {\n type: \"TIME\",\n interval: extractDurationFromRegexMatch(\n isoString.startsWith(\"-\"),\n matchDuration,\n ),\n };\n } else {\n throw new Error(`Invalid ISO duration: ${isoString}`);\n }\n};\n\n/**\n * Check if the given string is a valid duration or period ISO string. The type parameter\n * specifies whether the string should be a date, time, or either.\n *\n * @param isoString the string to check\n * @param type the type of the string - either \"DATE\", \"TIME\", or \"ANY\"\n */\nexport const isValidISOIntervalString = (\n isoString: string,\n type: AllowedIntervalTypesOrEither,\n): IntervalStringValidationResult => {\n try {\n const validationResult = parseISOIntervalString(isoString);\n const actualType = validationResult.type;\n const negative = validationResult.interval.negative;\n\n if (actualType === type || type === \"DATE_OR_TIME\") {\n return {\n valid: true,\n type: actualType,\n negative,\n };\n } else {\n return { valid: false };\n }\n } catch (_e) {\n return { valid: false };\n }\n};\n\n/**\n * Try to convert an interval string to an Interval object. The string can be either an ISO\n * duration/period string or a human readable string. If the string is not valid, an error is\n * thrown.\n *\n * @param time the time string, either ISO or human readable\n */\nexport const parseGenericIntervalString = (time: string): PeriodOrDuration => {\n const validISO = isValidISOIntervalString(time, \"DATE_OR_TIME\");\n const validHumanReadable = isValidHumanReadableIntervalString(\n time,\n \"DATE_OR_TIME\",\n );\n if (validISO.valid) {\n return parseISOIntervalString(time);\n } else if (validHumanReadable.valid) {\n return parseHumanReadableIntervalString(time);\n } else {\n throw new Error(`Invalid interval string: ${time}`);\n }\n};\n\n/**\n * Check if the given string is a valid interval string, either human readable or ISO. The type parameter\n * specifies whether the string should be a period, duration, or either.\n *\n * @param time the time string to check\n * @param type the type of the string - either \"DATE\", \"TIME\", or \"ANY\"\n */\nexport const isValidIntervalString = (\n time: string,\n type: AllowedIntervalTypesOrEither,\n): IntervalStringValidationResult => {\n const validISO = isValidISOIntervalString(time, type);\n const validHumanReadable = isValidHumanReadableIntervalString(time, type);\n if (validISO.valid) {\n return validISO;\n } else if (validHumanReadable.valid) {\n return validHumanReadable;\n } else {\n return { valid: false };\n }\n};\n","/**\n * Count the number of integer digits for a given number.\n *\n * @param input number.\n * @returns number of integer digits x has. 1234 = 4 but 1234.44 is also 4.\n */\nexport default (input: number) =>\n Math.max(Math.floor(Math.log10(Math.abs(input))), 0) + 1;\n","export class AbortError extends Error {}\n\n/**\n * Helper to create an abortable promise. Returns an AbortController and a Function\n * that you can pass your async handler to. Whenever the AbortController signal is\n * aborted then the async handler's promise will reject with an AbortError\n *\n * Example:\n * ```\n * import { abortUtils } from \"@knime/utils\"\n * const myFetchCall = async (params...) => {...};\n *\n * try {\n * const { runAbortablePromise, abortController } = createAbortablePromise(() =>\n * myFetchCall(params...),\n * );\n * } catch (e) {\n * if (e instanceof abortUtils.AbortError) {\n * console.info('ignore due to abort');\n * return;\n * }\n * }\n *\n * // somewhere else (while request is in-flight)\n * abortController.abort(new abortUtils.AbortError('reason here'))\n * ```\n */\nexport const createAbortablePromise = () => {\n const abortController: AbortController = new AbortController();\n\n const runAbortablePromise = <T = unknown>(request: () => Promise<T>) => {\n return new Promise<T>((resolve, reject) => {\n // abort logic\n const abortListener = ({ target }: Event) => {\n abortController.signal.removeEventListener(\"abort\", abortListener);\n const reason = (target as AbortSignal).reason;\n reject(reason instanceof AbortError ? reason : new AbortError(reason));\n };\n\n // the actual call\n request()\n .then(resolve)\n .catch((error) => {\n if (error instanceof AbortError) {\n return;\n }\n\n reject(error);\n });\n\n abortController.signal.addEventListener(\"abort\", abortListener);\n });\n };\n\n return { abortController, runAbortablePromise };\n};\n","export type UnwrappedPromise<T = unknown> = {\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: unknown) => void;\n promise: Promise<T>;\n};\n\nexport const createUnwrappedPromise = <T>(): UnwrappedPromise<T> => {\n let resolve: (value: T | PromiseLike<T>) => void = () => {};\n let reject: (reason?: unknown) => void = () => {};\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { resolve, reject, promise };\n};\n","/**\n * Returns promise that resolves after ms.\n */\nexport default function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import sleep from \"../sleep\";\n\nexport const DEFAULT_RETRY_DELAY_MS = 0;\nexport const DEFAULT_RETRY_COUNT = 5;\n\n/**\n * Helper to add retry capability to an async function\n * @param fn async function\n * @param retryCount max number of retries. defaults to 5\n * @param retryDelayMS delay in-between retries in millisecs. defaults to 0\n * @param excludeError predicate fn to exclude specific errors from causing a retry\n */\nexport async function retryPromise<T>({\n fn,\n retryCount = DEFAULT_RETRY_COUNT,\n retryDelayMS = DEFAULT_RETRY_DELAY_MS,\n excludeError,\n}: {\n fn: () => Promise<T>;\n retryCount?: number;\n retryDelayMS?: number;\n excludeError?: (error: Error) => boolean;\n}) {\n try {\n return await fn();\n } catch (error) {\n if (excludeError?.(error as Error)) {\n throw error;\n }\n\n if (retryCount > 0) {\n await sleep(retryDelayMS);\n\n // eslint-disable-next-line no-return-await\n return await retryPromise({\n fn,\n retryCount: retryCount - 1,\n retryDelayMS,\n excludeError,\n });\n }\n\n throw error;\n }\n}\n","import DomPurify from \"dompurify\";\n\nconst ALLOWED_TAGS = [\n \"p\",\n \"div\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"ul\",\n \"ol\",\n \"li\",\n \"blockquote\",\n \"b\",\n \"i\",\n \"s\",\n \"u\",\n \"sup\",\n \"sub\",\n \"ins\",\n \"del\",\n \"strong\",\n \"strike\",\n \"tt\",\n \"code\",\n \"big\",\n \"small\",\n \"br\",\n \"span\",\n \"em\",\n];\n\n/**\n * Sanitizes Raw HTML and only allow specific tags to be used, as per OWASP standards.\n * @param rawHTML\n * @param options.allowStyleAttribute - Allow the style attribute on elements\n * @param options.allowHyperlinks - Allow anchor tags with href attribute\n * @returns sanitized html\n */\nconst sanitizeHTML = (\n rawHTML: string,\n options: { allowStyleAttribute?: boolean; allowHyperlinks?: boolean } = {\n allowStyleAttribute: false,\n allowHyperlinks: false,\n },\n) => {\n const { allowStyleAttribute, allowHyperlinks } = options;\n const ALLOWED_ATTR = [\n ...(allowStyleAttribute ? [\"style\"] : []),\n ...(allowHyperlinks ? [\"href\"] : []),\n ];\n const allowedTags = allowHyperlinks ? [...ALLOWED_TAGS, \"a\"] : ALLOWED_TAGS;\n\n return DomPurify.sanitize(rawHTML, {\n ALLOWED_TAGS: allowedTags,\n ALLOWED_ATTR,\n });\n};\n\n/**\n * Removes any HTML tag from the input string. Keeps HTML entities\n * (e.g because these can be considered plain text)\n * @param rawHTML\n * @returns plain text\n */\nconst stripHTML = (rawHTML: string) => {\n return DomPurify.sanitize(rawHTML, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] });\n};\n\nexport const sanitization = { sanitizeHTML, stripHTML };\n","const defaultMaxLength = 160;\n\n// truncates a string to a given max length\nexport default (string = \"\", maxLength = defaultMaxLength) => {\n const dots = string.length > maxLength ? \"…\" : \"\";\n return `${string.substring(0, maxLength - 1)}${dots}`;\n};\n","/**\n * Gets the file extension\n * @param nameOrPath can take a full file name (e.g \"file.txt\") or a path to a file\n * (e.g \"file://path/to/file.txt\" OR \"/path/to/file.txt\")\n * @returns just the file extension (e.g \"txt\")\n */\nexport const getFileExtension = (nameOrPath: string): string => {\n const basename = nameOrPath.split(/[\\\\/]/).pop() ?? \"\";\n\n const parts = basename.split(\".\");\n\n if (basename === \"\" || parts.length === 1) {\n return \"\";\n }\n\n return parts.at(-1) ?? \"\";\n};\n\n/**\n * Metadata for .knar files, which corresponds to exported KNIME Workflow Groups\n * or Components\n */\nconst KNAR = Object.freeze({\n extension: \"knar\",\n mimeType: \"application/vnd.knime.workflow-group+zip\",\n matches(file: File) {\n const extension = getFileExtension(file.name);\n return extension === this.extension;\n },\n});\n\n/**\n * Metadata for .knwf files, which corresponds to exported KNIME Workflows\n */\nconst KNWF = Object.freeze({\n extension: \"knwf\",\n mimeType: \"application/vnd.knime.workflow+zip\",\n matches(file: File) {\n const extension = getFileExtension(file.name);\n return extension === this.extension;\n },\n /**\n * Gets the name of a .knwf file without the extension. If the file is not\n * matched as a .knwf file then this function will return the default value,\n * which is empty string (\"\") if param is not provided\n */\n getNameOrDefault(file: File, defaultValue = \"\"): string {\n if (!this.matches(file)) {\n return defaultValue;\n }\n\n return file.name.replace(`.${this.extension}`, \"\");\n },\n});\n\nexport const knimeFileFormats = { KNAR, KNWF };\n\n/**\n * Gets the mime type from a given file. Defaults to `application/octet-stream`\n * if mimeType cannot be detected\n * @param file File\n * @returns mimeType\n */\nexport const getFileMimeType = (file: File): string => {\n const DEFAULT_MIMETYPE = \"application/octet-stream\";\n\n const extension = getFileExtension(file.name);\n\n if (!extension) {\n return DEFAULT_MIMETYPE;\n }\n\n if (KNWF.matches(file)) {\n return KNWF.mimeType;\n }\n\n if (KNAR.matches(file)) {\n return KNAR.mimeType;\n }\n\n // file has extension but unrecognizable mime type\n if (!file.type) {\n return DEFAULT_MIMETYPE;\n }\n\n return file.type;\n};\n","/**\n * Platforms that influence how modifier keys are rendered. macOS substitutes\n * dedicated glyphs (`⌘`, `⌥`, `⇧`, …), every other platform uses the textual\n * rendering (`Ctrl`, `Alt`, `Shift`, …).\n */\nexport const hotkeyPlatform = {\n MAC_OS: \"macOS\",\n OTHER: \"other\",\n} as const;\n\nexport const hotkeyPlatforms = Object.values(hotkeyPlatform);\n","/**\n *\n * @returns true if the platform of the user is Mac\n */\nexport const isMac = (): boolean =>\n navigator?.userAgent?.toLowerCase()?.includes(\"mac\");\n\n/**\n *\n * @returns true if the platform of the user is Windows\n */\nexport const isWindows = (): boolean =>\n navigator?.userAgent?.toLowerCase()?.includes(\"windows\");\n","import { isMac } from \"../platform/navigator\";\n\nimport { hotkeyPlatform } from \"./enums\";\nimport type { Hotkey, HotkeyPlatform } from \"./types\";\n\nconst globalKeyMap = {\n ArrowUp: \"↑\",\n ArrowDown: \"↓\",\n ArrowLeft: \"←\",\n ArrowRight: \"→\",\n Enter: \"↵\",\n \" \": \"Space\", // we use event.key and there space is an actual space not the code \"Space\"\n CtrlOrCmd: \"Ctrl\",\n} as const;\n\nconst MacOSkeyMap = {\n Shift: \"⇧\",\n Delete: \"⌫\",\n CtrlOrCmd: \"⌘\",\n Ctrl: \"⌃\",\n Alt: \"⌥\",\n Enter: \"↩\",\n} as const;\n\ntype KeyFormatMap = typeof MacOSkeyMap | typeof globalKeyMap;\n\n/**\n * Returns a string representation of a single hotkey. Replaces some special key names with symbols.\n *\n * By default the platform is auto-detected from the user agent via `isMac()`.\n * Pass `platform` to force a specific platform's glyphs — useful for SSR,\n * tests, or rendering multiple platforms on the same page.\n */\nexport const formatHotkey = (\n hotkey: Hotkey,\n platform?: HotkeyPlatform,\n): string => {\n /**\n * Returns the symbol corresponding to the `key` based on the given\n * `formatMap`. Otherwise, if not found, returns the same `key` value given\n */\n const mapSymbols = (formatMap: KeyFormatMap) => (key: Hotkey) =>\n formatMap[key as keyof KeyFormatMap] ?? key;\n\n /**\n * Pipe function implementation. Receives a list of functions to execute in order\n * and will pipe the parameter passed at the end to each function returning the final output\n */\n const pipe = <T extends () => string>(\n ...fns: Array<(...args: Hotkey[]) => ReturnType<T>>\n ) =>\n fns.reduce(\n (f, g) => (arg) => g(f(arg)),\n (arg: Hotkey) => arg as ReturnType<T>,\n );\n\n const macKeyFormatter = pipe(\n mapSymbols(MacOSkeyMap),\n mapSymbols(globalKeyMap),\n );\n\n const generalKeyFormatter = mapSymbols(globalKeyMap);\n\n const useMacFormatter =\n platform === undefined ? isMac() : platform === hotkeyPlatform.MAC_OS;\n return useMacFormatter\n ? macKeyFormatter(hotkey)\n : generalKeyFormatter(hotkey);\n};\n\nexport const getDefaultSeparator = () => (isMac() ? \" \" : \"+\");\n\n/**\n * Returns a string representation of a list of hotkeys. Replaces some special key names with symbols\n */\nexport const formatHotkeys = (\n hotkeys: Array<Hotkey>,\n getSeparator = getDefaultSeparator,\n) => hotkeys.map((hotkey) => formatHotkey(hotkey)).join(getSeparator());\n\n/**\n * Appends a formatted hotkey shortcut to the given string. Useful for tooltips\n */\nexport const textWithHotkeys = (text: string, hotkeys: Array<Hotkey>) => {\n return `${text} – ${formatHotkeys(hotkeys)}`;\n};\n","import * as navigatorUtils from \"../platform/navigator\";\n\nimport type { Hotkey } from \"./types\";\n\n/**\n * Checks whether a pressed `Digit` key falls within a numeric hotkey range such\n * as `1-9`.\n * @param keyCode - The `KeyboardEvent.code` to check (e.g. `Digit5`).\n * @param hotkey - The hotkey token, expected to be a single-digit range like `1-9`.\n * @returns True if the pressed digit lies within the inclusive range.\n */\nconst isDigitKeyInRange = (keyCode: string, hotkey: Hotkey): boolean => {\n // Digit keys exist from 0 to 9, so valid ranges always have length 3\n const digitRangeLength = 3;\n if (hotkey.length !== digitRangeLength || !keyCode?.startsWith(\"Digit\")) {\n return false;\n }\n\n const keyNumber = Number(keyCode.slice(\"Digit\".length));\n const [lower, upper] = hotkey.split(\"-\");\n\n return (\n Boolean(lower) &&\n Boolean(upper) &&\n Number.parseInt(lower, 10) <= keyNumber &&\n keyNumber <= Number.parseInt(upper, 10)\n );\n};\n\n/**\n * Checks whether a keyboard event matches a hotkey definition. The last token is\n * treated as the character; any preceding tokens are modifiers. The special\n * `CtrlOrCmd` modifier resolves to the platform's primary modifier (Meta/`⌘` on\n * macOS, Ctrl elsewhere).\n * @param event - The keyboard event to check.\n * @param hotkeys - The ordered hotkey tokens (modifiers followed by the character).\n * @returns True if the event matches the given hotkey, otherwise false.\n */\nexport const match = (event: KeyboardEvent, hotkeys: Hotkey[]): boolean => {\n const { key, code, metaKey, ctrlKey, shiftKey, altKey } = event;\n\n const modifiers = hotkeys.slice(); // copy so pop() doesn't mutate the caller's array\n const character = modifiers.pop() ?? \"\";\n\n // our special CtrlOrCmd has to match \"Command ⌘\" (metaKey) on Mac, and Ctrl-Key on other systems\n const ctrlOrMeta = navigatorUtils.isMac() ? \"Meta\" : \"Ctrl\";\n const platformModifiers = new Set(\n modifiers.map((modifier) =>\n modifier === \"CtrlOrCmd\" ? ctrlOrMeta : modifier,\n ),\n );\n\n const metaMatches = Boolean(metaKey) === platformModifiers.has(\"Meta\");\n const ctrlMatches = Boolean(ctrlKey) === platformModifiers.has(\"Ctrl\");\n const shiftMatches = Boolean(shiftKey) === platformModifiers.has(\"Shift\");\n const altMatches = Boolean(altKey) === platformModifiers.has(\"Alt\");\n\n const keysMatch =\n // keys are matched case insensitively\n key.toUpperCase() === character.toUpperCase() ||\n (character.includes(\"-\") && isDigitKeyInRange(code, character)) ||\n // on mac 'backspace' can be used instead of delete\n (navigatorUtils.isMac() && character === \"Delete\" && key === \"Backspace\");\n\n return metaMatches && ctrlMatches && shiftMatches && altMatches && keysMatch;\n};\n","import * as navigatorUtils from \"../platform/navigator\";\n\n/**\n * Checks if any modifier key (Ctrl, Meta, Alt, or Shift) is pressed.\n * @param event - The keyboard event to check.\n * @returns True if a modifier key is pressed, otherwise false.\n */\nexport const isModifierKeyPressed = (event: KeyboardEvent): boolean => {\n return event.ctrlKey || event.metaKey || event.altKey || event.shiftKey;\n};\n\n/**\n * Checks if a specific key (or keys) were pressed without any modifier keys.\n * @param event - The keyboard event to check.\n * @param keys - The key or keys to check for.\n * @returns True if the specified key(s) were pressed without modifiers, otherwise false.\n */\nexport const isKeyWithoutModifiers = (\n event: KeyboardEvent,\n keys: string | string[],\n): boolean => {\n const keyList = Array.isArray(keys) ? keys : [keys];\n return keyList.includes(event.key) && !isModifierKeyPressed(event);\n};\n\n/**\n * Returns the name of the primary modifier key for the current platform.\n */\nexport const getMetaOrCtrlKey = (): \"ctrlKey\" | \"metaKey\" => {\n return navigatorUtils.isMac() ? \"metaKey\" : \"ctrlKey\";\n};\n","import { hotkeyPlatform } from \"./enums\";\nimport {\n formatHotkey,\n formatHotkeys,\n getDefaultSeparator,\n textWithHotkeys,\n} from \"./format\";\nimport { match } from \"./match\";\n\n/**\n * Grouped keyboard-shortcut helpers, exposed as a single namespace for\n * ergonomic access (e.g. `hotkeys.formatHotkey`).\n */\nexport const hotkeys = {\n formatHotkeys,\n formatHotkey,\n getDefaultSeparator,\n hotkeyPlatform,\n textWithHotkeys,\n match,\n};\n\nexport { match };\nexport {\n getMetaOrCtrlKey,\n isKeyWithoutModifiers,\n isModifierKeyPressed,\n} from \"./modifiers\";\nexport type { Hotkey, HotkeyPlatform, KnownHotkey } from \"./types\";\n"],"names":["navigatorUtils.isMac"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/capitalize.ts","../src/updateDate.ts","../src/updateTime.ts","../src/dateMinMaxCheck.ts","../src/debounce.ts","../src/filters.ts","../src/localTimezone.ts","../src/format.ts","../src/getDeepActiveElement.ts","../src/getWrappedAroundIndex.ts","../src/intervalUtils.ts","../src/numIntegerDigits.ts","../src/promise/createAbortablePromise.ts","../src/promise/createUnwrappedPromise.ts","../src/sleep.ts","../src/promise/retryPromise.ts","../src/promise/index.ts","../src/sanitization.ts","../src/truncateString.ts","../src/fileExtensions.ts","../src/hotkeys/enums.ts","../src/platform/navigator.ts","../src/hotkeys/format.ts","../src/hotkeys/match.ts","../src/hotkeys/modifiers.ts","../src/hotkeys/index.ts"],"sourcesContent":["/**\n * Uppercases first letter of string\n * @param string to be capitalized first string, e.g. \"workflow\"\n * @return Capitalized String, e.g. \"Workflow\"\n */\nexport const capitalize = (input: string) =>\n input.charAt(0).toUpperCase() + input.substring(1);\n\nconst formats = {\n customFormat: (input: string, delimiter: string) =>\n capitalize(input.replace(delimiter, \" \").toLowerCase()),\n\n kebabFormat: (input: string) => formats.customFormat(input, \"-\"),\n snakeFormat: (input: string) => formats.customFormat(input, \"_\"),\n\n camelPascalCase: (input: string) =>\n capitalize(\n (input.match(/([A-Z]?[^A-Z]*)/g) ?? [])\n .slice(0, -1)\n .join(\" \")\n .toLowerCase(),\n ),\n} as const;\n\ntype CaseFormatterOptions = {\n string: string;\n delimiter?: string;\n format?: keyof typeof formats;\n};\n\nexport const caseFormatter = ({\n string,\n delimiter,\n format,\n}: CaseFormatterOptions) => {\n if (delimiter) {\n return formats.customFormat(string, delimiter);\n }\n\n if (format) {\n return formats[format](string, delimiter ?? \"\");\n }\n\n return capitalize(string);\n};\n","import { getDate, getMonth, getYear, isValid, set } from \"date-fns\";\n/**\n * Updates the date part (year, day and month) of a date object (base)\n * time, offset (timezone) and so on will be left untouched.\n *\n * @param base - Date which will be used (copied) to set day, month and year.\n * @param date - Extract day, month and year from this date object.\n * @returns Copy of base with day, month and year of date.\n */\nexport default (base: Date, date: Date | null) => {\n // ignore falsy dates\n if (date) {\n // allow invalid base and set time to 0\n base = isValid(base) ? base : new Date(Date.UTC(0, 0));\n return set(base, {\n year: getYear(date),\n month: getMonth(date),\n date: getDate(date),\n });\n }\n\n return base;\n};\n","/**\n * Updates the time part (hour, minute, second and millisecond) of a date object (base)\n * date, offset (timezone) and so on will be left untouched.\n *\n * @param base - Date which will be used (copied) to set day, month and year.\n * @param date - Extract hour, minute, second and millisecond from this date object.\n * @returns Copy of base with hour, minute, second and millisecond changed.\n */\nexport default (base: Date, date: Date | null) => {\n const d = new Date(base);\n // ignore falsy dates\n if (date) {\n d.setHours(date.getHours());\n d.setMinutes(date.getMinutes());\n d.setSeconds(date.getSeconds());\n d.setMilliseconds(date.getMilliseconds());\n }\n return d;\n};\n","import { isAfter, isBefore } from \"date-fns\";\n\nimport updateDate from \"./updateDate\";\nimport updateTime from \"./updateTime\";\n\n/**\n * Check if date is before min.\n * @param date\n * @param min\n * @param checkDate - check date part (year, day, month).\n * @param checkTime - check time part (hour, minutes etc.).\n * @returns whether limit is kept or not.\n */\nexport const isBeforeMinDate = (\n date: Date,\n min: Date | null,\n checkDate: boolean,\n checkTime: boolean,\n) => {\n if (min) {\n if (checkTime && checkDate) {\n return isBefore(date, min);\n }\n if (checkTime) {\n // only time is visible so ignore date: use same datre as base\n const base = new Date(0);\n return isBefore(updateTime(base, date), updateTime(base, min));\n }\n if (checkDate) {\n // only date is visible so ignore time: use same time as base\n const base = new Date(0);\n return isBefore(updateDate(base, date), updateDate(base, min));\n }\n }\n return false;\n};\n\n/**\n * Check\n * @param date - date to check.\n * @param max - maximum date.\n * @param checkDate - check date part (year, day, month).\n * @param checkTime - check time part (hour, minutes etc.).\n * @returns whether limit is kept or not.\n */\nexport const isAfterMaxDate = (\n date: Date,\n max: Date | null,\n checkDate: boolean,\n checkTime: boolean,\n) => {\n if (max) {\n if (checkTime && checkDate) {\n return isAfter(date, max);\n }\n if (checkTime) {\n // only time is visible so ignore date: use same datre as base\n const base = new Date(0);\n return isAfter(updateTime(base, date), updateTime(base, max));\n }\n if (checkDate) {\n // use same time base\n const base = new Date(0);\n return isAfter(updateDate(base, date), updateDate(base, max));\n }\n }\n return false;\n};\n","// Use this method to reduce many method calls to a few.\n// It's an 'immediate' implementation, so it will call the callbackindex: number once immediately an then again after the given wait.\n\ntype CallbackFunc<T> = (value: T, index: number) => void;\n\nconst debounce = <T>(callback: CallbackFunc<T>, wait: number) => {\n let timer: ReturnType<typeof setTimeout>;\n let lastCall = 0;\n\n return (...args: Parameters<typeof callback>) => {\n const [value, index] = args;\n clearTimeout(timer);\n const now = Date.now();\n const timeFromLastCall = now - lastCall;\n\n if (timeFromLastCall > wait) {\n lastCall = now;\n callback(value, index);\n } else {\n timer = setTimeout(() => {\n lastCall = now;\n callback(value, index);\n }, wait);\n }\n };\n};\n\nexport default debounce;\n","/**\n * These definitions can be used to filter an array. Each entry should contain a method normalize which can be used to\n * compile any filter settings and a method \"test\" which takes the compiled result, additional settings and the item to\n * be matched/filtered\n * */\ninterface FilterDefinition<SearchTerm, Normalized, Testable> {\n id: string;\n normalize: (\n searchTerm: SearchTerm,\n caseSensitiveSearch: boolean,\n ) => Normalized;\n test: (\n text: Testable,\n normalizedSearchTerm: Normalized,\n caseSensitiveSearch: boolean,\n inverseSearch: boolean,\n ) => boolean;\n}\n\ninterface StringTest {\n test(str: string): boolean;\n}\n\ntype SearchFilterDefinition = FilterDefinition<string, string, string>;\ntype PatternFilterDefinition = FilterDefinition<\n string,\n RegExp | StringTest,\n string\n>;\ntype TypeFilterDefinition = FilterDefinition<\n string[],\n StringTest,\n string | undefined\n>;\n\nconst modeDefinitions = [\n {\n id: \"search\",\n normalize(searchTerm, caseSensitiveSearch) {\n return caseSensitiveSearch ? searchTerm : searchTerm.toLowerCase();\n },\n test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {\n const testText = caseSensitiveSearch ? text : text.toLowerCase();\n const matches = testText.includes(normalizedSearchTerm);\n return inverseSearch ? !matches : matches;\n },\n } satisfies SearchFilterDefinition,\n {\n id: \"wildcard\",\n normalize(searchTerm, caseSensitiveSearch) {\n // Do a regex search, explicitly matching start and end of the search term.\n // All regex special character except from \"* and ?\" (wildcards) are escaped.\n if (searchTerm.length > 0) {\n const escapedSearchTerm = searchTerm.replace(\n /[-[\\]{}()+.,\\\\^$|#\\s]/g,\n \"\\\\$&\",\n );\n const wildcardSearchTerm = escapedSearchTerm\n .replace(/\\*/g, \".*\")\n .replace(/\\?/g, \".?\");\n searchTerm = `^${wildcardSearchTerm}$`;\n } else {\n return { test: () => false };\n }\n try {\n const flags = caseSensitiveSearch ? \"\" : \"i\";\n return new RegExp(searchTerm, flags);\n } catch (_error) {\n // In case of an invalid regular expression, an impossible\n // regex is returned, not matching anything.\n return /$^/;\n }\n },\n test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {\n const matches = normalizedSearchTerm.test(text);\n return inverseSearch ? !matches : matches;\n },\n } satisfies PatternFilterDefinition,\n {\n id: \"regex\",\n normalize(searchTerm, caseSensitiveSearch) {\n try {\n const flags = caseSensitiveSearch ? \"\" : \"i\";\n return new RegExp(`^(${searchTerm})$`, flags);\n } catch (_error) {\n // In case of an invalid regular expression, an impossible\n // regex is returned, not matching anything.\n return /$^/;\n }\n },\n test(text, normalizedSearchTerm, caseSensitiveSearch, inverseSearch) {\n const matches = normalizedSearchTerm.test(text);\n return inverseSearch ? !matches : matches;\n },\n } satisfies PatternFilterDefinition,\n {\n id: \"type\",\n normalize(selectedTypes) {\n return { test: (type: string) => selectedTypes.includes(type) };\n },\n test(type, normalizedSearchTerm) {\n if (typeof type === \"undefined\") {\n return false;\n }\n return normalizedSearchTerm.test(type);\n },\n } satisfies TypeFilterDefinition,\n];\n\n// convert [{id: \"key1\", text: \"asdf\"}, ...] to {\"key1\": {id:\"key1\", text: \"asdf\"} ... }\nexport const filters: Record<\n string,\n FilterDefinition<unknown, unknown, unknown>\n> = Object.assign({}, ...modeDefinitions.map((obj) => ({ [obj.id]: obj })));\n","/**\n * Get the users local timezone.\n *\n * @returns current users timezone (browser based) tz db string (e. g. Europe/Berlin).\n */\n// eslint-disable-next-line new-cap\nexport default () => Intl.DateTimeFormat().resolvedOptions().timeZone;\n","import prettyBytes from \"pretty-bytes\";\n\nimport getLocalTimeZone from \"./localTimezone\";\n/**\n * Converts the specified date String to human readable text containing the day, month, and year.\n * Example: '2018-07-31T09:44:31+00:00' => 'Jul 31, 2018'\n *\n * @param dateString String representation of the Date to format\n * @param useTimeZone to set the timeZone where the user is located, and display local date and time\n * @returns human readable date String\n */\nexport const formatDateString = (\n dateString: string | number,\n useTimeZone = false,\n) => {\n const date = new Date(dateString);\n\n // @ts-expect-error Argument of type 'Date' is not assignable to parameter of type 'number'\n if (isNaN(date)) {\n throw Error(\"Invalid Date format\");\n }\n\n const baseDateOptions: Intl.DateTimeFormatOptions = {\n day: \"numeric\",\n month: \"short\",\n year: \"numeric\",\n };\n\n // This only works for the default locale of en-US, as support of other locals in node js might not be available\n // See for example this issue https://github.com/nodejs/node/issues/8500\n const dateOptions: Intl.DateTimeFormatOptions = useTimeZone\n ? { ...baseDateOptions, timeZone: getLocalTimeZone() }\n : baseDateOptions;\n\n return date.toLocaleDateString(\"en-US\", dateOptions);\n};\n\n/**\n * Converts the specified time String to human readable text containing the hour (12-hour) and minute.\n * Example: '2018-07-31T09:44:31+00:00' => '9:44 AM'\n *\n * @param timeString String representation of the Date (including time) to format\n * @param useTimeZone to set the timeZone where the user is located, and display local date and time\n * @returns human readable time String\n */\nexport const formatTimeString = (\n timeString: string | number,\n useTimeZone = false,\n) => {\n const time = new Date(timeString);\n\n // @ts-expect-error Argument of type 'Date' is not assignable to parameter of type 'number'\n if (isNaN(time)) {\n throw Error(\"Invalid Date format\");\n }\n\n // This only works for the default locale of en-US, as support of other locals in node js might not be available\n // See for example this issue https://github.com/nodejs/node/issues/8500\n const baseTimeOptions: Intl.DateTimeFormatOptions = {\n hour: \"numeric\",\n minute: \"2-digit\",\n };\n\n const timeOptions: Intl.DateTimeFormatOptions = useTimeZone\n ? { ...baseTimeOptions, timeZone: getLocalTimeZone() }\n : baseTimeOptions;\n\n return time.toLocaleTimeString(\"en-US\", timeOptions);\n};\n\n/**\n * Converts the specified time String to human readable text containing the date (day, month, year) and time (hour,\n * minute; 12-hour).\n * Example: '2018-07-31T09:44:31+00:00' => 'Jul 31, 2018 9:44 AM'\n *\n * @param dateTimeString String representation of the Date (including time and date) to format\n * @param useTimeZone to set the timeZone where the user is located, and display local date and time\n * @returns human readable date/time String\n */\nexport const formatDateTimeString = (\n dateTimeString: string | number,\n useTimeZone = false,\n) => {\n return `${formatDateString(dateTimeString, useTimeZone)} ${formatTimeString(\n dateTimeString,\n useTimeZone,\n )}`;\n};\n\n/**\n * Converts the specified date and time to the user time zone with option to display (day, month, year) only or with time (hour,\n * minute; 12-hour).\n *\n * @param showTime String representation of the Date to convert and format\n * @param String | number} date String representation of the Date to convert and format\n * @returns human readable date/time String converted to user time zone\n */\nexport const formatLocalDateTimeString = (date: string, showTime: boolean) =>\n showTime ? formatDateTimeString(date, true) : formatDateString(date, true);\n\nexport const formatFileSize = (bytes: number): string => {\n const safeBytes = Number.isFinite(bytes) && bytes >= 0 ? bytes : 0;\n\n return prettyBytes(safeBytes);\n};\n","const getDeepActiveElement = () => {\n let element = document?.activeElement;\n while (element?.shadowRoot) {\n element = element?.shadowRoot?.activeElement;\n }\n return element;\n};\n\nexport default getDeepActiveElement;\n","/**\n * Since (a % b) yields a negative outcome for negative a, we need this method in order\n * to correctly compute wrapped around indices in lists\n * @param {number} index an arbitrary integer\n * @param {number} length a positive integer\n * @returns {number} the non-negative modulo outcome\n */\nexport default (index: number, length: number) =>\n ((index % length) + length) % length;\n","export type Period = {\n negative: boolean;\n years: number;\n months: number;\n weeks: number;\n days: number;\n};\n\nexport type Duration = {\n negative: boolean;\n hours: number;\n minutes: number;\n seconds: number;\n milliseconds: number;\n};\n\ntype AllowedIntervalTypes = \"DATE\" | \"TIME\";\ntype AllowedIntervalTypesOrEither = AllowedIntervalTypes | \"DATE_OR_TIME\";\n\ntype IntervalStringValidationResult =\n | {\n valid: true;\n type: AllowedIntervalTypes;\n negative: boolean;\n }\n | { valid: false };\n\nexport type PeriodOrDuration =\n | {\n interval: Period;\n type: \"DATE\";\n }\n | {\n interval: Duration;\n type: \"TIME\";\n };\n\nconst extractPeriodFromRegexMatch = (\n negative: boolean,\n match: RegExpExecArray,\n): Period => {\n return {\n negative,\n years: parseInt(match[1] ?? \"0\", 10),\n months: parseInt(match[2] ?? \"0\", 10),\n weeks: parseInt(match[3] ?? \"0\", 10),\n days: parseInt(match[4] ?? \"0\", 10),\n };\n};\n\nconst extractDurationFromRegexMatch = (\n negative: boolean,\n match: RegExpExecArray,\n): Duration => {\n // eslint-disable-next-line no-magic-numbers\n const milliseconds = parseInt(match[4]?.padEnd(3, \"0\") ?? \"0\", 10);\n\n return {\n negative,\n hours: parseInt(match[1] ?? \"0\", 10),\n minutes: parseInt(match[2] ?? \"0\", 10),\n seconds: parseInt(match[3] ?? \"0\", 10),\n milliseconds,\n };\n};\n\nexport const isZero = (interval: PeriodOrDuration): boolean => {\n if (interval.type === \"DATE\") {\n return (\n interval.interval.years === 0 &&\n interval.interval.months === 0 &&\n interval.interval.weeks === 0 &&\n interval.interval.days === 0\n );\n } else {\n return (\n interval.interval.hours === 0 &&\n interval.interval.minutes === 0 &&\n interval.interval.seconds === 0 &&\n interval.interval.milliseconds === 0\n );\n }\n};\n\n/**\n * Take an interval object and convert it to an ISO duration or period string. All parts of the\n * relevant part of the Interval object are included in the output, even if they are zero.\n *\n * Technically the ISO standard allows to mix period and duration parts, but we don't support that\n * here because it's incredibly hard to deal with all the edge cases. Maybe in a future ticket.\n *\n * The output here is allowed to be negative, in which case the minus sign is prepended to the\n * output.\n *\n * @param toFormat The PeriodOrDuration object to format\n */\nexport const formatIntervalToISOIntervalString = (\n toFormat: PeriodOrDuration,\n): string => {\n let output = \"P\";\n\n if (toFormat.type === \"DATE\") {\n output += `${toFormat.interval.years}Y${toFormat.interval.months}M${toFormat.interval.weeks}W${toFormat.interval.days}D`;\n } else {\n output += `T${toFormat.interval.hours}H${toFormat.interval.minutes}M${toFormat.interval.seconds}.${toFormat.interval.milliseconds\n .toString()\n // eslint-disable-next-line no-magic-numbers\n .padStart(3, \"0\")}S`;\n }\n\n if (toFormat.interval.negative) {\n output = `-${output}`;\n }\n return output;\n};\n\n/**\n * Take an interval object and convert it to a human readable string. Only non-zero parts are\n * included in the output (unless all parts are 0).\n *\n * The output here is allowed to be negative, in which case the minus sign is prepended to the\n * output and we wrap the whole thing in brackets e.g. -(1 year 2 days).\n *\n * @param toFormat The PeriodOrDuration object to format\n */\nexport const formatIntervalToHumanReadableIntervalString = (\n toFormat: PeriodOrDuration,\n): string => {\n const formatPart = (value: number, unit: string): string => {\n if (value === 0) {\n return \"\";\n } else if (value === 1) {\n return `${value} ${unit} `;\n } else {\n return `${value} ${unit}s `;\n }\n };\n\n let output = \"\";\n\n if (toFormat.type === \"DATE\") {\n if (isZero(toFormat)) {\n return \"0 days\";\n }\n\n output += formatPart(toFormat.interval.years, \"year\");\n output += formatPart(toFormat.interval.months, \"month\");\n output += formatPart(toFormat.interval.weeks, \"week\");\n output += formatPart(toFormat.interval.days, \"day\");\n } else {\n if (isZero(toFormat)) {\n return \"0 seconds\";\n }\n\n output += formatPart(toFormat.interval.hours, \"hour\");\n output += formatPart(toFormat.interval.minutes, \"minute\");\n\n const milliSecondsZero = toFormat.interval.milliseconds === 0;\n if (toFormat.interval.seconds !== 0 || !milliSecondsZero) {\n if (milliSecondsZero) {\n output += formatPart(toFormat.interval.seconds, \"second\");\n } else {\n output += `${toFormat.interval.seconds}.${toFormat.interval.milliseconds.toString().padStart(3, \"0\")} seconds `; // eslint-disable-line no-magic-numbers\n }\n }\n }\n\n if (toFormat.interval.negative) {\n output = `-(${output.trim()})`;\n }\n\n return output.trim();\n};\n\nconst yearsPart = \"(\\\\d+)\\\\s*y(?:ears?)?\";\nconst monthsPart = \"(\\\\d+)\\\\s*m(?:o(?:nths?)?)?\";\nconst weeksPart = \"(\\\\d+)\\\\s*w(?:eeks?)?\";\nconst daysPart = \"(\\\\d+)\\\\s*d(?:ays?)?\";\nconst hoursPart = \"(\\\\d+)\\\\s*h(?:ours?)?\";\nconst minutesPart = \"(\\\\d+)\\\\s*m(?:in(?:s|utes?)?)?\";\nconst secondsPart = \"(\\\\d+)(?:[,.](\\\\d{1,3}))?\\\\s*s(?:ec(?:s|onds?)?)?\";\n\n/**\n * Matches a human readable period string, e.g. \"1y 2mo 3weeks 4day\" (each part is optional)\n */\nconst humanReadablePeriodRegex = new RegExp(\n `^(?:${yearsPart})?\\\\s*(?:${monthsPart})?\\\\s*(?:${weeksPart})?\\\\s*(?:${daysPart})?\\\\s*$`,\n \"i\",\n);\n\n/**\n * Matches a human readable duration string, e.g. \"1h 2m 3.456s\" (each part is optional)\n */\nconst humanReadableDurationRegex = new RegExp(\n `^(?:${hoursPart})?\\\\s*(?:${minutesPart})?\\\\s*(?:${secondsPart})?$`,\n \"i\",\n);\n\n/**\n * Matches a negative human readable period string, e.g. \"-(1y 2mo 3weeks 4day)\" (each part is optional)\n */\nconst negativeHumanReadablePeriodRegex = new RegExp(\n `^\\\\s*-\\\\s*\\\\(\\\\s*${humanReadablePeriodRegex.source.replace(/[$^]/g, \"\")}\\\\s*\\\\)\\\\s*$`,\n \"i\",\n);\n\n/**\n * Matches a negative human readable period string with one field like \"-1y\" or \"-1w\"\n */\nconst negativeHumanReadablePeriodRegexWithSingleField = new RegExp(\n `^\\\\s*-\\\\s*(?:\\\\s*${yearsPart}|${monthsPart}|${weeksPart}|${daysPart})\\\\s*$`,\n \"i\",\n);\n\n/**\n * Matches a negative human readable duration string, e.g. \"-(1h 2m 3.456s)\" (each part is optional)\n */\nconst negativeHumanReadableDurationRegex = new RegExp(\n `^\\\\s*-\\\\s*\\\\(\\\\s*${humanReadableDurationRegex.source.replace(/[$^]/g, \"\")}\\\\s*\\\\)\\\\s*$`,\n \"i\",\n);\n\n/**\n * Matches a negative human readable duration string with one field like \"-1h\" or \"-1.5s\"\n */\nconst negativeHumanReadableDurationRegexWithSingleField = new RegExp(\n `^\\\\s*-\\\\s*(?:\\\\s*${hoursPart}|${minutesPart}|${secondsPart})\\\\s*$`,\n \"i\",\n);\n\n/**\n * Try to parse a human readable interval string into an Interval object. Any parts not specified\n * are assumed to be zero. Note that the string must be either a period or a duration, not a mix of\n * both. So for example, \"1y 2mo 3weeks 4day\" is fine, as is \"1h 2m 3.456s\". However, \"1y 2mo 1sec\"\n * is not, since it's a mix of both.\n *\n * Negative intervals are allowed, although if multiple fields are provided the string must include\n * brackets, so \"-(1y 2mo)\" is also valid, as is \"-5 seconds\".\n *\n * The string is required to have at least some content, any string that is blank will throw an error.\n *\n * @param intervalString The human readable time string\n */\nexport const parseHumanReadableIntervalString = (\n intervalString: string,\n): PeriodOrDuration => {\n intervalString = intervalString?.trim();\n\n if (!intervalString) {\n throw new Error(\"Empty interval string\");\n }\n\n const matchPositivePeriod = humanReadablePeriodRegex.exec(intervalString);\n const matchNegativePeriod =\n negativeHumanReadablePeriodRegex.exec(intervalString) ??\n negativeHumanReadablePeriodRegexWithSingleField.exec(intervalString);\n const matchPositiveDuration = humanReadableDurationRegex.exec(intervalString);\n const matchNegativeDuration =\n negativeHumanReadableDurationRegex.exec(intervalString) ??\n negativeHumanReadableDurationRegexWithSingleField.exec(intervalString);\n\n const matchPeriod = matchPositivePeriod ?? matchNegativePeriod;\n const matchDuration = matchPositiveDuration ?? matchNegativeDuration;\n const negative = (matchNegativePeriod ?? matchNegativeDuration) !== null;\n\n // I think this will happen only for the string \"1M\" or similar\n if (matchDuration && matchPeriod) {\n throw new Error(\"Ambiguous time format\");\n }\n\n if (matchPeriod) {\n return {\n type: \"DATE\",\n interval: extractPeriodFromRegexMatch(negative, matchPeriod),\n };\n } else if (matchDuration) {\n return {\n type: \"TIME\",\n interval: extractDurationFromRegexMatch(negative, matchDuration),\n };\n } else {\n throw new Error(`Invalid human readable time: ${intervalString}`);\n }\n};\n\n/**\n * Check if the given string can be understood as a human readable duration or period string. The\n * type parameter specifies whether the string should be a date, time, or either.\n *\n * @param time the string to check\n * @param expectedType the type of the string - either \"DATE\", \"TIME\", or \"ANY\"\n */\nexport const isValidHumanReadableIntervalString = (\n time: string,\n expectedType: AllowedIntervalTypesOrEither,\n): IntervalStringValidationResult => {\n try {\n const validationResult = parseHumanReadableIntervalString(time);\n const actualType = validationResult.type;\n const negative = validationResult.interval.negative;\n\n if (actualType === expectedType || expectedType === \"DATE_OR_TIME\") {\n return {\n valid: true,\n type: actualType,\n negative,\n };\n } else {\n return { valid: false };\n }\n } catch (_e) {\n return { valid: false };\n }\n};\n\n/**\n * Convert an ISO duration OR period string to an Interval object. So for example,\n * \"P1Y2M3W4D\" is fine, as is \"PT1H2M3.456S\". However, \"P1Y2M3W4D1H2M3.456S\" is not, since\n * it's a mix of both. We're more forgiving than the ISO standard, so we allow for missing parts.\n * Also, the string is allowed to be negative, so \"-P1Y2M3W4D\" is also valid.\n *\n * The string is required to have at least some content, so the strings \"\", \"P\", and \"PT\" are\n * considered invalid (also if they start with a -).\n *\n * @param isoString The ISO duration or period string.\n */\nexport const parseISOIntervalString = (isoString: string): PeriodOrDuration => {\n isoString = isoString?.trim();\n\n if ([\"\", \"P\", \"PT\", \"-\", \"-P\", \"-PT\"].includes(isoString)) {\n throw new Error(\"Empty ISO duration\");\n }\n\n const periodRegex = /^-?P(?:(\\d+)Y)?(?:(\\d+)M)?(?:(\\d+)W)?(?:(\\d+)D)?$/;\n const durationRegex =\n /^-?PT(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)(?:[,.](\\d{1,3}))?S)?$/;\n\n const matchPeriod = periodRegex.exec(isoString);\n const matchDuration = durationRegex.exec(isoString);\n\n if (matchPeriod) {\n return {\n type: \"DATE\",\n interval: extractPeriodFromRegexMatch(\n isoString.startsWith(\"-\"),\n matchPeriod,\n ),\n };\n } else if (matchDuration) {\n return {\n type: \"TIME\",\n interval: extractDurationFromRegexMatch(\n isoString.startsWith(\"-\"),\n matchDuration,\n ),\n };\n } else {\n throw new Error(`Invalid ISO duration: ${isoString}`);\n }\n};\n\n/**\n * Check if the given string is a valid duration or period ISO string. The type parameter\n * specifies whether the string should be a date, time, or either.\n *\n * @param isoString the string to check\n * @param type the type of the string - either \"DATE\", \"TIME\", or \"ANY\"\n */\nexport const isValidISOIntervalString = (\n isoString: string,\n type: AllowedIntervalTypesOrEither,\n): IntervalStringValidationResult => {\n try {\n const validationResult = parseISOIntervalString(isoString);\n const actualType = validationResult.type;\n const negative = validationResult.interval.negative;\n\n if (actualType === type || type === \"DATE_OR_TIME\") {\n return {\n valid: true,\n type: actualType,\n negative,\n };\n } else {\n return { valid: false };\n }\n } catch (_e) {\n return { valid: false };\n }\n};\n\n/**\n * Try to convert an interval string to an Interval object. The string can be either an ISO\n * duration/period string or a human readable string. If the string is not valid, an error is\n * thrown.\n *\n * @param time the time string, either ISO or human readable\n */\nexport const parseGenericIntervalString = (time: string): PeriodOrDuration => {\n const validISO = isValidISOIntervalString(time, \"DATE_OR_TIME\");\n const validHumanReadable = isValidHumanReadableIntervalString(\n time,\n \"DATE_OR_TIME\",\n );\n if (validISO.valid) {\n return parseISOIntervalString(time);\n } else if (validHumanReadable.valid) {\n return parseHumanReadableIntervalString(time);\n } else {\n throw new Error(`Invalid interval string: ${time}`);\n }\n};\n\n/**\n * Check if the given string is a valid interval string, either human readable or ISO. The type parameter\n * specifies whether the string should be a period, duration, or either.\n *\n * @param time the time string to check\n * @param type the type of the string - either \"DATE\", \"TIME\", or \"ANY\"\n */\nexport const isValidIntervalString = (\n time: string,\n type: AllowedIntervalTypesOrEither,\n): IntervalStringValidationResult => {\n const validISO = isValidISOIntervalString(time, type);\n const validHumanReadable = isValidHumanReadableIntervalString(time, type);\n if (validISO.valid) {\n return validISO;\n } else if (validHumanReadable.valid) {\n return validHumanReadable;\n } else {\n return { valid: false };\n }\n};\n","/**\n * Count the number of integer digits for a given number.\n *\n * @param input number.\n * @returns number of integer digits x has. 1234 = 4 but 1234.44 is also 4.\n */\nexport default (input: number) =>\n Math.max(Math.floor(Math.log10(Math.abs(input))), 0) + 1;\n","export class AbortError extends Error {}\n\n/**\n * Helper to create an abortable promise. Returns an AbortController and a Function\n * that you can pass your async handler to. Whenever the AbortController signal is\n * aborted then the async handler's promise will reject with an AbortError\n *\n * Example:\n * ```\n * import { abortUtils } from \"@knime/utils\"\n * const myFetchCall = async (params...) => {...};\n *\n * try {\n * const { runAbortablePromise, abortController } = createAbortablePromise(() =>\n * myFetchCall(params...),\n * );\n * } catch (e) {\n * if (e instanceof abortUtils.AbortError) {\n * console.info('ignore due to abort');\n * return;\n * }\n * }\n *\n * // somewhere else (while request is in-flight)\n * abortController.abort(new abortUtils.AbortError('reason here'))\n * ```\n */\nexport const createAbortablePromise = () => {\n const abortController: AbortController = new AbortController();\n\n const runAbortablePromise = <T = unknown>(request: () => Promise<T>) => {\n return new Promise<T>((resolve, reject) => {\n // abort logic\n const abortListener = ({ target }: Event) => {\n abortController.signal.removeEventListener(\"abort\", abortListener);\n const reason = (target as AbortSignal).reason;\n reject(reason instanceof AbortError ? reason : new AbortError(reason));\n };\n\n // the actual call\n request()\n .then(resolve)\n .catch((error) => {\n if (error instanceof AbortError) {\n return;\n }\n\n reject(error);\n });\n\n abortController.signal.addEventListener(\"abort\", abortListener);\n });\n };\n\n return { abortController, runAbortablePromise };\n};\n","export type UnwrappedPromise<T = unknown> = {\n resolve: (value: T | PromiseLike<T>) => void;\n reject: (reason?: unknown) => void;\n promise: Promise<T>;\n};\n\nexport const createUnwrappedPromise = <T>(): UnwrappedPromise<T> => {\n let resolve: (value: T | PromiseLike<T>) => void = () => {};\n let reject: (reason?: unknown) => void = () => {};\n\n const promise = new Promise<T>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n\n return { resolve, reject, promise };\n};\n","/**\n * Returns promise that resolves after ms.\n */\nexport default function sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import sleep from \"../sleep\";\n\nexport const DEFAULT_RETRY_DELAY_MS = 0;\nexport const DEFAULT_RETRY_COUNT = 5;\n\n/**\n * Helper to add retry capability to an async function\n * @param fn async function\n * @param retryCount max number of retries. defaults to 5\n * @param retryDelayMS delay in-between retries in millisecs. defaults to 0\n * @param excludeError predicate fn to exclude specific errors from causing a retry\n */\nexport async function retryPromise<T>({\n fn,\n retryCount = DEFAULT_RETRY_COUNT,\n retryDelayMS = DEFAULT_RETRY_DELAY_MS,\n excludeError,\n}: {\n fn: () => Promise<T>;\n retryCount?: number;\n retryDelayMS?: number;\n excludeError?: (error: Error) => boolean;\n}) {\n try {\n return await fn();\n } catch (error) {\n if (excludeError?.(error as Error)) {\n throw error;\n }\n\n if (retryCount > 0) {\n await sleep(retryDelayMS);\n\n // eslint-disable-next-line no-return-await\n return await retryPromise({\n fn,\n retryCount: retryCount - 1,\n retryDelayMS,\n excludeError,\n });\n }\n\n throw error;\n }\n}\n","export * from \"./createAbortablePromise\";\nexport * from \"./createUnwrappedPromise\";\nexport * from \"./retryPromise\";\n","import DomPurify from \"dompurify\";\n\nconst ALLOWED_TAGS = [\n \"p\",\n \"div\",\n \"h1\",\n \"h2\",\n \"h3\",\n \"h4\",\n \"h5\",\n \"h6\",\n \"ul\",\n \"ol\",\n \"li\",\n \"blockquote\",\n \"b\",\n \"i\",\n \"s\",\n \"u\",\n \"sup\",\n \"sub\",\n \"ins\",\n \"del\",\n \"strong\",\n \"strike\",\n \"tt\",\n \"code\",\n \"big\",\n \"small\",\n \"br\",\n \"span\",\n \"em\",\n];\n\n/**\n * Sanitizes Raw HTML and only allow specific tags to be used, as per OWASP standards.\n * @param rawHTML\n * @param options.allowStyleAttribute - Allow the style attribute on elements\n * @param options.allowHyperlinks - Allow anchor tags with href attribute\n * @returns sanitized html\n */\nconst sanitizeHTML = (\n rawHTML: string,\n options: { allowStyleAttribute?: boolean; allowHyperlinks?: boolean } = {\n allowStyleAttribute: false,\n allowHyperlinks: false,\n },\n) => {\n const { allowStyleAttribute, allowHyperlinks } = options;\n const ALLOWED_ATTR = [\n ...(allowStyleAttribute ? [\"style\"] : []),\n ...(allowHyperlinks ? [\"href\"] : []),\n ];\n const allowedTags = allowHyperlinks ? [...ALLOWED_TAGS, \"a\"] : ALLOWED_TAGS;\n\n return DomPurify.sanitize(rawHTML, {\n ALLOWED_TAGS: allowedTags,\n ALLOWED_ATTR,\n });\n};\n\n/**\n * Removes any HTML tag from the input string. Keeps HTML entities\n * (e.g because these can be considered plain text)\n * @param rawHTML\n * @returns plain text\n */\nconst stripHTML = (rawHTML: string) => {\n return DomPurify.sanitize(rawHTML, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] });\n};\n\nexport const sanitization = { sanitizeHTML, stripHTML };\n","const defaultMaxLength = 160;\n\n// truncates a string to a given max length\nexport default (string = \"\", maxLength = defaultMaxLength) => {\n const dots = string.length > maxLength ? \"…\" : \"\";\n return `${string.substring(0, maxLength - 1)}${dots}`;\n};\n","/**\n * Gets the file extension\n * @param nameOrPath can take a full file name (e.g \"file.txt\") or a path to a file\n * (e.g \"file://path/to/file.txt\" OR \"/path/to/file.txt\")\n * @returns just the file extension (e.g \"txt\")\n */\nexport const getFileExtension = (nameOrPath: string): string => {\n const basename = nameOrPath.split(/[\\\\/]/).pop() ?? \"\";\n\n const parts = basename.split(\".\");\n\n if (basename === \"\" || parts.length === 1) {\n return \"\";\n }\n\n return parts.at(-1) ?? \"\";\n};\n\n/**\n * Metadata for .knar files, which corresponds to exported KNIME Workflow Groups\n * or Components\n */\nconst KNAR = Object.freeze({\n extension: \"knar\",\n mimeType: \"application/vnd.knime.workflow-group+zip\",\n matches(file: File) {\n const extension = getFileExtension(file.name);\n return extension === this.extension;\n },\n});\n\n/**\n * Metadata for .knwf files, which corresponds to exported KNIME Workflows\n */\nconst KNWF = Object.freeze({\n extension: \"knwf\",\n mimeType: \"application/vnd.knime.workflow+zip\",\n matches(file: File) {\n const extension = getFileExtension(file.name);\n return extension === this.extension;\n },\n /**\n * Gets the name of a .knwf file without the extension. If the file is not\n * matched as a .knwf file then this function will return the default value,\n * which is empty string (\"\") if param is not provided\n */\n getNameOrDefault(file: File, defaultValue = \"\"): string {\n if (!this.matches(file)) {\n return defaultValue;\n }\n\n return file.name.replace(`.${this.extension}`, \"\");\n },\n});\n\nexport const knimeFileFormats = { KNAR, KNWF };\n\n/**\n * Gets the mime type from a given file. Defaults to `application/octet-stream`\n * if mimeType cannot be detected\n * @param file File\n * @returns mimeType\n */\nexport const getFileMimeType = (file: File): string => {\n const DEFAULT_MIMETYPE = \"application/octet-stream\";\n\n const extension = getFileExtension(file.name);\n\n if (!extension) {\n return DEFAULT_MIMETYPE;\n }\n\n if (KNWF.matches(file)) {\n return KNWF.mimeType;\n }\n\n if (KNAR.matches(file)) {\n return KNAR.mimeType;\n }\n\n // file has extension but unrecognizable mime type\n if (!file.type) {\n return DEFAULT_MIMETYPE;\n }\n\n return file.type;\n};\n","/**\n * Platforms that influence how modifier keys are rendered. macOS substitutes\n * dedicated glyphs (`⌘`, `⌥`, `⇧`, …), every other platform uses the textual\n * rendering (`Ctrl`, `Alt`, `Shift`, …).\n */\nexport const hotkeyPlatform = {\n MAC_OS: \"macOS\",\n OTHER: \"other\",\n} as const;\n\nexport const hotkeyPlatforms = Object.values(hotkeyPlatform);\n","/**\n *\n * @returns true if the platform of the user is Mac\n */\nexport const isMac = (): boolean =>\n navigator?.userAgent?.toLowerCase()?.includes(\"mac\");\n\n/**\n *\n * @returns true if the platform of the user is Windows\n */\nexport const isWindows = (): boolean =>\n navigator?.userAgent?.toLowerCase()?.includes(\"windows\");\n","import { isMac } from \"../platform/navigator\";\n\nimport { hotkeyPlatform } from \"./enums\";\nimport type { Hotkey, HotkeyPlatform } from \"./types\";\n\nconst globalKeyMap = {\n ArrowUp: \"↑\",\n ArrowDown: \"↓\",\n ArrowLeft: \"←\",\n ArrowRight: \"→\",\n Enter: \"↵\",\n \" \": \"Space\", // we use event.key and there space is an actual space not the code \"Space\"\n CtrlOrCmd: \"Ctrl\",\n} as const;\n\nconst MacOSkeyMap = {\n Shift: \"⇧\",\n Delete: \"⌫\",\n CtrlOrCmd: \"⌘\",\n Ctrl: \"⌃\",\n Alt: \"⌥\",\n Enter: \"↩\",\n} as const;\n\ntype KeyFormatMap = typeof MacOSkeyMap | typeof globalKeyMap;\n\n/**\n * Returns a string representation of a single hotkey. Replaces some special key names with symbols.\n *\n * By default the platform is auto-detected from the user agent via `isMac()`.\n * Pass `platform` to force a specific platform's glyphs — useful for SSR,\n * tests, or rendering multiple platforms on the same page.\n */\nexport const formatHotkey = (\n hotkey: Hotkey,\n platform?: HotkeyPlatform,\n): string => {\n /**\n * Returns the symbol corresponding to the `key` based on the given\n * `formatMap`. Otherwise, if not found, returns the same `key` value given\n */\n const mapSymbols = (formatMap: KeyFormatMap) => (key: Hotkey) =>\n formatMap[key as keyof KeyFormatMap] ?? key;\n\n /**\n * Pipe function implementation. Receives a list of functions to execute in order\n * and will pipe the parameter passed at the end to each function returning the final output\n */\n const pipe = <T extends () => string>(\n ...fns: Array<(...args: Hotkey[]) => ReturnType<T>>\n ) =>\n fns.reduce(\n (f, g) => (arg) => g(f(arg)),\n (arg: Hotkey) => arg as ReturnType<T>,\n );\n\n const macKeyFormatter = pipe(\n mapSymbols(MacOSkeyMap),\n mapSymbols(globalKeyMap),\n );\n\n const generalKeyFormatter = mapSymbols(globalKeyMap);\n\n const useMacFormatter =\n platform === undefined ? isMac() : platform === hotkeyPlatform.MAC_OS;\n return useMacFormatter\n ? macKeyFormatter(hotkey)\n : generalKeyFormatter(hotkey);\n};\n\nexport const getDefaultSeparator = () => (isMac() ? \" \" : \"+\");\n\n/**\n * Returns a string representation of a list of hotkeys. Replaces some special key names with symbols\n */\nexport const formatHotkeys = (\n hotkeys: Array<Hotkey>,\n getSeparator = getDefaultSeparator,\n) => hotkeys.map((hotkey) => formatHotkey(hotkey)).join(getSeparator());\n\n/**\n * Appends a formatted hotkey shortcut to the given string. Useful for tooltips\n */\nexport const textWithHotkeys = (text: string, hotkeys: Array<Hotkey>) => {\n return `${text} – ${formatHotkeys(hotkeys)}`;\n};\n","import * as navigatorUtils from \"../platform/navigator\";\n\nimport type { Hotkey } from \"./types\";\n\n/**\n * Checks whether a pressed `Digit` key falls within a numeric hotkey range such\n * as `1-9`.\n * @param keyCode - The `KeyboardEvent.code` to check (e.g. `Digit5`).\n * @param hotkey - The hotkey token, expected to be a single-digit range like `1-9`.\n * @returns True if the pressed digit lies within the inclusive range.\n */\nconst isDigitKeyInRange = (keyCode: string, hotkey: Hotkey): boolean => {\n // Digit keys exist from 0 to 9, so valid ranges always have length 3\n const digitRangeLength = 3;\n if (hotkey.length !== digitRangeLength || !keyCode?.startsWith(\"Digit\")) {\n return false;\n }\n\n const keyNumber = Number(keyCode.slice(\"Digit\".length));\n const [lower, upper] = hotkey.split(\"-\");\n\n return (\n Boolean(lower) &&\n Boolean(upper) &&\n Number.parseInt(lower, 10) <= keyNumber &&\n keyNumber <= Number.parseInt(upper, 10)\n );\n};\n\n/**\n * Checks whether a keyboard event matches a hotkey definition. The last token is\n * treated as the character; any preceding tokens are modifiers. The special\n * `CtrlOrCmd` modifier resolves to the platform's primary modifier (Meta/`⌘` on\n * macOS, Ctrl elsewhere).\n * @param event - The keyboard event to check.\n * @param hotkeys - The ordered hotkey tokens (modifiers followed by the character).\n * @returns True if the event matches the given hotkey, otherwise false.\n */\nexport const match = (event: KeyboardEvent, hotkeys: Hotkey[]): boolean => {\n const { key, code, metaKey, ctrlKey, shiftKey, altKey } = event;\n\n const modifiers = hotkeys.slice(); // copy so pop() doesn't mutate the caller's array\n const character = modifiers.pop() ?? \"\";\n\n // our special CtrlOrCmd has to match \"Command ⌘\" (metaKey) on Mac, and Ctrl-Key on other systems\n const ctrlOrMeta = navigatorUtils.isMac() ? \"Meta\" : \"Ctrl\";\n const platformModifiers = new Set(\n modifiers.map((modifier) =>\n modifier === \"CtrlOrCmd\" ? ctrlOrMeta : modifier,\n ),\n );\n\n const metaMatches = Boolean(metaKey) === platformModifiers.has(\"Meta\");\n const ctrlMatches = Boolean(ctrlKey) === platformModifiers.has(\"Ctrl\");\n const shiftMatches = Boolean(shiftKey) === platformModifiers.has(\"Shift\");\n const altMatches = Boolean(altKey) === platformModifiers.has(\"Alt\");\n\n const keysMatch =\n // keys are matched case insensitively\n key.toUpperCase() === character.toUpperCase() ||\n (character.includes(\"-\") && isDigitKeyInRange(code, character)) ||\n // on mac 'backspace' can be used instead of delete\n (navigatorUtils.isMac() && character === \"Delete\" && key === \"Backspace\");\n\n return metaMatches && ctrlMatches && shiftMatches && altMatches && keysMatch;\n};\n","import * as navigatorUtils from \"../platform/navigator\";\n\n/**\n * Checks if any modifier key (Ctrl, Meta, Alt, or Shift) is pressed.\n * @param event - The keyboard event to check.\n * @returns True if a modifier key is pressed, otherwise false.\n */\nexport const isModifierKeyPressed = (event: KeyboardEvent): boolean => {\n return event.ctrlKey || event.metaKey || event.altKey || event.shiftKey;\n};\n\n/**\n * Checks if a specific key (or keys) were pressed without any modifier keys.\n * @param event - The keyboard event to check.\n * @param keys - The key or keys to check for.\n * @returns True if the specified key(s) were pressed without modifiers, otherwise false.\n */\nexport const isKeyWithoutModifiers = (\n event: KeyboardEvent,\n keys: string | string[],\n): boolean => {\n const keyList = Array.isArray(keys) ? keys : [keys];\n return keyList.includes(event.key) && !isModifierKeyPressed(event);\n};\n\n/**\n * Returns the name of the primary modifier key for the current platform.\n */\nexport const getMetaOrCtrlKey = (): \"ctrlKey\" | \"metaKey\" => {\n return navigatorUtils.isMac() ? \"metaKey\" : \"ctrlKey\";\n};\n","import { hotkeyPlatform } from \"./enums\";\nimport {\n formatHotkey,\n formatHotkeys,\n getDefaultSeparator,\n textWithHotkeys,\n} from \"./format\";\nimport { match } from \"./match\";\n\n/**\n * Grouped keyboard-shortcut helpers, exposed as a single namespace for\n * ergonomic access (e.g. `hotkeys.formatHotkey`).\n */\nexport const hotkeys = {\n formatHotkeys,\n formatHotkey,\n getDefaultSeparator,\n hotkeyPlatform,\n textWithHotkeys,\n match,\n};\n\nexport { match };\nexport {\n getMetaOrCtrlKey,\n isKeyWithoutModifiers,\n isModifierKeyPressed,\n} from \"./modifiers\";\nexport type { Hotkey, HotkeyPlatform, KnownHotkey } from \"./types\";\n"],"mappings":"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"}
|
package/dist/test-utils/index.js
CHANGED
|
@@ -1,40 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
1
|
+
//#region test-utils/muteConsole.ts
|
|
2
|
+
var methods = [
|
|
3
|
+
"log",
|
|
4
|
+
"warn",
|
|
5
|
+
"error",
|
|
6
|
+
"info"
|
|
7
|
+
];
|
|
8
|
+
/**
|
|
9
|
+
* Helper function to run code suppressing all console output
|
|
10
|
+
* @param f The function to run. Can be async.
|
|
11
|
+
* @returns The original function's return value
|
|
12
|
+
*/
|
|
13
|
+
var muteConsole_default = (f) => {
|
|
14
|
+
const originals = methods.map((method) => console[method]);
|
|
15
|
+
methods.forEach((method) => {
|
|
16
|
+
console[method] = () => {};
|
|
17
|
+
});
|
|
18
|
+
let originalConsola;
|
|
19
|
+
if (global.consola) {
|
|
20
|
+
originalConsola = global.consola;
|
|
21
|
+
global.consola = consola.create({ level: -1 });
|
|
22
|
+
}
|
|
23
|
+
const restoreOriginals = () => {
|
|
24
|
+
methods.forEach((method, i) => {
|
|
25
|
+
console[method] = originals[i];
|
|
26
|
+
});
|
|
27
|
+
if (originalConsola) global.consola = originalConsola;
|
|
28
|
+
};
|
|
29
|
+
if (f.constructor.name === "AsyncFunction") {
|
|
30
|
+
const result = f();
|
|
31
|
+
if (result instanceof Promise) return result.finally(restoreOriginals);
|
|
32
|
+
} else try {
|
|
33
|
+
return f();
|
|
34
|
+
} catch (e) {
|
|
35
|
+
throw e;
|
|
36
|
+
} finally {
|
|
37
|
+
restoreOriginals();
|
|
38
|
+
}
|
|
37
39
|
};
|
|
40
|
+
//#endregion
|
|
41
|
+
export { muteConsole_default as muteConsole };
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
//# sourceMappingURL=index.js.map
|
|
43
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../test-utils/muteConsole.ts"],"sourcesContent":["/* eslint-disable no-console */\n\ntype ConsoleMethod = \"log\" | \"warn\" | \"error\" | \"info\";\nconst methods: ConsoleMethod[] = [\"log\", \"warn\", \"error\", \"info\"];\n\n/**\n * Helper function to run code suppressing all console output\n * @param f The function to run. Can be async.\n * @returns The original function's return value\n */\nexport default (f: (...args: never[]) => Promise<unknown>) => {\n const originals = methods.map((method) => console[method]);\n methods.forEach((method) => {\n console[method] = () => {};\n });\n\n let originalConsola: typeof consola;\n // @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.\n if (global.consola) {\n // @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.\n originalConsola = global.consola;\n // @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.\n global.consola = consola.create({\n level: -1,\n });\n }\n\n const restoreOriginals = () => {\n methods.forEach((method, i) => {\n console[method] = originals[i];\n });\n if (originalConsola) {\n // @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.\n global.consola = originalConsola;\n }\n };\n\n if (f.constructor.name === \"AsyncFunction\") {\n // async\n const result = f();\n if (result instanceof Promise) {\n return result.finally(restoreOriginals);\n }\n } else {\n // sync\n try {\n return f();\n } catch (e) {\n throw e;\n } finally {\n restoreOriginals();\n }\n }\n};\n"],"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../test-utils/muteConsole.ts"],"sourcesContent":["/* eslint-disable no-console */\n\ntype ConsoleMethod = \"log\" | \"warn\" | \"error\" | \"info\";\nconst methods: ConsoleMethod[] = [\"log\", \"warn\", \"error\", \"info\"];\n\n/**\n * Helper function to run code suppressing all console output\n * @param f The function to run. Can be async.\n * @returns The original function's return value\n */\nexport default (f: (...args: never[]) => Promise<unknown>) => {\n const originals = methods.map((method) => console[method]);\n methods.forEach((method) => {\n console[method] = () => {};\n });\n\n let originalConsola: typeof consola;\n // @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.\n if (global.consola) {\n // @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.\n originalConsola = global.consola;\n // @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.\n global.consola = consola.create({\n level: -1,\n });\n }\n\n const restoreOriginals = () => {\n methods.forEach((method, i) => {\n console[method] = originals[i];\n });\n if (originalConsola) {\n // @ts-expect-error Property 'consola' does not exist on type 'typeof globalThis'.\n global.consola = originalConsola;\n }\n };\n\n if (f.constructor.name === \"AsyncFunction\") {\n // async\n const result = f();\n if (result instanceof Promise) {\n return result.finally(restoreOriginals);\n }\n } else {\n // sync\n try {\n return f();\n } catch (e) {\n throw e;\n } finally {\n restoreOriginals();\n }\n }\n};\n"],"mappings":";AAGA,IAAM,UAA2B;CAAC;CAAO;CAAQ;CAAS;AAAM;;;;;;AAOhE,IAAA,uBAAgB,MAA8C;CAC5D,MAAM,YAAY,QAAQ,KAAK,WAAW,QAAQ,OAAO;CACzD,QAAQ,SAAS,WAAW;EAC1B,QAAQ,gBAAgB,CAAC;CAC3B,CAAC;CAED,IAAI;CAEJ,IAAI,OAAO,SAAS;EAElB,kBAAkB,OAAO;EAEzB,OAAO,UAAU,QAAQ,OAAO,EAC9B,OAAO,GACT,CAAC;CACH;CAEA,MAAM,yBAAyB;EAC7B,QAAQ,SAAS,QAAQ,MAAM;GAC7B,QAAQ,UAAU,UAAU;EAC9B,CAAC;EACD,IAAI,iBAEF,OAAO,UAAU;CAErB;CAEA,IAAI,EAAE,YAAY,SAAS,iBAAiB;EAE1C,MAAM,SAAS,EAAE;EACjB,IAAI,kBAAkB,SACpB,OAAO,OAAO,QAAQ,gBAAgB;CAE1C,OAEE,IAAI;EACF,OAAO,EAAE;CACX,SAAS,GAAG;EACV,MAAM;CACR,UAAU;EACR,iBAAiB;CACnB;AAEJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knime/utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "Internal utility functions and constants shared across @knime packages.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,17 +13,11 @@
|
|
|
13
13
|
"main": "./dist/index.js",
|
|
14
14
|
"module": "./dist/index.js",
|
|
15
15
|
"types": "./dist/src/index.d.ts",
|
|
16
|
-
"bin": {
|
|
17
|
-
"pnpm-bulk-audit": "./audit/cli.js"
|
|
18
|
-
},
|
|
19
16
|
"exports": {
|
|
20
17
|
".": {
|
|
21
18
|
"types": "./dist/src/index.d.ts",
|
|
22
19
|
"import": "./dist/index.js"
|
|
23
20
|
},
|
|
24
|
-
"./audit": {
|
|
25
|
-
"import": "./audit/bulkAudit.js"
|
|
26
|
-
},
|
|
27
21
|
"./globals.d.ts": {
|
|
28
22
|
"import": "./globals.d.ts"
|
|
29
23
|
},
|
|
@@ -34,7 +28,6 @@
|
|
|
34
28
|
},
|
|
35
29
|
"files": [
|
|
36
30
|
"dist",
|
|
37
|
-
"audit",
|
|
38
31
|
"globals.d.ts",
|
|
39
32
|
"CHANGELOG.md"
|
|
40
33
|
],
|
|
@@ -45,23 +38,22 @@
|
|
|
45
38
|
"dependencies": {
|
|
46
39
|
"date-fns": "2.30.0",
|
|
47
40
|
"date-fns-tz": "2.0.0",
|
|
48
|
-
"dompurify": "^3.4.
|
|
41
|
+
"dompurify": "^3.4.13",
|
|
49
42
|
"pretty-bytes": "^7.1.0"
|
|
50
43
|
},
|
|
51
44
|
"devDependencies": {
|
|
52
45
|
"@tsconfig/node24": "^24.0.4",
|
|
53
|
-
"@types/node": "^26.
|
|
46
|
+
"@types/node": "^26.1.1",
|
|
54
47
|
"consola": "^3.4.2",
|
|
55
48
|
"flush-promises": "^1.0.2",
|
|
56
49
|
"mock-xmlhttprequest": "^8.3.0",
|
|
57
|
-
"typescript": "^
|
|
58
|
-
"vite": "^
|
|
59
|
-
"vite-plugin-dts": "^
|
|
60
|
-
"vue-tsc": "^3.3.
|
|
50
|
+
"typescript": "^6.0.3",
|
|
51
|
+
"vite": "^8.1.3",
|
|
52
|
+
"vite-plugin-dts": "^5.0.3",
|
|
53
|
+
"vue-tsc": "^3.3.8"
|
|
61
54
|
},
|
|
62
55
|
"engines": {
|
|
63
|
-
"node": "24
|
|
64
|
-
"npm": "please-use-pnpm"
|
|
56
|
+
"node": ">=24"
|
|
65
57
|
},
|
|
66
58
|
"scripts": {
|
|
67
59
|
"build": "pnpm run type-check && pnpm run build-only",
|
|
@@ -71,7 +63,6 @@
|
|
|
71
63
|
"format:check": "prettier --cache --check .",
|
|
72
64
|
"lint": "eslint . --cache --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
|
|
73
65
|
"lint:js": "eslint . --cache --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
|
|
74
|
-
"audit": "pnpm audit --prod",
|
|
75
66
|
"test:unit": "vitest",
|
|
76
67
|
"coverage": "vitest run --coverage"
|
|
77
68
|
}
|
package/audit/README.md
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
# pnpm Bulk Audit
|
|
2
|
-
|
|
3
|
-
A workaround for `pnpm audit` failing with HTTP 410 after npm retired the legacy
|
|
4
|
-
audit endpoints. This tool calls the replacement
|
|
5
|
-
[bulk advisory endpoint](https://api-docs.npmjs.com/#tag/Audit) directly.
|
|
6
|
-
|
|
7
|
-
**Background:** In April 2026 npm retired `/-/npm/v1/security/audits` (and the
|
|
8
|
-
`/quick` variant). `pnpm audit` on all 10.x and early 11.x versions is broken
|
|
9
|
-
because it still calls the old endpoints. See
|
|
10
|
-
[pnpm/pnpm#11265](https://github.com/pnpm/pnpm/issues/11265). This tool bridges
|
|
11
|
-
the gap until pnpm ships a fix.
|
|
12
|
-
|
|
13
|
-
## Quick start
|
|
14
|
-
|
|
15
|
-
Add `@knime/utils` as a dev dependency (it is already present in the monorepo),
|
|
16
|
-
then call the binary directly:
|
|
17
|
-
|
|
18
|
-
```jsonc
|
|
19
|
-
// package.json
|
|
20
|
-
{
|
|
21
|
-
"scripts": {
|
|
22
|
-
"audit": "pnpm-bulk-audit",
|
|
23
|
-
},
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"@knime/utils": "workspace:*",
|
|
26
|
-
},
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Then run:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
pnpm run audit
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## CLI options
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
Usage: pnpm-bulk-audit [options]
|
|
40
|
-
|
|
41
|
-
Options:
|
|
42
|
-
--lockfile <path> Path to pnpm-lock.yaml (default: ./pnpm-lock.yaml)
|
|
43
|
-
--registry <url> npm registry URL (default: https://registry.npmjs.org)
|
|
44
|
-
--severity <level> Minimum severity: low, moderate, high, critical (default: low)
|
|
45
|
-
--prod, -P Only report vulnerabilities in production dependencies
|
|
46
|
-
--json Output raw JSON
|
|
47
|
-
--no-ignore Skip reading ignoreCves/ignoreGhsas from config
|
|
48
|
-
--help, -h Show this help
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Prod vs dev classification
|
|
52
|
-
|
|
53
|
-
Each vulnerability is annotated with `[prod]` or `[dev]` based on whether the
|
|
54
|
-
affected package is reachable from any importer's `dependencies` (as opposed to
|
|
55
|
-
`devDependencies`). The classifier walks the full dependency graph in the
|
|
56
|
-
lockfile, following workspace links transitively.
|
|
57
|
-
|
|
58
|
-
Use `--prod` (or `-P`) to only report vulnerabilities in production
|
|
59
|
-
dependencies.
|
|
60
|
-
|
|
61
|
-
## Ignore lists
|
|
62
|
-
|
|
63
|
-
The tool reads `auditConfig.ignoreCves` and `auditConfig.ignoreGhsas` from two
|
|
64
|
-
places (both are merged):
|
|
65
|
-
|
|
66
|
-
### pnpm-workspace.yaml
|
|
67
|
-
|
|
68
|
-
```yaml
|
|
69
|
-
auditConfig:
|
|
70
|
-
ignoreCves:
|
|
71
|
-
- CVE-2026-4800
|
|
72
|
-
ignoreGhsas:
|
|
73
|
-
- GHSA-78h3-pg4x-j8cv
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### package.json
|
|
77
|
-
|
|
78
|
-
```jsonc
|
|
79
|
-
{
|
|
80
|
-
"pnpm": {
|
|
81
|
-
"auditConfig": {
|
|
82
|
-
"ignoreCves": ["CVE-2026-4800"],
|
|
83
|
-
"ignoreGhsas": ["GHSA-78h3-pg4x-j8cv"],
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
**GHSA IDs** are matched directly from the advisory URL returned by the npm
|
|
90
|
-
registry.
|
|
91
|
-
**CVE IDs** require an extra lookup via the GitHub advisories API
|
|
92
|
-
(`api.github.com/advisories/{ghsa}`) because the npm bulk endpoint does not
|
|
93
|
-
include CVE identifiers in its response.
|
|
94
|
-
|
|
95
|
-
Use `--no-ignore` to skip all ignore-list processing.
|
|
96
|
-
|
|
97
|
-
## Programmatic usage
|
|
98
|
-
|
|
99
|
-
```ts
|
|
100
|
-
import { audit, formatAuditReport, readAuditConfig } from "@knime/utils/audit";
|
|
101
|
-
|
|
102
|
-
const config = readAuditConfig(".");
|
|
103
|
-
const result = await audit({
|
|
104
|
-
lockfilePath: "./pnpm-lock.yaml",
|
|
105
|
-
minSeverity: "high",
|
|
106
|
-
auditConfig: config,
|
|
107
|
-
});
|
|
108
|
-
console.log(formatAuditReport(result));
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## How it works
|
|
112
|
-
|
|
113
|
-
1. Parses the `packages:` section of `pnpm-lock.yaml` to extract every
|
|
114
|
-
`name@version` pair.
|
|
115
|
-
2. POSTs them as `{ "pkg": ["version", …] }` to the npm bulk advisory endpoint
|
|
116
|
-
(`/-/npm/v1/security/advisories/bulk`).
|
|
117
|
-
3. Filters the response by severity and ignore lists.
|
|
118
|
-
4. Exits with code 1 if any vulnerabilities remain, 0 otherwise.
|