diff --git a/.eslintrc.js b/.eslintrc.js index 0d941f5a66b4..c2198da60c52 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -250,6 +250,14 @@ module.exports = { message: "Please don't declare enums, use union types instead.", }, ], + 'no-restricted-properties': [ + 'error', + { + object: 'Image', + property: 'getSize', + message: 'Usage of Image.getImage is restricted. Please use the `react-native-image-size`.', + }, + ], 'no-restricted-imports': [ 'error', { diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4f78ee6b69bf..e9e4da575b4b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,2 +1,6 @@ # Every PR gets a review from an internal Expensify engineer * @Expensify/pullerbear + +# Assign the Design team to review changes to our styles & assets +src/styles/ @Expensify/design @Expensify/pullerbear +assets/ @Expensify/design @Expensify/pullerbear diff --git a/.github/actions/javascript/authorChecklist/index.js b/.github/actions/javascript/authorChecklist/index.js index 02c97d7a0e2b..d779e197c081 100644 --- a/.github/actions/javascript/authorChecklist/index.js +++ b/.github/actions/javascript/authorChecklist/index.js @@ -16918,6 +16918,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/awaitStagingDeploys/awaitStagingDeploys.js b/.github/actions/javascript/awaitStagingDeploys/awaitStagingDeploys.js index 950a8e7092cc..ee3415ce21e3 100644 --- a/.github/actions/javascript/awaitStagingDeploys/awaitStagingDeploys.js +++ b/.github/actions/javascript/awaitStagingDeploys/awaitStagingDeploys.js @@ -1,4 +1,5 @@ const _ = require('underscore'); +const lodashThrottle = require('lodash/throttle'); const CONST = require('../../../libs/CONST'); const ActionUtils = require('../../../libs/ActionUtils'); const GitHubUtils = require('../../../libs/GithubUtils'); @@ -56,7 +57,7 @@ function run() { return promiseDoWhile( () => !_.isEmpty(currentStagingDeploys), - _.throttle( + lodashThrottle( throttleFunc, // Poll every 60 seconds instead of every 10 seconds diff --git a/.github/actions/javascript/awaitStagingDeploys/index.js b/.github/actions/javascript/awaitStagingDeploys/index.js index 6dc6a4a213e3..5f768bd4a725 100644 --- a/.github/actions/javascript/awaitStagingDeploys/index.js +++ b/.github/actions/javascript/awaitStagingDeploys/index.js @@ -8,6 +8,7 @@ /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { const _ = __nccwpck_require__(5067); +const lodashThrottle = __nccwpck_require__(2891); const CONST = __nccwpck_require__(4097); const ActionUtils = __nccwpck_require__(970); const GitHubUtils = __nccwpck_require__(9296); @@ -65,7 +66,7 @@ function run() { return promiseDoWhile( () => !_.isEmpty(currentStagingDeploys), - _.throttle( + lodashThrottle( throttleFunc, // Poll every 60 seconds instead of every 10 seconds @@ -6716,6 +6717,700 @@ function isPlainObject(o) { exports.isPlainObject = isPlainObject; +/***/ }), + +/***/ 9213: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var root = __nccwpck_require__(9882); + +/** Built-in value references. */ +var Symbol = root.Symbol; + +module.exports = Symbol; + + +/***/ }), + +/***/ 7497: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var Symbol = __nccwpck_require__(9213), + getRawTag = __nccwpck_require__(923), + objectToString = __nccwpck_require__(4200); + +/** `Object#toString` result references. */ +var nullTag = '[object Null]', + undefinedTag = '[object Undefined]'; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * The base implementation of `getTag` without fallbacks for buggy environments. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the `toStringTag`. + */ +function baseGetTag(value) { + if (value == null) { + return value === undefined ? undefinedTag : nullTag; + } + return (symToStringTag && symToStringTag in Object(value)) + ? getRawTag(value) + : objectToString(value); +} + +module.exports = baseGetTag; + + +/***/ }), + +/***/ 9528: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var trimmedEndIndex = __nccwpck_require__(7010); + +/** Used to match leading whitespace. */ +var reTrimStart = /^\s+/; + +/** + * The base implementation of `_.trim`. + * + * @private + * @param {string} string The string to trim. + * @returns {string} Returns the trimmed string. + */ +function baseTrim(string) { + return string + ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, '') + : string; +} + +module.exports = baseTrim; + + +/***/ }), + +/***/ 2085: +/***/ ((module) => { + +/** Detect free variable `global` from Node.js. */ +var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; + +module.exports = freeGlobal; + + +/***/ }), + +/***/ 923: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var Symbol = __nccwpck_require__(9213); + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** Used to check objects for own properties. */ +var hasOwnProperty = objectProto.hasOwnProperty; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** Built-in value references. */ +var symToStringTag = Symbol ? Symbol.toStringTag : undefined; + +/** + * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. + * + * @private + * @param {*} value The value to query. + * @returns {string} Returns the raw `toStringTag`. + */ +function getRawTag(value) { + var isOwn = hasOwnProperty.call(value, symToStringTag), + tag = value[symToStringTag]; + + try { + value[symToStringTag] = undefined; + var unmasked = true; + } catch (e) {} + + var result = nativeObjectToString.call(value); + if (unmasked) { + if (isOwn) { + value[symToStringTag] = tag; + } else { + delete value[symToStringTag]; + } + } + return result; +} + +module.exports = getRawTag; + + +/***/ }), + +/***/ 4200: +/***/ ((module) => { + +/** Used for built-in method references. */ +var objectProto = Object.prototype; + +/** + * Used to resolve the + * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) + * of values. + */ +var nativeObjectToString = objectProto.toString; + +/** + * Converts `value` to a string using `Object.prototype.toString`. + * + * @private + * @param {*} value The value to convert. + * @returns {string} Returns the converted string. + */ +function objectToString(value) { + return nativeObjectToString.call(value); +} + +module.exports = objectToString; + + +/***/ }), + +/***/ 9882: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var freeGlobal = __nccwpck_require__(2085); + +/** Detect free variable `self`. */ +var freeSelf = typeof self == 'object' && self && self.Object === Object && self; + +/** Used as a reference to the global object. */ +var root = freeGlobal || freeSelf || Function('return this')(); + +module.exports = root; + + +/***/ }), + +/***/ 7010: +/***/ ((module) => { + +/** Used to match a single whitespace character. */ +var reWhitespace = /\s/; + +/** + * Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace + * character of `string`. + * + * @private + * @param {string} string The string to inspect. + * @returns {number} Returns the index of the last non-whitespace character. + */ +function trimmedEndIndex(string) { + var index = string.length; + + while (index-- && reWhitespace.test(string.charAt(index))) {} + return index; +} + +module.exports = trimmedEndIndex; + + +/***/ }), + +/***/ 3626: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var isObject = __nccwpck_require__(3334), + now = __nccwpck_require__(8349), + toNumber = __nccwpck_require__(1235); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/* Built-in method references for those with the same name as other `lodash` methods. */ +var nativeMax = Math.max, + nativeMin = Math.min; + +/** + * Creates a debounced function that delays invoking `func` until after `wait` + * milliseconds have elapsed since the last time the debounced function was + * invoked. The debounced function comes with a `cancel` method to cancel + * delayed `func` invocations and a `flush` method to immediately invoke them. + * Provide `options` to indicate whether `func` should be invoked on the + * leading and/or trailing edge of the `wait` timeout. The `func` is invoked + * with the last arguments provided to the debounced function. Subsequent + * calls to the debounced function return the result of the last `func` + * invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the debounced function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.debounce` and `_.throttle`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to debounce. + * @param {number} [wait=0] The number of milliseconds to delay. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=false] + * Specify invoking on the leading edge of the timeout. + * @param {number} [options.maxWait] + * The maximum time `func` is allowed to be delayed before it's invoked. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * // Avoid costly calculations while the window size is in flux. + * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); + * + * // Invoke `sendMail` when clicked, debouncing subsequent calls. + * jQuery(element).on('click', _.debounce(sendMail, 300, { + * 'leading': true, + * 'trailing': false + * })); + * + * // Ensure `batchLog` is invoked once after 1 second of debounced calls. + * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); + * var source = new EventSource('/stream'); + * jQuery(source).on('message', debounced); + * + * // Cancel the trailing debounced invocation. + * jQuery(window).on('popstate', debounced.cancel); + */ +function debounce(func, wait, options) { + var lastArgs, + lastThis, + maxWait, + result, + timerId, + lastCallTime, + lastInvokeTime = 0, + leading = false, + maxing = false, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + wait = toNumber(wait) || 0; + if (isObject(options)) { + leading = !!options.leading; + maxing = 'maxWait' in options; + maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + + function invokeFunc(time) { + var args = lastArgs, + thisArg = lastThis; + + lastArgs = lastThis = undefined; + lastInvokeTime = time; + result = func.apply(thisArg, args); + return result; + } + + function leadingEdge(time) { + // Reset any `maxWait` timer. + lastInvokeTime = time; + // Start the timer for the trailing edge. + timerId = setTimeout(timerExpired, wait); + // Invoke the leading edge. + return leading ? invokeFunc(time) : result; + } + + function remainingWait(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime, + timeWaiting = wait - timeSinceLastCall; + + return maxing + ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) + : timeWaiting; + } + + function shouldInvoke(time) { + var timeSinceLastCall = time - lastCallTime, + timeSinceLastInvoke = time - lastInvokeTime; + + // Either this is the first call, activity has stopped and we're at the + // trailing edge, the system time has gone backwards and we're treating + // it as the trailing edge, or we've hit the `maxWait` limit. + return (lastCallTime === undefined || (timeSinceLastCall >= wait) || + (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); + } + + function timerExpired() { + var time = now(); + if (shouldInvoke(time)) { + return trailingEdge(time); + } + // Restart the timer. + timerId = setTimeout(timerExpired, remainingWait(time)); + } + + function trailingEdge(time) { + timerId = undefined; + + // Only invoke if we have `lastArgs` which means `func` has been + // debounced at least once. + if (trailing && lastArgs) { + return invokeFunc(time); + } + lastArgs = lastThis = undefined; + return result; + } + + function cancel() { + if (timerId !== undefined) { + clearTimeout(timerId); + } + lastInvokeTime = 0; + lastArgs = lastCallTime = lastThis = timerId = undefined; + } + + function flush() { + return timerId === undefined ? result : trailingEdge(now()); + } + + function debounced() { + var time = now(), + isInvoking = shouldInvoke(time); + + lastArgs = arguments; + lastThis = this; + lastCallTime = time; + + if (isInvoking) { + if (timerId === undefined) { + return leadingEdge(lastCallTime); + } + if (maxing) { + // Handle invocations in a tight loop. + clearTimeout(timerId); + timerId = setTimeout(timerExpired, wait); + return invokeFunc(lastCallTime); + } + } + if (timerId === undefined) { + timerId = setTimeout(timerExpired, wait); + } + return result; + } + debounced.cancel = cancel; + debounced.flush = flush; + return debounced; +} + +module.exports = debounce; + + +/***/ }), + +/***/ 3334: +/***/ ((module) => { + +/** + * Checks if `value` is the + * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) + * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(_.noop); + * // => true + * + * _.isObject(null); + * // => false + */ +function isObject(value) { + var type = typeof value; + return value != null && (type == 'object' || type == 'function'); +} + +module.exports = isObject; + + +/***/ }), + +/***/ 5926: +/***/ ((module) => { + +/** + * Checks if `value` is object-like. A value is object-like if it's not `null` + * and has a `typeof` result of "object". + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is object-like, else `false`. + * @example + * + * _.isObjectLike({}); + * // => true + * + * _.isObjectLike([1, 2, 3]); + * // => true + * + * _.isObjectLike(_.noop); + * // => false + * + * _.isObjectLike(null); + * // => false + */ +function isObjectLike(value) { + return value != null && typeof value == 'object'; +} + +module.exports = isObjectLike; + + +/***/ }), + +/***/ 6403: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var baseGetTag = __nccwpck_require__(7497), + isObjectLike = __nccwpck_require__(5926); + +/** `Object#toString` result references. */ +var symbolTag = '[object Symbol]'; + +/** + * Checks if `value` is classified as a `Symbol` primitive or object. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to check. + * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. + * @example + * + * _.isSymbol(Symbol.iterator); + * // => true + * + * _.isSymbol('abc'); + * // => false + */ +function isSymbol(value) { + return typeof value == 'symbol' || + (isObjectLike(value) && baseGetTag(value) == symbolTag); +} + +module.exports = isSymbol; + + +/***/ }), + +/***/ 8349: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var root = __nccwpck_require__(9882); + +/** + * Gets the timestamp of the number of milliseconds that have elapsed since + * the Unix epoch (1 January 1970 00:00:00 UTC). + * + * @static + * @memberOf _ + * @since 2.4.0 + * @category Date + * @returns {number} Returns the timestamp. + * @example + * + * _.defer(function(stamp) { + * console.log(_.now() - stamp); + * }, _.now()); + * // => Logs the number of milliseconds it took for the deferred invocation. + */ +var now = function() { + return root.Date.now(); +}; + +module.exports = now; + + +/***/ }), + +/***/ 2891: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var debounce = __nccwpck_require__(3626), + isObject = __nccwpck_require__(3334); + +/** Error message constants. */ +var FUNC_ERROR_TEXT = 'Expected a function'; + +/** + * Creates a throttled function that only invokes `func` at most once per + * every `wait` milliseconds. The throttled function comes with a `cancel` + * method to cancel delayed `func` invocations and a `flush` method to + * immediately invoke them. Provide `options` to indicate whether `func` + * should be invoked on the leading and/or trailing edge of the `wait` + * timeout. The `func` is invoked with the last arguments provided to the + * throttled function. Subsequent calls to the throttled function return the + * result of the last `func` invocation. + * + * **Note:** If `leading` and `trailing` options are `true`, `func` is + * invoked on the trailing edge of the timeout only if the throttled function + * is invoked more than once during the `wait` timeout. + * + * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred + * until to the next tick, similar to `setTimeout` with a timeout of `0`. + * + * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) + * for details over the differences between `_.throttle` and `_.debounce`. + * + * @static + * @memberOf _ + * @since 0.1.0 + * @category Function + * @param {Function} func The function to throttle. + * @param {number} [wait=0] The number of milliseconds to throttle invocations to. + * @param {Object} [options={}] The options object. + * @param {boolean} [options.leading=true] + * Specify invoking on the leading edge of the timeout. + * @param {boolean} [options.trailing=true] + * Specify invoking on the trailing edge of the timeout. + * @returns {Function} Returns the new throttled function. + * @example + * + * // Avoid excessively updating the position while scrolling. + * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); + * + * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. + * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); + * jQuery(element).on('click', throttled); + * + * // Cancel the trailing throttled invocation. + * jQuery(window).on('popstate', throttled.cancel); + */ +function throttle(func, wait, options) { + var leading = true, + trailing = true; + + if (typeof func != 'function') { + throw new TypeError(FUNC_ERROR_TEXT); + } + if (isObject(options)) { + leading = 'leading' in options ? !!options.leading : leading; + trailing = 'trailing' in options ? !!options.trailing : trailing; + } + return debounce(func, wait, { + 'leading': leading, + 'maxWait': wait, + 'trailing': trailing + }); +} + +module.exports = throttle; + + +/***/ }), + +/***/ 1235: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var baseTrim = __nccwpck_require__(9528), + isObject = __nccwpck_require__(3334), + isSymbol = __nccwpck_require__(6403); + +/** Used as references for various `Number` constants. */ +var NAN = 0 / 0; + +/** Used to detect bad signed hexadecimal string values. */ +var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; + +/** Used to detect binary string values. */ +var reIsBinary = /^0b[01]+$/i; + +/** Used to detect octal string values. */ +var reIsOctal = /^0o[0-7]+$/i; + +/** Built-in method references without a dependency on `root`. */ +var freeParseInt = parseInt; + +/** + * Converts `value` to a number. + * + * @static + * @memberOf _ + * @since 4.0.0 + * @category Lang + * @param {*} value The value to process. + * @returns {number} Returns the number. + * @example + * + * _.toNumber(3.2); + * // => 3.2 + * + * _.toNumber(Number.MIN_VALUE); + * // => 5e-324 + * + * _.toNumber(Infinity); + * // => Infinity + * + * _.toNumber('3.2'); + * // => 3.2 + */ +function toNumber(value) { + if (typeof value == 'number') { + return value; + } + if (isSymbol(value)) { + return NAN; + } + if (isObject(value)) { + var other = typeof value.valueOf == 'function' ? value.valueOf() : value; + value = isObject(other) ? (other + '') : other; + } + if (typeof value != 'string') { + return value === 0 ? value : +value; + } + value = baseTrim(value); + var isBinary = reIsBinary.test(value); + return (isBinary || reIsOctal.test(value)) + ? freeParseInt(value.slice(2), isBinary ? 2 : 8) + : (reIsBadHex.test(value) ? NAN : +value); +} + +module.exports = toNumber; + + /***/ }), /***/ 467: @@ -11680,6 +12375,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/checkDeployBlockers/index.js b/.github/actions/javascript/checkDeployBlockers/index.js index a83cdd2b71fc..979543ac3ba8 100644 --- a/.github/actions/javascript/checkDeployBlockers/index.js +++ b/.github/actions/javascript/checkDeployBlockers/index.js @@ -11578,6 +11578,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index 69eef6cfc7fc..c9f8f7d560ce 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -14751,6 +14751,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/getArtifactInfo/index.js b/.github/actions/javascript/getArtifactInfo/index.js index 7dc0300895b0..c99381ffe0b4 100644 --- a/.github/actions/javascript/getArtifactInfo/index.js +++ b/.github/actions/javascript/getArtifactInfo/index.js @@ -11560,6 +11560,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index 30cef0dbdc68..da8a91a28c0d 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -11978,6 +11978,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/getPullRequestDetails/index.js b/.github/actions/javascript/getPullRequestDetails/index.js index 71c502f6161f..dd13a9c3f8f4 100644 --- a/.github/actions/javascript/getPullRequestDetails/index.js +++ b/.github/actions/javascript/getPullRequestDetails/index.js @@ -11545,6 +11545,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/getReleaseBody/index.js b/.github/actions/javascript/getReleaseBody/index.js index f07678cbaf24..68e211b29ab0 100644 --- a/.github/actions/javascript/getReleaseBody/index.js +++ b/.github/actions/javascript/getReleaseBody/index.js @@ -11545,6 +11545,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/isStagingDeployLocked/index.js b/.github/actions/javascript/isStagingDeployLocked/index.js index c5afdab0b078..635e224e87bd 100644 --- a/.github/actions/javascript/isStagingDeployLocked/index.js +++ b/.github/actions/javascript/isStagingDeployLocked/index.js @@ -4,36 +4,6 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 8441: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -const _ = __nccwpck_require__(5067); -const core = __nccwpck_require__(2186); -const GithubUtils = __nccwpck_require__(9296); - -const run = function () { - return GithubUtils.getStagingDeployCash() - .then(({labels, number}) => { - console.log(`Found StagingDeployCash with labels: ${_.pluck(labels, 'name')}`); - core.setOutput('IS_LOCKED', _.contains(_.pluck(labels, 'name'), '🔐 LockCashDeploys 🔐')); - core.setOutput('NUMBER', number); - }) - .catch((err) => { - console.warn('No open StagingDeployCash found, continuing...', err); - core.setOutput('IS_LOCKED', false); - core.setOutput('NUMBER', 0); - }); -}; - -if (require.main === require.cache[eval('__filename')]) { - run(); -} - -module.exports = run; - - -/***/ }), - /***/ 4097: /***/ ((module) => { @@ -11473,6 +11443,67 @@ function wrappy (fn, cb) { } +/***/ }), + +/***/ 2137: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const core = __importStar(__nccwpck_require__(2186)); +const GithubUtils_1 = __importDefault(__nccwpck_require__(9296)); +const run = function () { + return GithubUtils_1.default.getStagingDeployCash() + .then(({ labels, number }) => { + const labelsNames = labels.map((label) => { + if (typeof label === 'string') { + return ''; + } + return label.name; + }); + console.log(`Found StagingDeployCash with labels: ${JSON.stringify(labelsNames)}`); + core.setOutput('IS_LOCKED', labelsNames.includes('🔐 LockCashDeploys 🔐')); + core.setOutput('NUMBER', number); + }) + .catch((err) => { + console.warn('No open StagingDeployCash found, continuing...', err); + core.setOutput('IS_LOCKED', false); + core.setOutput('NUMBER', 0); + }); +}; +if (require.main === require.cache[eval('__filename')]) { + run(); +} +exports["default"] = run; + + /***/ }), /***/ 9296: @@ -11529,6 +11560,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * @@ -12087,2189 +12119,6 @@ module.exports = require("util"); "use strict"; module.exports = require("zlib"); -/***/ }), - -/***/ 6717: -/***/ ((__unused_webpack_module, exports) => { - -// Underscore.js 1.13.6 -// https://underscorejs.org -// (c) 2009-2022 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -Object.defineProperty(exports, "__esModule", ({ value: true })); - -// Current version. -var VERSION = '1.13.6'; - -// Establish the root object, `window` (`self`) in the browser, `global` -// on the server, or `this` in some virtual machines. We use `self` -// instead of `window` for `WebWorker` support. -var root = (typeof self == 'object' && self.self === self && self) || - (typeof global == 'object' && global.global === global && global) || - Function('return this')() || - {}; - -// Save bytes in the minified (but not gzipped) version: -var ArrayProto = Array.prototype, ObjProto = Object.prototype; -var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null; - -// Create quick reference variables for speed access to core prototypes. -var push = ArrayProto.push, - slice = ArrayProto.slice, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; - -// Modern feature detection. -var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined', - supportsDataView = typeof DataView !== 'undefined'; - -// All **ECMAScript 5+** native function implementations that we hope to use -// are declared here. -var nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeCreate = Object.create, - nativeIsView = supportsArrayBuffer && ArrayBuffer.isView; - -// Create references to these builtin functions because we override them. -var _isNaN = isNaN, - _isFinite = isFinite; - -// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. -var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); -var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', - 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; - -// The largest integer that can be represented exactly. -var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; - -// Some functions take a variable number of arguments, or a few expected -// arguments at the beginning and then a variable number of values to operate -// on. This helper accumulates all remaining arguments past the function’s -// argument length (or an explicit `startIndex`), into an array that becomes -// the last argument. Similar to ES6’s "rest parameter". -function restArguments(func, startIndex) { - startIndex = startIndex == null ? func.length - 1 : +startIndex; - return function() { - var length = Math.max(arguments.length - startIndex, 0), - rest = Array(length), - index = 0; - for (; index < length; index++) { - rest[index] = arguments[index + startIndex]; - } - switch (startIndex) { - case 0: return func.call(this, rest); - case 1: return func.call(this, arguments[0], rest); - case 2: return func.call(this, arguments[0], arguments[1], rest); - } - var args = Array(startIndex + 1); - for (index = 0; index < startIndex; index++) { - args[index] = arguments[index]; - } - args[startIndex] = rest; - return func.apply(this, args); - }; -} - -// Is a given variable an object? -function isObject(obj) { - var type = typeof obj; - return type === 'function' || (type === 'object' && !!obj); -} - -// Is a given value equal to null? -function isNull(obj) { - return obj === null; -} - -// Is a given variable undefined? -function isUndefined(obj) { - return obj === void 0; -} - -// Is a given value a boolean? -function isBoolean(obj) { - return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; -} - -// Is a given value a DOM element? -function isElement(obj) { - return !!(obj && obj.nodeType === 1); -} - -// Internal function for creating a `toString`-based type tester. -function tagTester(name) { - var tag = '[object ' + name + ']'; - return function(obj) { - return toString.call(obj) === tag; - }; -} - -var isString = tagTester('String'); - -var isNumber = tagTester('Number'); - -var isDate = tagTester('Date'); - -var isRegExp = tagTester('RegExp'); - -var isError = tagTester('Error'); - -var isSymbol = tagTester('Symbol'); - -var isArrayBuffer = tagTester('ArrayBuffer'); - -var isFunction = tagTester('Function'); - -// Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old -// v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236). -var nodelist = root.document && root.document.childNodes; -if ( true && typeof Int8Array != 'object' && typeof nodelist != 'function') { - isFunction = function(obj) { - return typeof obj == 'function' || false; - }; -} - -var isFunction$1 = isFunction; - -var hasObjectTag = tagTester('Object'); - -// In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`. -// In IE 11, the most common among them, this problem also applies to -// `Map`, `WeakMap` and `Set`. -var hasStringTagBug = ( - supportsDataView && hasObjectTag(new DataView(new ArrayBuffer(8))) - ), - isIE11 = (typeof Map !== 'undefined' && hasObjectTag(new Map)); - -var isDataView = tagTester('DataView'); - -// In IE 10 - Edge 13, we need a different heuristic -// to determine whether an object is a `DataView`. -function ie10IsDataView(obj) { - return obj != null && isFunction$1(obj.getInt8) && isArrayBuffer(obj.buffer); -} - -var isDataView$1 = (hasStringTagBug ? ie10IsDataView : isDataView); - -// Is a given value an array? -// Delegates to ECMA5's native `Array.isArray`. -var isArray = nativeIsArray || tagTester('Array'); - -// Internal function to check whether `key` is an own property name of `obj`. -function has$1(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); -} - -var isArguments = tagTester('Arguments'); - -// Define a fallback version of the method in browsers (ahem, IE < 9), where -// there isn't any inspectable "Arguments" type. -(function() { - if (!isArguments(arguments)) { - isArguments = function(obj) { - return has$1(obj, 'callee'); - }; - } -}()); - -var isArguments$1 = isArguments; - -// Is a given object a finite number? -function isFinite$1(obj) { - return !isSymbol(obj) && _isFinite(obj) && !isNaN(parseFloat(obj)); -} - -// Is the given value `NaN`? -function isNaN$1(obj) { - return isNumber(obj) && _isNaN(obj); -} - -// Predicate-generating function. Often useful outside of Underscore. -function constant(value) { - return function() { - return value; - }; -} - -// Common internal logic for `isArrayLike` and `isBufferLike`. -function createSizePropertyCheck(getSizeProperty) { - return function(collection) { - var sizeProperty = getSizeProperty(collection); - return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= MAX_ARRAY_INDEX; - } -} - -// Internal helper to generate a function to obtain property `key` from `obj`. -function shallowProperty(key) { - return function(obj) { - return obj == null ? void 0 : obj[key]; - }; -} - -// Internal helper to obtain the `byteLength` property of an object. -var getByteLength = shallowProperty('byteLength'); - -// Internal helper to determine whether we should spend extensive checks against -// `ArrayBuffer` et al. -var isBufferLike = createSizePropertyCheck(getByteLength); - -// Is a given value a typed array? -var typedArrayPattern = /\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/; -function isTypedArray(obj) { - // `ArrayBuffer.isView` is the most future-proof, so use it when available. - // Otherwise, fall back on the above regular expression. - return nativeIsView ? (nativeIsView(obj) && !isDataView$1(obj)) : - isBufferLike(obj) && typedArrayPattern.test(toString.call(obj)); -} - -var isTypedArray$1 = supportsArrayBuffer ? isTypedArray : constant(false); - -// Internal helper to obtain the `length` property of an object. -var getLength = shallowProperty('length'); - -// Internal helper to create a simple lookup structure. -// `collectNonEnumProps` used to depend on `_.contains`, but this led to -// circular imports. `emulatedSet` is a one-off solution that only works for -// arrays of strings. -function emulatedSet(keys) { - var hash = {}; - for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true; - return { - contains: function(key) { return hash[key] === true; }, - push: function(key) { - hash[key] = true; - return keys.push(key); - } - }; -} - -// Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't -// be iterated by `for key in ...` and thus missed. Extends `keys` in place if -// needed. -function collectNonEnumProps(obj, keys) { - keys = emulatedSet(keys); - var nonEnumIdx = nonEnumerableProps.length; - var constructor = obj.constructor; - var proto = (isFunction$1(constructor) && constructor.prototype) || ObjProto; - - // Constructor is a special case. - var prop = 'constructor'; - if (has$1(obj, prop) && !keys.contains(prop)) keys.push(prop); - - while (nonEnumIdx--) { - prop = nonEnumerableProps[nonEnumIdx]; - if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) { - keys.push(prop); - } - } -} - -// Retrieve the names of an object's own properties. -// Delegates to **ECMAScript 5**'s native `Object.keys`. -function keys(obj) { - if (!isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (has$1(obj, key)) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; -} - -// Is a given array, string, or object empty? -// An "empty" object has no enumerable own-properties. -function isEmpty(obj) { - if (obj == null) return true; - // Skip the more expensive `toString`-based type checks if `obj` has no - // `.length`. - var length = getLength(obj); - if (typeof length == 'number' && ( - isArray(obj) || isString(obj) || isArguments$1(obj) - )) return length === 0; - return getLength(keys(obj)) === 0; -} - -// Returns whether an object has a given set of `key:value` pairs. -function isMatch(object, attrs) { - var _keys = keys(attrs), length = _keys.length; - if (object == null) return !length; - var obj = Object(object); - for (var i = 0; i < length; i++) { - var key = _keys[i]; - if (attrs[key] !== obj[key] || !(key in obj)) return false; - } - return true; -} - -// If Underscore is called as a function, it returns a wrapped object that can -// be used OO-style. This wrapper holds altered versions of all functions added -// through `_.mixin`. Wrapped objects may be chained. -function _$1(obj) { - if (obj instanceof _$1) return obj; - if (!(this instanceof _$1)) return new _$1(obj); - this._wrapped = obj; -} - -_$1.VERSION = VERSION; - -// Extracts the result from a wrapped and chained object. -_$1.prototype.value = function() { - return this._wrapped; -}; - -// Provide unwrapping proxies for some methods used in engine operations -// such as arithmetic and JSON stringification. -_$1.prototype.valueOf = _$1.prototype.toJSON = _$1.prototype.value; - -_$1.prototype.toString = function() { - return String(this._wrapped); -}; - -// Internal function to wrap or shallow-copy an ArrayBuffer, -// typed array or DataView to a new view, reusing the buffer. -function toBufferView(bufferSource) { - return new Uint8Array( - bufferSource.buffer || bufferSource, - bufferSource.byteOffset || 0, - getByteLength(bufferSource) - ); -} - -// We use this string twice, so give it a name for minification. -var tagDataView = '[object DataView]'; - -// Internal recursive comparison function for `_.isEqual`. -function eq(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](https://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) return a !== 0 || 1 / a === 1 / b; - // `null` or `undefined` only equal to itself (strict comparison). - if (a == null || b == null) return false; - // `NaN`s are equivalent, but non-reflexive. - if (a !== a) return b !== b; - // Exhaust primitive checks - var type = typeof a; - if (type !== 'function' && type !== 'object' && typeof b != 'object') return false; - return deepEq(a, b, aStack, bStack); -} - -// Internal recursive comparison function for `_.isEqual`. -function deepEq(a, b, aStack, bStack) { - // Unwrap any wrapped objects. - if (a instanceof _$1) a = a._wrapped; - if (b instanceof _$1) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className !== toString.call(b)) return false; - // Work around a bug in IE 10 - Edge 13. - if (hasStringTagBug && className == '[object Object]' && isDataView$1(a)) { - if (!isDataView$1(b)) return false; - className = tagDataView; - } - switch (className) { - // These types are compared by value. - case '[object RegExp]': - // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return '' + a === '' + b; - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. - // Object(NaN) is equivalent to NaN. - if (+a !== +a) return +b !== +b; - // An `egal` comparison is performed for other numeric values. - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a === +b; - case '[object Symbol]': - return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b); - case '[object ArrayBuffer]': - case tagDataView: - // Coerce to typed array so we can fall through. - return deepEq(toBufferView(a), toBufferView(b), aStack, bStack); - } - - var areArrays = className === '[object Array]'; - if (!areArrays && isTypedArray$1(a)) { - var byteLength = getByteLength(a); - if (byteLength !== getByteLength(b)) return false; - if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) return true; - areArrays = true; - } - if (!areArrays) { - if (typeof a != 'object' || typeof b != 'object') return false; - - // Objects with different constructors are not equivalent, but `Object`s or `Array`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(isFunction$1(aCtor) && aCtor instanceof aCtor && - isFunction$1(bCtor) && bCtor instanceof bCtor) - && ('constructor' in a && 'constructor' in b)) { - return false; - } - } - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - - // Initializing stack of traversed objects. - // It's done here since we only need them for objects and arrays comparison. - aStack = aStack || []; - bStack = bStack || []; - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] === a) return bStack[length] === b; - } - - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - - // Recursively compare objects and arrays. - if (areArrays) { - // Compare array lengths to determine if a deep comparison is necessary. - length = a.length; - if (length !== b.length) return false; - // Deep compare the contents, ignoring non-numeric properties. - while (length--) { - if (!eq(a[length], b[length], aStack, bStack)) return false; - } - } else { - // Deep compare objects. - var _keys = keys(a), key; - length = _keys.length; - // Ensure that both objects contain the same number of properties before comparing deep equality. - if (keys(b).length !== length) return false; - while (length--) { - // Deep compare each member - key = _keys[length]; - if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack))) return false; - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return true; -} - -// Perform a deep comparison to check if two objects are equal. -function isEqual(a, b) { - return eq(a, b); -} - -// Retrieve all the enumerable property names of an object. -function allKeys(obj) { - if (!isObject(obj)) return []; - var keys = []; - for (var key in obj) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; -} - -// Since the regular `Object.prototype.toString` type tests don't work for -// some types in IE 11, we use a fingerprinting heuristic instead, based -// on the methods. It's not great, but it's the best we got. -// The fingerprint method lists are defined below. -function ie11fingerprint(methods) { - var length = getLength(methods); - return function(obj) { - if (obj == null) return false; - // `Map`, `WeakMap` and `Set` have no enumerable keys. - var keys = allKeys(obj); - if (getLength(keys)) return false; - for (var i = 0; i < length; i++) { - if (!isFunction$1(obj[methods[i]])) return false; - } - // If we are testing against `WeakMap`, we need to ensure that - // `obj` doesn't have a `forEach` method in order to distinguish - // it from a regular `Map`. - return methods !== weakMapMethods || !isFunction$1(obj[forEachName]); - }; -} - -// In the interest of compact minification, we write -// each string in the fingerprints only once. -var forEachName = 'forEach', - hasName = 'has', - commonInit = ['clear', 'delete'], - mapTail = ['get', hasName, 'set']; - -// `Map`, `WeakMap` and `Set` each have slightly different -// combinations of the above sublists. -var mapMethods = commonInit.concat(forEachName, mapTail), - weakMapMethods = commonInit.concat(mapTail), - setMethods = ['add'].concat(commonInit, forEachName, hasName); - -var isMap = isIE11 ? ie11fingerprint(mapMethods) : tagTester('Map'); - -var isWeakMap = isIE11 ? ie11fingerprint(weakMapMethods) : tagTester('WeakMap'); - -var isSet = isIE11 ? ie11fingerprint(setMethods) : tagTester('Set'); - -var isWeakSet = tagTester('WeakSet'); - -// Retrieve the values of an object's properties. -function values(obj) { - var _keys = keys(obj); - var length = _keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[_keys[i]]; - } - return values; -} - -// Convert an object into a list of `[key, value]` pairs. -// The opposite of `_.object` with one argument. -function pairs(obj) { - var _keys = keys(obj); - var length = _keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [_keys[i], obj[_keys[i]]]; - } - return pairs; -} - -// Invert the keys and values of an object. The values must be serializable. -function invert(obj) { - var result = {}; - var _keys = keys(obj); - for (var i = 0, length = _keys.length; i < length; i++) { - result[obj[_keys[i]]] = _keys[i]; - } - return result; -} - -// Return a sorted list of the function names available on the object. -function functions(obj) { - var names = []; - for (var key in obj) { - if (isFunction$1(obj[key])) names.push(key); - } - return names.sort(); -} - -// An internal function for creating assigner functions. -function createAssigner(keysFunc, defaults) { - return function(obj) { - var length = arguments.length; - if (defaults) obj = Object(obj); - if (length < 2 || obj == null) return obj; - for (var index = 1; index < length; index++) { - var source = arguments[index], - keys = keysFunc(source), - l = keys.length; - for (var i = 0; i < l; i++) { - var key = keys[i]; - if (!defaults || obj[key] === void 0) obj[key] = source[key]; - } - } - return obj; - }; -} - -// Extend a given object with all the properties in passed-in object(s). -var extend = createAssigner(allKeys); - -// Assigns a given object with all the own properties in the passed-in -// object(s). -// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) -var extendOwn = createAssigner(keys); - -// Fill in a given object with default properties. -var defaults = createAssigner(allKeys, true); - -// Create a naked function reference for surrogate-prototype-swapping. -function ctor() { - return function(){}; -} - -// An internal function for creating a new object that inherits from another. -function baseCreate(prototype) { - if (!isObject(prototype)) return {}; - if (nativeCreate) return nativeCreate(prototype); - var Ctor = ctor(); - Ctor.prototype = prototype; - var result = new Ctor; - Ctor.prototype = null; - return result; -} - -// Creates an object that inherits from the given prototype object. -// If additional properties are provided then they will be added to the -// created object. -function create(prototype, props) { - var result = baseCreate(prototype); - if (props) extendOwn(result, props); - return result; -} - -// Create a (shallow-cloned) duplicate of an object. -function clone(obj) { - if (!isObject(obj)) return obj; - return isArray(obj) ? obj.slice() : extend({}, obj); -} - -// Invokes `interceptor` with the `obj` and then returns `obj`. -// The primary purpose of this method is to "tap into" a method chain, in -// order to perform operations on intermediate results within the chain. -function tap(obj, interceptor) { - interceptor(obj); - return obj; -} - -// Normalize a (deep) property `path` to array. -// Like `_.iteratee`, this function can be customized. -function toPath$1(path) { - return isArray(path) ? path : [path]; -} -_$1.toPath = toPath$1; - -// Internal wrapper for `_.toPath` to enable minification. -// Similar to `cb` for `_.iteratee`. -function toPath(path) { - return _$1.toPath(path); -} - -// Internal function to obtain a nested property in `obj` along `path`. -function deepGet(obj, path) { - var length = path.length; - for (var i = 0; i < length; i++) { - if (obj == null) return void 0; - obj = obj[path[i]]; - } - return length ? obj : void 0; -} - -// Get the value of the (deep) property on `path` from `object`. -// If any property in `path` does not exist or if the value is -// `undefined`, return `defaultValue` instead. -// The `path` is normalized through `_.toPath`. -function get(object, path, defaultValue) { - var value = deepGet(object, toPath(path)); - return isUndefined(value) ? defaultValue : value; -} - -// Shortcut function for checking if an object has a given property directly on -// itself (in other words, not on a prototype). Unlike the internal `has` -// function, this public version can also traverse nested properties. -function has(obj, path) { - path = toPath(path); - var length = path.length; - for (var i = 0; i < length; i++) { - var key = path[i]; - if (!has$1(obj, key)) return false; - obj = obj[key]; - } - return !!length; -} - -// Keep the identity function around for default iteratees. -function identity(value) { - return value; -} - -// Returns a predicate for checking whether an object has a given set of -// `key:value` pairs. -function matcher(attrs) { - attrs = extendOwn({}, attrs); - return function(obj) { - return isMatch(obj, attrs); - }; -} - -// Creates a function that, when passed an object, will traverse that object’s -// properties down the given `path`, specified as an array of keys or indices. -function property(path) { - path = toPath(path); - return function(obj) { - return deepGet(obj, path); - }; -} - -// Internal function that returns an efficient (for current engines) version -// of the passed-in callback, to be repeatedly applied in other Underscore -// functions. -function optimizeCb(func, context, argCount) { - if (context === void 0) return func; - switch (argCount == null ? 3 : argCount) { - case 1: return function(value) { - return func.call(context, value); - }; - // The 2-argument case is omitted because we’re not using it. - case 3: return function(value, index, collection) { - return func.call(context, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(context, accumulator, value, index, collection); - }; - } - return function() { - return func.apply(context, arguments); - }; -} - -// An internal function to generate callbacks that can be applied to each -// element in a collection, returning the desired result — either `_.identity`, -// an arbitrary callback, a property matcher, or a property accessor. -function baseIteratee(value, context, argCount) { - if (value == null) return identity; - if (isFunction$1(value)) return optimizeCb(value, context, argCount); - if (isObject(value) && !isArray(value)) return matcher(value); - return property(value); -} - -// External wrapper for our callback generator. Users may customize -// `_.iteratee` if they want additional predicate/iteratee shorthand styles. -// This abstraction hides the internal-only `argCount` argument. -function iteratee(value, context) { - return baseIteratee(value, context, Infinity); -} -_$1.iteratee = iteratee; - -// The function we call internally to generate a callback. It invokes -// `_.iteratee` if overridden, otherwise `baseIteratee`. -function cb(value, context, argCount) { - if (_$1.iteratee !== iteratee) return _$1.iteratee(value, context); - return baseIteratee(value, context, argCount); -} - -// Returns the results of applying the `iteratee` to each element of `obj`. -// In contrast to `_.map` it returns an object. -function mapObject(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var _keys = keys(obj), - length = _keys.length, - results = {}; - for (var index = 0; index < length; index++) { - var currentKey = _keys[index]; - results[currentKey] = iteratee(obj[currentKey], currentKey, obj); - } - return results; -} - -// Predicate-generating function. Often useful outside of Underscore. -function noop(){} - -// Generates a function for a given object that returns a given property. -function propertyOf(obj) { - if (obj == null) return noop; - return function(path) { - return get(obj, path); - }; -} - -// Run a function **n** times. -function times(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = optimizeCb(iteratee, context, 1); - for (var i = 0; i < n; i++) accum[i] = iteratee(i); - return accum; -} - -// Return a random integer between `min` and `max` (inclusive). -function random(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); -} - -// A (possibly faster) way to get the current timestamp as an integer. -var now = Date.now || function() { - return new Date().getTime(); -}; - -// Internal helper to generate functions for escaping and unescaping strings -// to/from HTML interpolation. -function createEscaper(map) { - var escaper = function(match) { - return map[match]; - }; - // Regexes for identifying a key that needs to be escaped. - var source = '(?:' + keys(map).join('|') + ')'; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, 'g'); - return function(string) { - string = string == null ? '' : '' + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; -} - -// Internal list of HTML entities for escaping. -var escapeMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`' -}; - -// Function for escaping strings to HTML interpolation. -var _escape = createEscaper(escapeMap); - -// Internal list of HTML entities for unescaping. -var unescapeMap = invert(escapeMap); - -// Function for unescaping strings from HTML interpolation. -var _unescape = createEscaper(unescapeMap); - -// By default, Underscore uses ERB-style template delimiters. Change the -// following template settings to use alternative delimiters. -var templateSettings = _$1.templateSettings = { - evaluate: /<%([\s\S]+?)%>/g, - interpolate: /<%=([\s\S]+?)%>/g, - escape: /<%-([\s\S]+?)%>/g -}; - -// When customizing `_.templateSettings`, if you don't want to define an -// interpolation, evaluation or escaping regex, we need one that is -// guaranteed not to match. -var noMatch = /(.)^/; - -// Certain characters need to be escaped so that they can be put into a -// string literal. -var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\u2028': 'u2028', - '\u2029': 'u2029' -}; - -var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g; - -function escapeChar(match) { - return '\\' + escapes[match]; -} - -// In order to prevent third-party code injection through -// `_.templateSettings.variable`, we test it against the following regular -// expression. It is intentionally a bit more liberal than just matching valid -// identifiers, but still prevents possible loopholes through defaults or -// destructuring assignment. -var bareIdentifier = /^\s*(\w|\$)+\s*$/; - -// JavaScript micro-templating, similar to John Resig's implementation. -// Underscore templating handles arbitrary delimiters, preserves whitespace, -// and correctly escapes quotes within interpolated code. -// NB: `oldSettings` only exists for backwards compatibility. -function template(text, settings, oldSettings) { - if (!settings && oldSettings) settings = oldSettings; - settings = defaults({}, settings, _$1.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escapeRegExp, escapeChar); - index = offset + match.length; - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - - // Adobe VMs need the match returned to produce the correct offset. - return match; - }); - source += "';\n"; - - var argument = settings.variable; - if (argument) { - // Insure against third-party code injection. (CVE-2021-23358) - if (!bareIdentifier.test(argument)) throw new Error( - 'variable is not a bare identifier: ' + argument - ); - } else { - // If a variable is not specified, place data values in local scope. - source = 'with(obj||{}){\n' + source + '}\n'; - argument = 'obj'; - } - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + 'return __p;\n'; - - var render; - try { - render = new Function(argument, '_', source); - } catch (e) { - e.source = source; - throw e; - } - - var template = function(data) { - return render.call(this, data, _$1); - }; - - // Provide the compiled source as a convenience for precompilation. - template.source = 'function(' + argument + '){\n' + source + '}'; - - return template; -} - -// Traverses the children of `obj` along `path`. If a child is a function, it -// is invoked with its parent as context. Returns the value of the final -// child, or `fallback` if any child is undefined. -function result(obj, path, fallback) { - path = toPath(path); - var length = path.length; - if (!length) { - return isFunction$1(fallback) ? fallback.call(obj) : fallback; - } - for (var i = 0; i < length; i++) { - var prop = obj == null ? void 0 : obj[path[i]]; - if (prop === void 0) { - prop = fallback; - i = length; // Ensure we don't continue iterating. - } - obj = isFunction$1(prop) ? prop.call(obj) : prop; - } - return obj; -} - -// Generate a unique integer id (unique within the entire client session). -// Useful for temporary DOM ids. -var idCounter = 0; -function uniqueId(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; -} - -// Start chaining a wrapped Underscore object. -function chain(obj) { - var instance = _$1(obj); - instance._chain = true; - return instance; -} - -// Internal function to execute `sourceFunc` bound to `context` with optional -// `args`. Determines whether to execute a function as a constructor or as a -// normal function. -function executeBound(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); - var self = baseCreate(sourceFunc.prototype); - var result = sourceFunc.apply(self, args); - if (isObject(result)) return result; - return self; -} - -// Partially apply a function by creating a version that has had some of its -// arguments pre-filled, without changing its dynamic `this` context. `_` acts -// as a placeholder by default, allowing any combination of arguments to be -// pre-filled. Set `_.partial.placeholder` for a custom placeholder argument. -var partial = restArguments(function(func, boundArgs) { - var placeholder = partial.placeholder; - var bound = function() { - var position = 0, length = boundArgs.length; - var args = Array(length); - for (var i = 0; i < length; i++) { - args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i]; - } - while (position < arguments.length) args.push(arguments[position++]); - return executeBound(func, bound, this, this, args); - }; - return bound; -}); - -partial.placeholder = _$1; - -// Create a function bound to a given object (assigning `this`, and arguments, -// optionally). -var bind = restArguments(function(func, context, args) { - if (!isFunction$1(func)) throw new TypeError('Bind must be called on a function'); - var bound = restArguments(function(callArgs) { - return executeBound(func, bound, context, this, args.concat(callArgs)); - }); - return bound; -}); - -// Internal helper for collection methods to determine whether a collection -// should be iterated as an array or as an object. -// Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength -// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 -var isArrayLike = createSizePropertyCheck(getLength); - -// Internal implementation of a recursive `flatten` function. -function flatten$1(input, depth, strict, output) { - output = output || []; - if (!depth && depth !== 0) { - depth = Infinity; - } else if (depth <= 0) { - return output.concat(input); - } - var idx = output.length; - for (var i = 0, length = getLength(input); i < length; i++) { - var value = input[i]; - if (isArrayLike(value) && (isArray(value) || isArguments$1(value))) { - // Flatten current level of array or arguments object. - if (depth > 1) { - flatten$1(value, depth - 1, strict, output); - idx = output.length; - } else { - var j = 0, len = value.length; - while (j < len) output[idx++] = value[j++]; - } - } else if (!strict) { - output[idx++] = value; - } - } - return output; -} - -// Bind a number of an object's methods to that object. Remaining arguments -// are the method names to be bound. Useful for ensuring that all callbacks -// defined on an object belong to it. -var bindAll = restArguments(function(obj, keys) { - keys = flatten$1(keys, false, false); - var index = keys.length; - if (index < 1) throw new Error('bindAll must be passed function names'); - while (index--) { - var key = keys[index]; - obj[key] = bind(obj[key], obj); - } - return obj; -}); - -// Memoize an expensive function by storing its results. -function memoize(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = '' + (hasher ? hasher.apply(this, arguments) : key); - if (!has$1(cache, address)) cache[address] = func.apply(this, arguments); - return cache[address]; - }; - memoize.cache = {}; - return memoize; -} - -// Delays a function for the given number of milliseconds, and then calls -// it with the arguments supplied. -var delay = restArguments(function(func, wait, args) { - return setTimeout(function() { - return func.apply(null, args); - }, wait); -}); - -// Defers a function, scheduling it to run after the current call stack has -// cleared. -var defer = partial(delay, _$1, 1); - -// Returns a function, that, when invoked, will only be triggered at most once -// during a given window of time. Normally, the throttled function will run -// as much as it can, without ever going more than once per `wait` duration; -// but if you'd like to disable the execution on the leading edge, pass -// `{leading: false}`. To disable execution on the trailing edge, ditto. -function throttle(func, wait, options) { - var timeout, context, args, result; - var previous = 0; - if (!options) options = {}; - - var later = function() { - previous = options.leading === false ? 0 : now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }; - - var throttled = function() { - var _now = now(); - if (!previous && options.leading === false) previous = _now; - var remaining = wait - (_now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = _now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; - - throttled.cancel = function() { - clearTimeout(timeout); - previous = 0; - timeout = context = args = null; - }; - - return throttled; -} - -// When a sequence of calls of the returned function ends, the argument -// function is triggered. The end of a sequence is defined by the `wait` -// parameter. If `immediate` is passed, the argument function will be -// triggered at the beginning of the sequence instead of at the end. -function debounce(func, wait, immediate) { - var timeout, previous, args, result, context; - - var later = function() { - var passed = now() - previous; - if (wait > passed) { - timeout = setTimeout(later, wait - passed); - } else { - timeout = null; - if (!immediate) result = func.apply(context, args); - // This check is needed because `func` can recursively invoke `debounced`. - if (!timeout) args = context = null; - } - }; - - var debounced = restArguments(function(_args) { - context = this; - args = _args; - previous = now(); - if (!timeout) { - timeout = setTimeout(later, wait); - if (immediate) result = func.apply(context, args); - } - return result; - }); - - debounced.cancel = function() { - clearTimeout(timeout); - timeout = args = context = null; - }; - - return debounced; -} - -// Returns the first function passed as an argument to the second, -// allowing you to adjust arguments, run code before and after, and -// conditionally execute the original function. -function wrap(func, wrapper) { - return partial(wrapper, func); -} - -// Returns a negated version of the passed-in predicate. -function negate(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; -} - -// Returns a function that is the composition of a list of functions, each -// consuming the return value of the function that follows. -function compose() { - var args = arguments; - var start = args.length - 1; - return function() { - var i = start; - var result = args[start].apply(this, arguments); - while (i--) result = args[i].call(this, result); - return result; - }; -} - -// Returns a function that will only be executed on and after the Nth call. -function after(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; -} - -// Returns a function that will only be executed up to (but not including) the -// Nth call. -function before(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } - if (times <= 1) func = null; - return memo; - }; -} - -// Returns a function that will be executed at most one time, no matter how -// often you call it. Useful for lazy initialization. -var once = partial(before, 2); - -// Returns the first key on an object that passes a truth test. -function findKey(obj, predicate, context) { - predicate = cb(predicate, context); - var _keys = keys(obj), key; - for (var i = 0, length = _keys.length; i < length; i++) { - key = _keys[i]; - if (predicate(obj[key], key, obj)) return key; - } -} - -// Internal function to generate `_.findIndex` and `_.findLastIndex`. -function createPredicateIndexFinder(dir) { - return function(array, predicate, context) { - predicate = cb(predicate, context); - var length = getLength(array); - var index = dir > 0 ? 0 : length - 1; - for (; index >= 0 && index < length; index += dir) { - if (predicate(array[index], index, array)) return index; - } - return -1; - }; -} - -// Returns the first index on an array-like that passes a truth test. -var findIndex = createPredicateIndexFinder(1); - -// Returns the last index on an array-like that passes a truth test. -var findLastIndex = createPredicateIndexFinder(-1); - -// Use a comparator function to figure out the smallest index at which -// an object should be inserted so as to maintain order. Uses binary search. -function sortedIndex(array, obj, iteratee, context) { - iteratee = cb(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = getLength(array); - while (low < high) { - var mid = Math.floor((low + high) / 2); - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; -} - -// Internal function to generate the `_.indexOf` and `_.lastIndexOf` functions. -function createIndexFinder(dir, predicateFind, sortedIndex) { - return function(array, item, idx) { - var i = 0, length = getLength(array); - if (typeof idx == 'number') { - if (dir > 0) { - i = idx >= 0 ? idx : Math.max(idx + length, i); - } else { - length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; - } - } else if (sortedIndex && idx && length) { - idx = sortedIndex(array, item); - return array[idx] === item ? idx : -1; - } - if (item !== item) { - idx = predicateFind(slice.call(array, i, length), isNaN$1); - return idx >= 0 ? idx + i : -1; - } - for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { - if (array[idx] === item) return idx; - } - return -1; - }; -} - -// Return the position of the first occurrence of an item in an array, -// or -1 if the item is not included in the array. -// If the array is large and already in sort order, pass `true` -// for **isSorted** to use binary search. -var indexOf = createIndexFinder(1, findIndex, sortedIndex); - -// Return the position of the last occurrence of an item in an array, -// or -1 if the item is not included in the array. -var lastIndexOf = createIndexFinder(-1, findLastIndex); - -// Return the first value which passes a truth test. -function find(obj, predicate, context) { - var keyFinder = isArrayLike(obj) ? findIndex : findKey; - var key = keyFinder(obj, predicate, context); - if (key !== void 0 && key !== -1) return obj[key]; -} - -// Convenience version of a common use case of `_.find`: getting the first -// object containing specific `key:value` pairs. -function findWhere(obj, attrs) { - return find(obj, matcher(attrs)); -} - -// The cornerstone for collection functions, an `each` -// implementation, aka `forEach`. -// Handles raw objects in addition to array-likes. Treats all -// sparse array-likes as if they were dense. -function each(obj, iteratee, context) { - iteratee = optimizeCb(iteratee, context); - var i, length; - if (isArrayLike(obj)) { - for (i = 0, length = obj.length; i < length; i++) { - iteratee(obj[i], i, obj); - } - } else { - var _keys = keys(obj); - for (i = 0, length = _keys.length; i < length; i++) { - iteratee(obj[_keys[i]], _keys[i], obj); - } - } - return obj; -} - -// Return the results of applying the iteratee to each element. -function map(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var _keys = !isArrayLike(obj) && keys(obj), - length = (_keys || obj).length, - results = Array(length); - for (var index = 0; index < length; index++) { - var currentKey = _keys ? _keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); - } - return results; -} - -// Internal helper to create a reducing function, iterating left or right. -function createReduce(dir) { - // Wrap code that reassigns argument variables in a separate function than - // the one that accesses `arguments.length` to avoid a perf hit. (#1991) - var reducer = function(obj, iteratee, memo, initial) { - var _keys = !isArrayLike(obj) && keys(obj), - length = (_keys || obj).length, - index = dir > 0 ? 0 : length - 1; - if (!initial) { - memo = obj[_keys ? _keys[index] : index]; - index += dir; - } - for (; index >= 0 && index < length; index += dir) { - var currentKey = _keys ? _keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; - - return function(obj, iteratee, memo, context) { - var initial = arguments.length >= 3; - return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial); - }; -} - -// **Reduce** builds up a single result from a list of values, aka `inject`, -// or `foldl`. -var reduce = createReduce(1); - -// The right-associative version of reduce, also known as `foldr`. -var reduceRight = createReduce(-1); - -// Return all the elements that pass a truth test. -function filter(obj, predicate, context) { - var results = []; - predicate = cb(predicate, context); - each(obj, function(value, index, list) { - if (predicate(value, index, list)) results.push(value); - }); - return results; -} - -// Return all the elements for which a truth test fails. -function reject(obj, predicate, context) { - return filter(obj, negate(cb(predicate)), context); -} - -// Determine whether all of the elements pass a truth test. -function every(obj, predicate, context) { - predicate = cb(predicate, context); - var _keys = !isArrayLike(obj) && keys(obj), - length = (_keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = _keys ? _keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) return false; - } - return true; -} - -// Determine if at least one element in the object passes a truth test. -function some(obj, predicate, context) { - predicate = cb(predicate, context); - var _keys = !isArrayLike(obj) && keys(obj), - length = (_keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = _keys ? _keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) return true; - } - return false; -} - -// Determine if the array or object contains a given item (using `===`). -function contains(obj, item, fromIndex, guard) { - if (!isArrayLike(obj)) obj = values(obj); - if (typeof fromIndex != 'number' || guard) fromIndex = 0; - return indexOf(obj, item, fromIndex) >= 0; -} - -// Invoke a method (with arguments) on every item in a collection. -var invoke = restArguments(function(obj, path, args) { - var contextPath, func; - if (isFunction$1(path)) { - func = path; - } else { - path = toPath(path); - contextPath = path.slice(0, -1); - path = path[path.length - 1]; - } - return map(obj, function(context) { - var method = func; - if (!method) { - if (contextPath && contextPath.length) { - context = deepGet(context, contextPath); - } - if (context == null) return void 0; - method = context[path]; - } - return method == null ? method : method.apply(context, args); - }); -}); - -// Convenience version of a common use case of `_.map`: fetching a property. -function pluck(obj, key) { - return map(obj, property(key)); -} - -// Convenience version of a common use case of `_.filter`: selecting only -// objects containing specific `key:value` pairs. -function where(obj, attrs) { - return filter(obj, matcher(attrs)); -} - -// Return the maximum element (or element-based computation). -function max(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, - value, computed; - if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null)) { - obj = isArrayLike(obj) ? obj : values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value != null && value > result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - each(obj, function(v, index, list) { - computed = iteratee(v, index, list); - if (computed > lastComputed || (computed === -Infinity && result === -Infinity)) { - result = v; - lastComputed = computed; - } - }); - } - return result; -} - -// Return the minimum element (or element-based computation). -function min(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, - value, computed; - if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null)) { - obj = isArrayLike(obj) ? obj : values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value != null && value < result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - each(obj, function(v, index, list) { - computed = iteratee(v, index, list); - if (computed < lastComputed || (computed === Infinity && result === Infinity)) { - result = v; - lastComputed = computed; - } - }); - } - return result; -} - -// Safely create a real, live array from anything iterable. -var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g; -function toArray(obj) { - if (!obj) return []; - if (isArray(obj)) return slice.call(obj); - if (isString(obj)) { - // Keep surrogate pair characters together. - return obj.match(reStrSymbol); - } - if (isArrayLike(obj)) return map(obj, identity); - return values(obj); -} - -// Sample **n** random values from a collection using the modern version of the -// [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle). -// If **n** is not specified, returns a single random element. -// The internal `guard` argument allows it to work with `_.map`. -function sample(obj, n, guard) { - if (n == null || guard) { - if (!isArrayLike(obj)) obj = values(obj); - return obj[random(obj.length - 1)]; - } - var sample = toArray(obj); - var length = getLength(sample); - n = Math.max(Math.min(n, length), 0); - var last = length - 1; - for (var index = 0; index < n; index++) { - var rand = random(index, last); - var temp = sample[index]; - sample[index] = sample[rand]; - sample[rand] = temp; - } - return sample.slice(0, n); -} - -// Shuffle a collection. -function shuffle(obj) { - return sample(obj, Infinity); -} - -// Sort the object's values by a criterion produced by an iteratee. -function sortBy(obj, iteratee, context) { - var index = 0; - iteratee = cb(iteratee, context); - return pluck(map(obj, function(value, key, list) { - return { - value: value, - index: index++, - criteria: iteratee(value, key, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index - right.index; - }), 'value'); -} - -// An internal function used for aggregate "group by" operations. -function group(behavior, partition) { - return function(obj, iteratee, context) { - var result = partition ? [[], []] : {}; - iteratee = cb(iteratee, context); - each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); - return result; - }; -} - -// Groups the object's values by a criterion. Pass either a string attribute -// to group by, or a function that returns the criterion. -var groupBy = group(function(result, value, key) { - if (has$1(result, key)) result[key].push(value); else result[key] = [value]; -}); - -// Indexes the object's values by a criterion, similar to `_.groupBy`, but for -// when you know that your index values will be unique. -var indexBy = group(function(result, value, key) { - result[key] = value; -}); - -// Counts instances of an object that group by a certain criterion. Pass -// either a string attribute to count by, or a function that returns the -// criterion. -var countBy = group(function(result, value, key) { - if (has$1(result, key)) result[key]++; else result[key] = 1; -}); - -// Split a collection into two arrays: one whose elements all pass the given -// truth test, and one whose elements all do not pass the truth test. -var partition = group(function(result, value, pass) { - result[pass ? 0 : 1].push(value); -}, true); - -// Return the number of elements in a collection. -function size(obj) { - if (obj == null) return 0; - return isArrayLike(obj) ? obj.length : keys(obj).length; -} - -// Internal `_.pick` helper function to determine whether `key` is an enumerable -// property name of `obj`. -function keyInObj(value, key, obj) { - return key in obj; -} - -// Return a copy of the object only containing the allowed properties. -var pick = restArguments(function(obj, keys) { - var result = {}, iteratee = keys[0]; - if (obj == null) return result; - if (isFunction$1(iteratee)) { - if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]); - keys = allKeys(obj); - } else { - iteratee = keyInObj; - keys = flatten$1(keys, false, false); - obj = Object(obj); - } - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i]; - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; - } - return result; -}); - -// Return a copy of the object without the disallowed properties. -var omit = restArguments(function(obj, keys) { - var iteratee = keys[0], context; - if (isFunction$1(iteratee)) { - iteratee = negate(iteratee); - if (keys.length > 1) context = keys[1]; - } else { - keys = map(flatten$1(keys, false, false), String); - iteratee = function(value, key) { - return !contains(keys, key); - }; - } - return pick(obj, iteratee, context); -}); - -// Returns everything but the last entry of the array. Especially useful on -// the arguments object. Passing **n** will return all the values in -// the array, excluding the last N. -function initial(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); -} - -// Get the first element of an array. Passing **n** will return the first N -// values in the array. The **guard** check allows it to work with `_.map`. -function first(array, n, guard) { - if (array == null || array.length < 1) return n == null || guard ? void 0 : []; - if (n == null || guard) return array[0]; - return initial(array, array.length - n); -} - -// Returns everything but the first entry of the `array`. Especially useful on -// the `arguments` object. Passing an **n** will return the rest N values in the -// `array`. -function rest(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); -} - -// Get the last element of an array. Passing **n** will return the last N -// values in the array. -function last(array, n, guard) { - if (array == null || array.length < 1) return n == null || guard ? void 0 : []; - if (n == null || guard) return array[array.length - 1]; - return rest(array, Math.max(0, array.length - n)); -} - -// Trim out all falsy values from an array. -function compact(array) { - return filter(array, Boolean); -} - -// Flatten out an array, either recursively (by default), or up to `depth`. -// Passing `true` or `false` as `depth` means `1` or `Infinity`, respectively. -function flatten(array, depth) { - return flatten$1(array, depth, false); -} - -// Take the difference between one array and a number of other arrays. -// Only the elements present in just the first array will remain. -var difference = restArguments(function(array, rest) { - rest = flatten$1(rest, true, true); - return filter(array, function(value){ - return !contains(rest, value); - }); -}); - -// Return a version of the array that does not contain the specified value(s). -var without = restArguments(function(array, otherArrays) { - return difference(array, otherArrays); -}); - -// Produce a duplicate-free version of the array. If the array has already -// been sorted, you have the option of using a faster algorithm. -// The faster algorithm will not work with an iteratee if the iteratee -// is not a one-to-one function, so providing an iteratee will disable -// the faster algorithm. -function uniq(array, isSorted, iteratee, context) { - if (!isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; - } - if (iteratee != null) iteratee = cb(iteratee, context); - var result = []; - var seen = []; - for (var i = 0, length = getLength(array); i < length; i++) { - var value = array[i], - computed = iteratee ? iteratee(value, i, array) : value; - if (isSorted && !iteratee) { - if (!i || seen !== computed) result.push(value); - seen = computed; - } else if (iteratee) { - if (!contains(seen, computed)) { - seen.push(computed); - result.push(value); - } - } else if (!contains(result, value)) { - result.push(value); - } - } - return result; -} - -// Produce an array that contains the union: each distinct element from all of -// the passed-in arrays. -var union = restArguments(function(arrays) { - return uniq(flatten$1(arrays, true, true)); -}); - -// Produce an array that contains every item shared between all the -// passed-in arrays. -function intersection(array) { - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = getLength(array); i < length; i++) { - var item = array[i]; - if (contains(result, item)) continue; - var j; - for (j = 1; j < argsLength; j++) { - if (!contains(arguments[j], item)) break; - } - if (j === argsLength) result.push(item); - } - return result; -} - -// Complement of zip. Unzip accepts an array of arrays and groups -// each array's elements on shared indices. -function unzip(array) { - var length = (array && max(array, getLength).length) || 0; - var result = Array(length); - - for (var index = 0; index < length; index++) { - result[index] = pluck(array, index); - } - return result; -} - -// Zip together multiple lists into a single array -- elements that share -// an index go together. -var zip = restArguments(unzip); - -// Converts lists into objects. Pass either a single array of `[key, value]` -// pairs, or two parallel arrays of the same length -- one of keys, and one of -// the corresponding values. Passing by pairs is the reverse of `_.pairs`. -function object(list, values) { - var result = {}; - for (var i = 0, length = getLength(list); i < length; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; -} - -// Generate an integer Array containing an arithmetic progression. A port of -// the native Python `range()` function. See -// [the Python documentation](https://docs.python.org/library/functions.html#range). -function range(start, stop, step) { - if (stop == null) { - stop = start || 0; - start = 0; - } - if (!step) { - step = stop < start ? -1 : 1; - } - - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; - } - - return range; -} - -// Chunk a single array into multiple arrays, each containing `count` or fewer -// items. -function chunk(array, count) { - if (count == null || count < 1) return []; - var result = []; - var i = 0, length = array.length; - while (i < length) { - result.push(slice.call(array, i, i += count)); - } - return result; -} - -// Helper function to continue chaining intermediate results. -function chainResult(instance, obj) { - return instance._chain ? _$1(obj).chain() : obj; -} - -// Add your own custom functions to the Underscore object. -function mixin(obj) { - each(functions(obj), function(name) { - var func = _$1[name] = obj[name]; - _$1.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return chainResult(this, func.apply(_$1, args)); - }; - }); - return _$1; -} - -// Add all mutator `Array` functions to the wrapper. -each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _$1.prototype[name] = function() { - var obj = this._wrapped; - if (obj != null) { - method.apply(obj, arguments); - if ((name === 'shift' || name === 'splice') && obj.length === 0) { - delete obj[0]; - } - } - return chainResult(this, obj); - }; -}); - -// Add all accessor `Array` functions to the wrapper. -each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _$1.prototype[name] = function() { - var obj = this._wrapped; - if (obj != null) obj = method.apply(obj, arguments); - return chainResult(this, obj); - }; -}); - -// Named Exports - -var allExports = { - __proto__: null, - VERSION: VERSION, - restArguments: restArguments, - isObject: isObject, - isNull: isNull, - isUndefined: isUndefined, - isBoolean: isBoolean, - isElement: isElement, - isString: isString, - isNumber: isNumber, - isDate: isDate, - isRegExp: isRegExp, - isError: isError, - isSymbol: isSymbol, - isArrayBuffer: isArrayBuffer, - isDataView: isDataView$1, - isArray: isArray, - isFunction: isFunction$1, - isArguments: isArguments$1, - isFinite: isFinite$1, - isNaN: isNaN$1, - isTypedArray: isTypedArray$1, - isEmpty: isEmpty, - isMatch: isMatch, - isEqual: isEqual, - isMap: isMap, - isWeakMap: isWeakMap, - isSet: isSet, - isWeakSet: isWeakSet, - keys: keys, - allKeys: allKeys, - values: values, - pairs: pairs, - invert: invert, - functions: functions, - methods: functions, - extend: extend, - extendOwn: extendOwn, - assign: extendOwn, - defaults: defaults, - create: create, - clone: clone, - tap: tap, - get: get, - has: has, - mapObject: mapObject, - identity: identity, - constant: constant, - noop: noop, - toPath: toPath$1, - property: property, - propertyOf: propertyOf, - matcher: matcher, - matches: matcher, - times: times, - random: random, - now: now, - escape: _escape, - unescape: _unescape, - templateSettings: templateSettings, - template: template, - result: result, - uniqueId: uniqueId, - chain: chain, - iteratee: iteratee, - partial: partial, - bind: bind, - bindAll: bindAll, - memoize: memoize, - delay: delay, - defer: defer, - throttle: throttle, - debounce: debounce, - wrap: wrap, - negate: negate, - compose: compose, - after: after, - before: before, - once: once, - findKey: findKey, - findIndex: findIndex, - findLastIndex: findLastIndex, - sortedIndex: sortedIndex, - indexOf: indexOf, - lastIndexOf: lastIndexOf, - find: find, - detect: find, - findWhere: findWhere, - each: each, - forEach: each, - map: map, - collect: map, - reduce: reduce, - foldl: reduce, - inject: reduce, - reduceRight: reduceRight, - foldr: reduceRight, - filter: filter, - select: filter, - reject: reject, - every: every, - all: every, - some: some, - any: some, - contains: contains, - includes: contains, - include: contains, - invoke: invoke, - pluck: pluck, - where: where, - max: max, - min: min, - shuffle: shuffle, - sample: sample, - sortBy: sortBy, - groupBy: groupBy, - indexBy: indexBy, - countBy: countBy, - partition: partition, - toArray: toArray, - size: size, - pick: pick, - omit: omit, - first: first, - head: first, - take: first, - initial: initial, - last: last, - rest: rest, - tail: rest, - drop: rest, - compact: compact, - flatten: flatten, - without: without, - uniq: uniq, - unique: uniq, - union: union, - intersection: intersection, - difference: difference, - unzip: unzip, - transpose: unzip, - zip: zip, - object: object, - range: range, - chunk: chunk, - mixin: mixin, - 'default': _$1 -}; - -// Default Export - -// Add all of the Underscore functions to the wrapper object. -var _ = mixin(allExports); -// Legacy Node.js API. -_._ = _; - -exports.VERSION = VERSION; -exports._ = _; -exports._escape = _escape; -exports._unescape = _unescape; -exports.after = after; -exports.allKeys = allKeys; -exports.before = before; -exports.bind = bind; -exports.bindAll = bindAll; -exports.chain = chain; -exports.chunk = chunk; -exports.clone = clone; -exports.compact = compact; -exports.compose = compose; -exports.constant = constant; -exports.contains = contains; -exports.countBy = countBy; -exports.create = create; -exports.debounce = debounce; -exports.defaults = defaults; -exports.defer = defer; -exports.delay = delay; -exports.difference = difference; -exports.each = each; -exports.every = every; -exports.extend = extend; -exports.extendOwn = extendOwn; -exports.filter = filter; -exports.find = find; -exports.findIndex = findIndex; -exports.findKey = findKey; -exports.findLastIndex = findLastIndex; -exports.findWhere = findWhere; -exports.first = first; -exports.flatten = flatten; -exports.functions = functions; -exports.get = get; -exports.groupBy = groupBy; -exports.has = has; -exports.identity = identity; -exports.indexBy = indexBy; -exports.indexOf = indexOf; -exports.initial = initial; -exports.intersection = intersection; -exports.invert = invert; -exports.invoke = invoke; -exports.isArguments = isArguments$1; -exports.isArray = isArray; -exports.isArrayBuffer = isArrayBuffer; -exports.isBoolean = isBoolean; -exports.isDataView = isDataView$1; -exports.isDate = isDate; -exports.isElement = isElement; -exports.isEmpty = isEmpty; -exports.isEqual = isEqual; -exports.isError = isError; -exports.isFinite = isFinite$1; -exports.isFunction = isFunction$1; -exports.isMap = isMap; -exports.isMatch = isMatch; -exports.isNaN = isNaN$1; -exports.isNull = isNull; -exports.isNumber = isNumber; -exports.isObject = isObject; -exports.isRegExp = isRegExp; -exports.isSet = isSet; -exports.isString = isString; -exports.isSymbol = isSymbol; -exports.isTypedArray = isTypedArray$1; -exports.isUndefined = isUndefined; -exports.isWeakMap = isWeakMap; -exports.isWeakSet = isWeakSet; -exports.iteratee = iteratee; -exports.keys = keys; -exports.last = last; -exports.lastIndexOf = lastIndexOf; -exports.map = map; -exports.mapObject = mapObject; -exports.matcher = matcher; -exports.max = max; -exports.memoize = memoize; -exports.min = min; -exports.mixin = mixin; -exports.negate = negate; -exports.noop = noop; -exports.now = now; -exports.object = object; -exports.omit = omit; -exports.once = once; -exports.pairs = pairs; -exports.partial = partial; -exports.partition = partition; -exports.pick = pick; -exports.pluck = pluck; -exports.property = property; -exports.propertyOf = propertyOf; -exports.random = random; -exports.range = range; -exports.reduce = reduce; -exports.reduceRight = reduceRight; -exports.reject = reject; -exports.rest = rest; -exports.restArguments = restArguments; -exports.result = result; -exports.sample = sample; -exports.shuffle = shuffle; -exports.size = size; -exports.some = some; -exports.sortBy = sortBy; -exports.sortedIndex = sortedIndex; -exports.tap = tap; -exports.template = template; -exports.templateSettings = templateSettings; -exports.throttle = throttle; -exports.times = times; -exports.toArray = toArray; -exports.toPath = toPath$1; -exports.union = union; -exports.uniq = uniq; -exports.uniqueId = uniqueId; -exports.unzip = unzip; -exports.values = values; -exports.where = where; -exports.without = without; -exports.wrap = wrap; -exports.zip = zip; -//# sourceMappingURL=underscore-node-f.cjs.map - - -/***/ }), - -/***/ 5067: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -// Underscore.js 1.13.6 -// https://underscorejs.org -// (c) 2009-2022 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -var underscoreNodeF = __nccwpck_require__(6717); - - - -module.exports = underscoreNodeF._; -//# sourceMappingURL=underscore-node.cjs.map - - /***/ }), /***/ 1907: @@ -14322,7 +12171,7 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"] /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __nccwpck_require__(8441); +/******/ var __webpack_exports__ = __nccwpck_require__(2137); /******/ module.exports = __webpack_exports__; /******/ /******/ })() diff --git a/.github/actions/javascript/isStagingDeployLocked/isStagingDeployLocked.js b/.github/actions/javascript/isStagingDeployLocked/isStagingDeployLocked.js deleted file mode 100644 index 61714274a307..000000000000 --- a/.github/actions/javascript/isStagingDeployLocked/isStagingDeployLocked.js +++ /dev/null @@ -1,23 +0,0 @@ -const _ = require('underscore'); -const core = require('@actions/core'); -const GithubUtils = require('../../../libs/GithubUtils'); - -const run = function () { - return GithubUtils.getStagingDeployCash() - .then(({labels, number}) => { - console.log(`Found StagingDeployCash with labels: ${_.pluck(labels, 'name')}`); - core.setOutput('IS_LOCKED', _.contains(_.pluck(labels, 'name'), '🔐 LockCashDeploys 🔐')); - core.setOutput('NUMBER', number); - }) - .catch((err) => { - console.warn('No open StagingDeployCash found, continuing...', err); - core.setOutput('IS_LOCKED', false); - core.setOutput('NUMBER', 0); - }); -}; - -if (require.main === module) { - run(); -} - -module.exports = run; diff --git a/.github/actions/javascript/isStagingDeployLocked/isStagingDeployLocked.ts b/.github/actions/javascript/isStagingDeployLocked/isStagingDeployLocked.ts new file mode 100644 index 000000000000..ce19ce62f8af --- /dev/null +++ b/.github/actions/javascript/isStagingDeployLocked/isStagingDeployLocked.ts @@ -0,0 +1,28 @@ +import * as core from '@actions/core'; +import GithubUtils from '@github/libs/GithubUtils'; + +const run = function (): Promise { + return GithubUtils.getStagingDeployCash() + .then(({labels, number}) => { + const labelsNames = labels.map((label) => { + if (typeof label === 'string') { + return ''; + } + return label.name; + }); + console.log(`Found StagingDeployCash with labels: ${JSON.stringify(labelsNames)}`); + core.setOutput('IS_LOCKED', labelsNames.includes('🔐 LockCashDeploys 🔐')); + core.setOutput('NUMBER', number); + }) + .catch((err) => { + console.warn('No open StagingDeployCash found, continuing...', err); + core.setOutput('IS_LOCKED', false); + core.setOutput('NUMBER', 0); + }); +}; + +if (require.main === module) { + run(); +} + +export default run; diff --git a/.github/actions/javascript/markPullRequestsAsDeployed/index.js b/.github/actions/javascript/markPullRequestsAsDeployed/index.js index e43aec749df7..ebd9d8b16098 100644 --- a/.github/actions/javascript/markPullRequestsAsDeployed/index.js +++ b/.github/actions/javascript/markPullRequestsAsDeployed/index.js @@ -11741,6 +11741,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/postTestBuildComment/index.js b/.github/actions/javascript/postTestBuildComment/index.js index 27214d85d18d..09cececf3177 100644 --- a/.github/actions/javascript/postTestBuildComment/index.js +++ b/.github/actions/javascript/postTestBuildComment/index.js @@ -4,111 +4,6 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 2052: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -const _ = __nccwpck_require__(5067); -const core = __nccwpck_require__(2186); -const {context} = __nccwpck_require__(5438); -const CONST = __nccwpck_require__(4097); -const GithubUtils = __nccwpck_require__(9296); - -/** - * @returns {String} - */ -function getTestBuildMessage() { - console.log('Input for android', core.getInput('ANDROID', {required: true})); - const androidSuccess = core.getInput('ANDROID', {required: true}) === 'success'; - const desktopSuccess = core.getInput('DESKTOP', {required: true}) === 'success'; - const iOSSuccess = core.getInput('IOS', {required: true}) === 'success'; - const webSuccess = core.getInput('WEB', {required: true}) === 'success'; - - const androidLink = androidSuccess ? core.getInput('ANDROID_LINK') : '❌ FAILED ❌'; - const desktopLink = desktopSuccess ? core.getInput('DESKTOP_LINK') : '❌ FAILED ❌'; - const iOSLink = iOSSuccess ? core.getInput('IOS_LINK') : '❌ FAILED ❌'; - const webLink = webSuccess ? core.getInput('WEB_LINK') : '❌ FAILED ❌'; - - const androidQRCode = androidSuccess - ? `![Android](https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${androidLink})` - : "The QR code can't be generated, because the android build failed"; - const desktopQRCode = desktopSuccess - ? `![Desktop](https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${desktopLink})` - : "The QR code can't be generated, because the Desktop build failed"; - const iOSQRCode = iOSSuccess ? `![iOS](https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${iOSLink})` : "The QR code can't be generated, because the iOS build failed"; - const webQRCode = webSuccess ? `![Web](https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${webLink})` : "The QR code can't be generated, because the web build failed"; - - const message = `:test_tube::test_tube: Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! :test_tube::test_tube: -| Android :robot: | iOS :apple: | -| ------------- | ------------- | -| ${androidLink} | ${iOSLink} | -| ${androidQRCode} | ${iOSQRCode} | -| Desktop :computer: | Web :spider_web: | -| ${desktopLink} | ${webLink} | -| ${desktopQRCode} | ${webQRCode} | - ---- - -:eyes: [View the workflow run that generated this build](https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}) :eyes: -`; - - return message; -} - -/** - * Comment on a single PR - * - * @param {Number} PR - * @param {String} message - * @returns {Promise} - */ -async function commentPR(PR, message) { - console.log(`Posting test build comment on #${PR}`); - try { - await GithubUtils.createComment(context.repo.repo, PR, message); - console.log(`Comment created on #${PR} successfully 🎉`); - } catch (err) { - console.log(`Unable to write comment on #${PR} 😞`); - core.setFailed(err.message); - } -} - -async function run() { - const PR_NUMBER = core.getInput('PR_NUMBER', {required: true}); - const comments = await GithubUtils.paginate( - GithubUtils.octokit.issues.listComments, - { - owner: CONST.GITHUB_OWNER, - repo: CONST.APP_REPO, - issue_number: PR_NUMBER, - per_page: 100, - }, - (response) => response.data, - ); - const testBuildComment = _.find(comments, (comment) => comment.body.startsWith(':test_tube::test_tube: Use the links below to test this adhoc build')); - if (testBuildComment) { - console.log('Found previous build comment, hiding it', testBuildComment); - await GithubUtils.graphql(` - mutation { - minimizeComment(input: {classifier: OUTDATED, subjectId: "${testBuildComment.node_id}"}) { - minimizedComment { - minimizedReason - } - } - } - `); - } - await commentPR(PR_NUMBER, getTestBuildMessage()); -} - -if (require.main === require.cache[eval('__filename')]) { - run(); -} - -module.exports = run; - - -/***/ }), - /***/ 4097: /***/ ((module) => { @@ -11592,6 +11487,122 @@ function wrappy (fn, cb) { } +/***/ }), + +/***/ 3580: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const core = __importStar(__nccwpck_require__(2186)); +const github_1 = __nccwpck_require__(5438); +const CONST_1 = __importDefault(__nccwpck_require__(4097)); +const GithubUtils_1 = __importDefault(__nccwpck_require__(9296)); +function getTestBuildMessage() { + console.log('Input for android', core.getInput('ANDROID', { required: true })); + const androidSuccess = core.getInput('ANDROID', { required: true }) === 'success'; + const desktopSuccess = core.getInput('DESKTOP', { required: true }) === 'success'; + const iOSSuccess = core.getInput('IOS', { required: true }) === 'success'; + const webSuccess = core.getInput('WEB', { required: true }) === 'success'; + const androidLink = androidSuccess ? core.getInput('ANDROID_LINK') : '❌ FAILED ❌'; + const desktopLink = desktopSuccess ? core.getInput('DESKTOP_LINK') : '❌ FAILED ❌'; + const iOSLink = iOSSuccess ? core.getInput('IOS_LINK') : '❌ FAILED ❌'; + const webLink = webSuccess ? core.getInput('WEB_LINK') : '❌ FAILED ❌'; + const androidQRCode = androidSuccess + ? `![Android](https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${androidLink})` + : "The QR code can't be generated, because the android build failed"; + const desktopQRCode = desktopSuccess + ? `![Desktop](https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${desktopLink})` + : "The QR code can't be generated, because the Desktop build failed"; + const iOSQRCode = iOSSuccess ? `![iOS](https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${iOSLink})` : "The QR code can't be generated, because the iOS build failed"; + const webQRCode = webSuccess ? `![Web](https://api.qrserver.com/v1/create-qr-code/?size=120x120&data=${webLink})` : "The QR code can't be generated, because the web build failed"; + const message = `:test_tube::test_tube: Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! :test_tube::test_tube: +| Android :robot: | iOS :apple: | +| ------------- | ------------- | +| ${androidLink} | ${iOSLink} | +| ${androidQRCode} | ${iOSQRCode} | +| Desktop :computer: | Web :spider_web: | +| ${desktopLink} | ${webLink} | +| ${desktopQRCode} | ${webQRCode} | + +--- + +:eyes: [View the workflow run that generated this build](https://github.com/${github_1.context.repo.owner}/${github_1.context.repo.repo}/actions/runs/${github_1.context.runId}) :eyes: +`; + return message; +} +/** Comment on a single PR */ +async function commentPR(PR, message) { + console.log(`Posting test build comment on #${PR}`); + try { + await GithubUtils_1.default.createComment(github_1.context.repo.repo, PR, message); + console.log(`Comment created on #${PR} successfully 🎉`); + } + catch (err) { + console.log(`Unable to write comment on #${PR} 😞`); + if (err instanceof Error) { + core.setFailed(err.message); + } + } +} +async function run() { + const PR_NUMBER = Number(core.getInput('PR_NUMBER', { required: true })); + const comments = await GithubUtils_1.default.paginate(GithubUtils_1.default.octokit.issues.listComments, { + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + // eslint-disable-next-line @typescript-eslint/naming-convention + issue_number: PR_NUMBER, + // eslint-disable-next-line @typescript-eslint/naming-convention + per_page: 100, + }, (response) => response.data); + const testBuildComment = comments.find((comment) => comment.body?.startsWith(':test_tube::test_tube: Use the links below to test this adhoc build')); + if (testBuildComment) { + console.log('Found previous build comment, hiding it', testBuildComment); + await GithubUtils_1.default.graphql(` + mutation { + minimizeComment(input: {classifier: OUTDATED, subjectId: "${testBuildComment.node_id}"}) { + minimizedComment { + minimizedReason + } + } + } + `); + } + await commentPR(PR_NUMBER, getTestBuildMessage()); +} +if (require.main === require.cache[eval('__filename')]) { + run(); +} +exports["default"] = run; + + /***/ }), /***/ 9296: @@ -11648,6 +11659,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * @@ -12206,2189 +12218,6 @@ module.exports = require("util"); "use strict"; module.exports = require("zlib"); -/***/ }), - -/***/ 6717: -/***/ ((__unused_webpack_module, exports) => { - -// Underscore.js 1.13.6 -// https://underscorejs.org -// (c) 2009-2022 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -Object.defineProperty(exports, "__esModule", ({ value: true })); - -// Current version. -var VERSION = '1.13.6'; - -// Establish the root object, `window` (`self`) in the browser, `global` -// on the server, or `this` in some virtual machines. We use `self` -// instead of `window` for `WebWorker` support. -var root = (typeof self == 'object' && self.self === self && self) || - (typeof global == 'object' && global.global === global && global) || - Function('return this')() || - {}; - -// Save bytes in the minified (but not gzipped) version: -var ArrayProto = Array.prototype, ObjProto = Object.prototype; -var SymbolProto = typeof Symbol !== 'undefined' ? Symbol.prototype : null; - -// Create quick reference variables for speed access to core prototypes. -var push = ArrayProto.push, - slice = ArrayProto.slice, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; - -// Modern feature detection. -var supportsArrayBuffer = typeof ArrayBuffer !== 'undefined', - supportsDataView = typeof DataView !== 'undefined'; - -// All **ECMAScript 5+** native function implementations that we hope to use -// are declared here. -var nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeCreate = Object.create, - nativeIsView = supportsArrayBuffer && ArrayBuffer.isView; - -// Create references to these builtin functions because we override them. -var _isNaN = isNaN, - _isFinite = isFinite; - -// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. -var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); -var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', - 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; - -// The largest integer that can be represented exactly. -var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; - -// Some functions take a variable number of arguments, or a few expected -// arguments at the beginning and then a variable number of values to operate -// on. This helper accumulates all remaining arguments past the function’s -// argument length (or an explicit `startIndex`), into an array that becomes -// the last argument. Similar to ES6’s "rest parameter". -function restArguments(func, startIndex) { - startIndex = startIndex == null ? func.length - 1 : +startIndex; - return function() { - var length = Math.max(arguments.length - startIndex, 0), - rest = Array(length), - index = 0; - for (; index < length; index++) { - rest[index] = arguments[index + startIndex]; - } - switch (startIndex) { - case 0: return func.call(this, rest); - case 1: return func.call(this, arguments[0], rest); - case 2: return func.call(this, arguments[0], arguments[1], rest); - } - var args = Array(startIndex + 1); - for (index = 0; index < startIndex; index++) { - args[index] = arguments[index]; - } - args[startIndex] = rest; - return func.apply(this, args); - }; -} - -// Is a given variable an object? -function isObject(obj) { - var type = typeof obj; - return type === 'function' || (type === 'object' && !!obj); -} - -// Is a given value equal to null? -function isNull(obj) { - return obj === null; -} - -// Is a given variable undefined? -function isUndefined(obj) { - return obj === void 0; -} - -// Is a given value a boolean? -function isBoolean(obj) { - return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; -} - -// Is a given value a DOM element? -function isElement(obj) { - return !!(obj && obj.nodeType === 1); -} - -// Internal function for creating a `toString`-based type tester. -function tagTester(name) { - var tag = '[object ' + name + ']'; - return function(obj) { - return toString.call(obj) === tag; - }; -} - -var isString = tagTester('String'); - -var isNumber = tagTester('Number'); - -var isDate = tagTester('Date'); - -var isRegExp = tagTester('RegExp'); - -var isError = tagTester('Error'); - -var isSymbol = tagTester('Symbol'); - -var isArrayBuffer = tagTester('ArrayBuffer'); - -var isFunction = tagTester('Function'); - -// Optimize `isFunction` if appropriate. Work around some `typeof` bugs in old -// v8, IE 11 (#1621), Safari 8 (#1929), and PhantomJS (#2236). -var nodelist = root.document && root.document.childNodes; -if ( true && typeof Int8Array != 'object' && typeof nodelist != 'function') { - isFunction = function(obj) { - return typeof obj == 'function' || false; - }; -} - -var isFunction$1 = isFunction; - -var hasObjectTag = tagTester('Object'); - -// In IE 10 - Edge 13, `DataView` has string tag `'[object Object]'`. -// In IE 11, the most common among them, this problem also applies to -// `Map`, `WeakMap` and `Set`. -var hasStringTagBug = ( - supportsDataView && hasObjectTag(new DataView(new ArrayBuffer(8))) - ), - isIE11 = (typeof Map !== 'undefined' && hasObjectTag(new Map)); - -var isDataView = tagTester('DataView'); - -// In IE 10 - Edge 13, we need a different heuristic -// to determine whether an object is a `DataView`. -function ie10IsDataView(obj) { - return obj != null && isFunction$1(obj.getInt8) && isArrayBuffer(obj.buffer); -} - -var isDataView$1 = (hasStringTagBug ? ie10IsDataView : isDataView); - -// Is a given value an array? -// Delegates to ECMA5's native `Array.isArray`. -var isArray = nativeIsArray || tagTester('Array'); - -// Internal function to check whether `key` is an own property name of `obj`. -function has$1(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); -} - -var isArguments = tagTester('Arguments'); - -// Define a fallback version of the method in browsers (ahem, IE < 9), where -// there isn't any inspectable "Arguments" type. -(function() { - if (!isArguments(arguments)) { - isArguments = function(obj) { - return has$1(obj, 'callee'); - }; - } -}()); - -var isArguments$1 = isArguments; - -// Is a given object a finite number? -function isFinite$1(obj) { - return !isSymbol(obj) && _isFinite(obj) && !isNaN(parseFloat(obj)); -} - -// Is the given value `NaN`? -function isNaN$1(obj) { - return isNumber(obj) && _isNaN(obj); -} - -// Predicate-generating function. Often useful outside of Underscore. -function constant(value) { - return function() { - return value; - }; -} - -// Common internal logic for `isArrayLike` and `isBufferLike`. -function createSizePropertyCheck(getSizeProperty) { - return function(collection) { - var sizeProperty = getSizeProperty(collection); - return typeof sizeProperty == 'number' && sizeProperty >= 0 && sizeProperty <= MAX_ARRAY_INDEX; - } -} - -// Internal helper to generate a function to obtain property `key` from `obj`. -function shallowProperty(key) { - return function(obj) { - return obj == null ? void 0 : obj[key]; - }; -} - -// Internal helper to obtain the `byteLength` property of an object. -var getByteLength = shallowProperty('byteLength'); - -// Internal helper to determine whether we should spend extensive checks against -// `ArrayBuffer` et al. -var isBufferLike = createSizePropertyCheck(getByteLength); - -// Is a given value a typed array? -var typedArrayPattern = /\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\]/; -function isTypedArray(obj) { - // `ArrayBuffer.isView` is the most future-proof, so use it when available. - // Otherwise, fall back on the above regular expression. - return nativeIsView ? (nativeIsView(obj) && !isDataView$1(obj)) : - isBufferLike(obj) && typedArrayPattern.test(toString.call(obj)); -} - -var isTypedArray$1 = supportsArrayBuffer ? isTypedArray : constant(false); - -// Internal helper to obtain the `length` property of an object. -var getLength = shallowProperty('length'); - -// Internal helper to create a simple lookup structure. -// `collectNonEnumProps` used to depend on `_.contains`, but this led to -// circular imports. `emulatedSet` is a one-off solution that only works for -// arrays of strings. -function emulatedSet(keys) { - var hash = {}; - for (var l = keys.length, i = 0; i < l; ++i) hash[keys[i]] = true; - return { - contains: function(key) { return hash[key] === true; }, - push: function(key) { - hash[key] = true; - return keys.push(key); - } - }; -} - -// Internal helper. Checks `keys` for the presence of keys in IE < 9 that won't -// be iterated by `for key in ...` and thus missed. Extends `keys` in place if -// needed. -function collectNonEnumProps(obj, keys) { - keys = emulatedSet(keys); - var nonEnumIdx = nonEnumerableProps.length; - var constructor = obj.constructor; - var proto = (isFunction$1(constructor) && constructor.prototype) || ObjProto; - - // Constructor is a special case. - var prop = 'constructor'; - if (has$1(obj, prop) && !keys.contains(prop)) keys.push(prop); - - while (nonEnumIdx--) { - prop = nonEnumerableProps[nonEnumIdx]; - if (prop in obj && obj[prop] !== proto[prop] && !keys.contains(prop)) { - keys.push(prop); - } - } -} - -// Retrieve the names of an object's own properties. -// Delegates to **ECMAScript 5**'s native `Object.keys`. -function keys(obj) { - if (!isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (has$1(obj, key)) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; -} - -// Is a given array, string, or object empty? -// An "empty" object has no enumerable own-properties. -function isEmpty(obj) { - if (obj == null) return true; - // Skip the more expensive `toString`-based type checks if `obj` has no - // `.length`. - var length = getLength(obj); - if (typeof length == 'number' && ( - isArray(obj) || isString(obj) || isArguments$1(obj) - )) return length === 0; - return getLength(keys(obj)) === 0; -} - -// Returns whether an object has a given set of `key:value` pairs. -function isMatch(object, attrs) { - var _keys = keys(attrs), length = _keys.length; - if (object == null) return !length; - var obj = Object(object); - for (var i = 0; i < length; i++) { - var key = _keys[i]; - if (attrs[key] !== obj[key] || !(key in obj)) return false; - } - return true; -} - -// If Underscore is called as a function, it returns a wrapped object that can -// be used OO-style. This wrapper holds altered versions of all functions added -// through `_.mixin`. Wrapped objects may be chained. -function _$1(obj) { - if (obj instanceof _$1) return obj; - if (!(this instanceof _$1)) return new _$1(obj); - this._wrapped = obj; -} - -_$1.VERSION = VERSION; - -// Extracts the result from a wrapped and chained object. -_$1.prototype.value = function() { - return this._wrapped; -}; - -// Provide unwrapping proxies for some methods used in engine operations -// such as arithmetic and JSON stringification. -_$1.prototype.valueOf = _$1.prototype.toJSON = _$1.prototype.value; - -_$1.prototype.toString = function() { - return String(this._wrapped); -}; - -// Internal function to wrap or shallow-copy an ArrayBuffer, -// typed array or DataView to a new view, reusing the buffer. -function toBufferView(bufferSource) { - return new Uint8Array( - bufferSource.buffer || bufferSource, - bufferSource.byteOffset || 0, - getByteLength(bufferSource) - ); -} - -// We use this string twice, so give it a name for minification. -var tagDataView = '[object DataView]'; - -// Internal recursive comparison function for `_.isEqual`. -function eq(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](https://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) return a !== 0 || 1 / a === 1 / b; - // `null` or `undefined` only equal to itself (strict comparison). - if (a == null || b == null) return false; - // `NaN`s are equivalent, but non-reflexive. - if (a !== a) return b !== b; - // Exhaust primitive checks - var type = typeof a; - if (type !== 'function' && type !== 'object' && typeof b != 'object') return false; - return deepEq(a, b, aStack, bStack); -} - -// Internal recursive comparison function for `_.isEqual`. -function deepEq(a, b, aStack, bStack) { - // Unwrap any wrapped objects. - if (a instanceof _$1) a = a._wrapped; - if (b instanceof _$1) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className !== toString.call(b)) return false; - // Work around a bug in IE 10 - Edge 13. - if (hasStringTagBug && className == '[object Object]' && isDataView$1(a)) { - if (!isDataView$1(b)) return false; - className = tagDataView; - } - switch (className) { - // These types are compared by value. - case '[object RegExp]': - // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return '' + a === '' + b; - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. - // Object(NaN) is equivalent to NaN. - if (+a !== +a) return +b !== +b; - // An `egal` comparison is performed for other numeric values. - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a === +b; - case '[object Symbol]': - return SymbolProto.valueOf.call(a) === SymbolProto.valueOf.call(b); - case '[object ArrayBuffer]': - case tagDataView: - // Coerce to typed array so we can fall through. - return deepEq(toBufferView(a), toBufferView(b), aStack, bStack); - } - - var areArrays = className === '[object Array]'; - if (!areArrays && isTypedArray$1(a)) { - var byteLength = getByteLength(a); - if (byteLength !== getByteLength(b)) return false; - if (a.buffer === b.buffer && a.byteOffset === b.byteOffset) return true; - areArrays = true; - } - if (!areArrays) { - if (typeof a != 'object' || typeof b != 'object') return false; - - // Objects with different constructors are not equivalent, but `Object`s or `Array`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(isFunction$1(aCtor) && aCtor instanceof aCtor && - isFunction$1(bCtor) && bCtor instanceof bCtor) - && ('constructor' in a && 'constructor' in b)) { - return false; - } - } - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - - // Initializing stack of traversed objects. - // It's done here since we only need them for objects and arrays comparison. - aStack = aStack || []; - bStack = bStack || []; - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] === a) return bStack[length] === b; - } - - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - - // Recursively compare objects and arrays. - if (areArrays) { - // Compare array lengths to determine if a deep comparison is necessary. - length = a.length; - if (length !== b.length) return false; - // Deep compare the contents, ignoring non-numeric properties. - while (length--) { - if (!eq(a[length], b[length], aStack, bStack)) return false; - } - } else { - // Deep compare objects. - var _keys = keys(a), key; - length = _keys.length; - // Ensure that both objects contain the same number of properties before comparing deep equality. - if (keys(b).length !== length) return false; - while (length--) { - // Deep compare each member - key = _keys[length]; - if (!(has$1(b, key) && eq(a[key], b[key], aStack, bStack))) return false; - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return true; -} - -// Perform a deep comparison to check if two objects are equal. -function isEqual(a, b) { - return eq(a, b); -} - -// Retrieve all the enumerable property names of an object. -function allKeys(obj) { - if (!isObject(obj)) return []; - var keys = []; - for (var key in obj) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; -} - -// Since the regular `Object.prototype.toString` type tests don't work for -// some types in IE 11, we use a fingerprinting heuristic instead, based -// on the methods. It's not great, but it's the best we got. -// The fingerprint method lists are defined below. -function ie11fingerprint(methods) { - var length = getLength(methods); - return function(obj) { - if (obj == null) return false; - // `Map`, `WeakMap` and `Set` have no enumerable keys. - var keys = allKeys(obj); - if (getLength(keys)) return false; - for (var i = 0; i < length; i++) { - if (!isFunction$1(obj[methods[i]])) return false; - } - // If we are testing against `WeakMap`, we need to ensure that - // `obj` doesn't have a `forEach` method in order to distinguish - // it from a regular `Map`. - return methods !== weakMapMethods || !isFunction$1(obj[forEachName]); - }; -} - -// In the interest of compact minification, we write -// each string in the fingerprints only once. -var forEachName = 'forEach', - hasName = 'has', - commonInit = ['clear', 'delete'], - mapTail = ['get', hasName, 'set']; - -// `Map`, `WeakMap` and `Set` each have slightly different -// combinations of the above sublists. -var mapMethods = commonInit.concat(forEachName, mapTail), - weakMapMethods = commonInit.concat(mapTail), - setMethods = ['add'].concat(commonInit, forEachName, hasName); - -var isMap = isIE11 ? ie11fingerprint(mapMethods) : tagTester('Map'); - -var isWeakMap = isIE11 ? ie11fingerprint(weakMapMethods) : tagTester('WeakMap'); - -var isSet = isIE11 ? ie11fingerprint(setMethods) : tagTester('Set'); - -var isWeakSet = tagTester('WeakSet'); - -// Retrieve the values of an object's properties. -function values(obj) { - var _keys = keys(obj); - var length = _keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[_keys[i]]; - } - return values; -} - -// Convert an object into a list of `[key, value]` pairs. -// The opposite of `_.object` with one argument. -function pairs(obj) { - var _keys = keys(obj); - var length = _keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [_keys[i], obj[_keys[i]]]; - } - return pairs; -} - -// Invert the keys and values of an object. The values must be serializable. -function invert(obj) { - var result = {}; - var _keys = keys(obj); - for (var i = 0, length = _keys.length; i < length; i++) { - result[obj[_keys[i]]] = _keys[i]; - } - return result; -} - -// Return a sorted list of the function names available on the object. -function functions(obj) { - var names = []; - for (var key in obj) { - if (isFunction$1(obj[key])) names.push(key); - } - return names.sort(); -} - -// An internal function for creating assigner functions. -function createAssigner(keysFunc, defaults) { - return function(obj) { - var length = arguments.length; - if (defaults) obj = Object(obj); - if (length < 2 || obj == null) return obj; - for (var index = 1; index < length; index++) { - var source = arguments[index], - keys = keysFunc(source), - l = keys.length; - for (var i = 0; i < l; i++) { - var key = keys[i]; - if (!defaults || obj[key] === void 0) obj[key] = source[key]; - } - } - return obj; - }; -} - -// Extend a given object with all the properties in passed-in object(s). -var extend = createAssigner(allKeys); - -// Assigns a given object with all the own properties in the passed-in -// object(s). -// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) -var extendOwn = createAssigner(keys); - -// Fill in a given object with default properties. -var defaults = createAssigner(allKeys, true); - -// Create a naked function reference for surrogate-prototype-swapping. -function ctor() { - return function(){}; -} - -// An internal function for creating a new object that inherits from another. -function baseCreate(prototype) { - if (!isObject(prototype)) return {}; - if (nativeCreate) return nativeCreate(prototype); - var Ctor = ctor(); - Ctor.prototype = prototype; - var result = new Ctor; - Ctor.prototype = null; - return result; -} - -// Creates an object that inherits from the given prototype object. -// If additional properties are provided then they will be added to the -// created object. -function create(prototype, props) { - var result = baseCreate(prototype); - if (props) extendOwn(result, props); - return result; -} - -// Create a (shallow-cloned) duplicate of an object. -function clone(obj) { - if (!isObject(obj)) return obj; - return isArray(obj) ? obj.slice() : extend({}, obj); -} - -// Invokes `interceptor` with the `obj` and then returns `obj`. -// The primary purpose of this method is to "tap into" a method chain, in -// order to perform operations on intermediate results within the chain. -function tap(obj, interceptor) { - interceptor(obj); - return obj; -} - -// Normalize a (deep) property `path` to array. -// Like `_.iteratee`, this function can be customized. -function toPath$1(path) { - return isArray(path) ? path : [path]; -} -_$1.toPath = toPath$1; - -// Internal wrapper for `_.toPath` to enable minification. -// Similar to `cb` for `_.iteratee`. -function toPath(path) { - return _$1.toPath(path); -} - -// Internal function to obtain a nested property in `obj` along `path`. -function deepGet(obj, path) { - var length = path.length; - for (var i = 0; i < length; i++) { - if (obj == null) return void 0; - obj = obj[path[i]]; - } - return length ? obj : void 0; -} - -// Get the value of the (deep) property on `path` from `object`. -// If any property in `path` does not exist or if the value is -// `undefined`, return `defaultValue` instead. -// The `path` is normalized through `_.toPath`. -function get(object, path, defaultValue) { - var value = deepGet(object, toPath(path)); - return isUndefined(value) ? defaultValue : value; -} - -// Shortcut function for checking if an object has a given property directly on -// itself (in other words, not on a prototype). Unlike the internal `has` -// function, this public version can also traverse nested properties. -function has(obj, path) { - path = toPath(path); - var length = path.length; - for (var i = 0; i < length; i++) { - var key = path[i]; - if (!has$1(obj, key)) return false; - obj = obj[key]; - } - return !!length; -} - -// Keep the identity function around for default iteratees. -function identity(value) { - return value; -} - -// Returns a predicate for checking whether an object has a given set of -// `key:value` pairs. -function matcher(attrs) { - attrs = extendOwn({}, attrs); - return function(obj) { - return isMatch(obj, attrs); - }; -} - -// Creates a function that, when passed an object, will traverse that object’s -// properties down the given `path`, specified as an array of keys or indices. -function property(path) { - path = toPath(path); - return function(obj) { - return deepGet(obj, path); - }; -} - -// Internal function that returns an efficient (for current engines) version -// of the passed-in callback, to be repeatedly applied in other Underscore -// functions. -function optimizeCb(func, context, argCount) { - if (context === void 0) return func; - switch (argCount == null ? 3 : argCount) { - case 1: return function(value) { - return func.call(context, value); - }; - // The 2-argument case is omitted because we’re not using it. - case 3: return function(value, index, collection) { - return func.call(context, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(context, accumulator, value, index, collection); - }; - } - return function() { - return func.apply(context, arguments); - }; -} - -// An internal function to generate callbacks that can be applied to each -// element in a collection, returning the desired result — either `_.identity`, -// an arbitrary callback, a property matcher, or a property accessor. -function baseIteratee(value, context, argCount) { - if (value == null) return identity; - if (isFunction$1(value)) return optimizeCb(value, context, argCount); - if (isObject(value) && !isArray(value)) return matcher(value); - return property(value); -} - -// External wrapper for our callback generator. Users may customize -// `_.iteratee` if they want additional predicate/iteratee shorthand styles. -// This abstraction hides the internal-only `argCount` argument. -function iteratee(value, context) { - return baseIteratee(value, context, Infinity); -} -_$1.iteratee = iteratee; - -// The function we call internally to generate a callback. It invokes -// `_.iteratee` if overridden, otherwise `baseIteratee`. -function cb(value, context, argCount) { - if (_$1.iteratee !== iteratee) return _$1.iteratee(value, context); - return baseIteratee(value, context, argCount); -} - -// Returns the results of applying the `iteratee` to each element of `obj`. -// In contrast to `_.map` it returns an object. -function mapObject(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var _keys = keys(obj), - length = _keys.length, - results = {}; - for (var index = 0; index < length; index++) { - var currentKey = _keys[index]; - results[currentKey] = iteratee(obj[currentKey], currentKey, obj); - } - return results; -} - -// Predicate-generating function. Often useful outside of Underscore. -function noop(){} - -// Generates a function for a given object that returns a given property. -function propertyOf(obj) { - if (obj == null) return noop; - return function(path) { - return get(obj, path); - }; -} - -// Run a function **n** times. -function times(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = optimizeCb(iteratee, context, 1); - for (var i = 0; i < n; i++) accum[i] = iteratee(i); - return accum; -} - -// Return a random integer between `min` and `max` (inclusive). -function random(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); -} - -// A (possibly faster) way to get the current timestamp as an integer. -var now = Date.now || function() { - return new Date().getTime(); -}; - -// Internal helper to generate functions for escaping and unescaping strings -// to/from HTML interpolation. -function createEscaper(map) { - var escaper = function(match) { - return map[match]; - }; - // Regexes for identifying a key that needs to be escaped. - var source = '(?:' + keys(map).join('|') + ')'; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, 'g'); - return function(string) { - string = string == null ? '' : '' + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; -} - -// Internal list of HTML entities for escaping. -var escapeMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`' -}; - -// Function for escaping strings to HTML interpolation. -var _escape = createEscaper(escapeMap); - -// Internal list of HTML entities for unescaping. -var unescapeMap = invert(escapeMap); - -// Function for unescaping strings from HTML interpolation. -var _unescape = createEscaper(unescapeMap); - -// By default, Underscore uses ERB-style template delimiters. Change the -// following template settings to use alternative delimiters. -var templateSettings = _$1.templateSettings = { - evaluate: /<%([\s\S]+?)%>/g, - interpolate: /<%=([\s\S]+?)%>/g, - escape: /<%-([\s\S]+?)%>/g -}; - -// When customizing `_.templateSettings`, if you don't want to define an -// interpolation, evaluation or escaping regex, we need one that is -// guaranteed not to match. -var noMatch = /(.)^/; - -// Certain characters need to be escaped so that they can be put into a -// string literal. -var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\u2028': 'u2028', - '\u2029': 'u2029' -}; - -var escapeRegExp = /\\|'|\r|\n|\u2028|\u2029/g; - -function escapeChar(match) { - return '\\' + escapes[match]; -} - -// In order to prevent third-party code injection through -// `_.templateSettings.variable`, we test it against the following regular -// expression. It is intentionally a bit more liberal than just matching valid -// identifiers, but still prevents possible loopholes through defaults or -// destructuring assignment. -var bareIdentifier = /^\s*(\w|\$)+\s*$/; - -// JavaScript micro-templating, similar to John Resig's implementation. -// Underscore templating handles arbitrary delimiters, preserves whitespace, -// and correctly escapes quotes within interpolated code. -// NB: `oldSettings` only exists for backwards compatibility. -function template(text, settings, oldSettings) { - if (!settings && oldSettings) settings = oldSettings; - settings = defaults({}, settings, _$1.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escapeRegExp, escapeChar); - index = offset + match.length; - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - - // Adobe VMs need the match returned to produce the correct offset. - return match; - }); - source += "';\n"; - - var argument = settings.variable; - if (argument) { - // Insure against third-party code injection. (CVE-2021-23358) - if (!bareIdentifier.test(argument)) throw new Error( - 'variable is not a bare identifier: ' + argument - ); - } else { - // If a variable is not specified, place data values in local scope. - source = 'with(obj||{}){\n' + source + '}\n'; - argument = 'obj'; - } - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + 'return __p;\n'; - - var render; - try { - render = new Function(argument, '_', source); - } catch (e) { - e.source = source; - throw e; - } - - var template = function(data) { - return render.call(this, data, _$1); - }; - - // Provide the compiled source as a convenience for precompilation. - template.source = 'function(' + argument + '){\n' + source + '}'; - - return template; -} - -// Traverses the children of `obj` along `path`. If a child is a function, it -// is invoked with its parent as context. Returns the value of the final -// child, or `fallback` if any child is undefined. -function result(obj, path, fallback) { - path = toPath(path); - var length = path.length; - if (!length) { - return isFunction$1(fallback) ? fallback.call(obj) : fallback; - } - for (var i = 0; i < length; i++) { - var prop = obj == null ? void 0 : obj[path[i]]; - if (prop === void 0) { - prop = fallback; - i = length; // Ensure we don't continue iterating. - } - obj = isFunction$1(prop) ? prop.call(obj) : prop; - } - return obj; -} - -// Generate a unique integer id (unique within the entire client session). -// Useful for temporary DOM ids. -var idCounter = 0; -function uniqueId(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; -} - -// Start chaining a wrapped Underscore object. -function chain(obj) { - var instance = _$1(obj); - instance._chain = true; - return instance; -} - -// Internal function to execute `sourceFunc` bound to `context` with optional -// `args`. Determines whether to execute a function as a constructor or as a -// normal function. -function executeBound(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); - var self = baseCreate(sourceFunc.prototype); - var result = sourceFunc.apply(self, args); - if (isObject(result)) return result; - return self; -} - -// Partially apply a function by creating a version that has had some of its -// arguments pre-filled, without changing its dynamic `this` context. `_` acts -// as a placeholder by default, allowing any combination of arguments to be -// pre-filled. Set `_.partial.placeholder` for a custom placeholder argument. -var partial = restArguments(function(func, boundArgs) { - var placeholder = partial.placeholder; - var bound = function() { - var position = 0, length = boundArgs.length; - var args = Array(length); - for (var i = 0; i < length; i++) { - args[i] = boundArgs[i] === placeholder ? arguments[position++] : boundArgs[i]; - } - while (position < arguments.length) args.push(arguments[position++]); - return executeBound(func, bound, this, this, args); - }; - return bound; -}); - -partial.placeholder = _$1; - -// Create a function bound to a given object (assigning `this`, and arguments, -// optionally). -var bind = restArguments(function(func, context, args) { - if (!isFunction$1(func)) throw new TypeError('Bind must be called on a function'); - var bound = restArguments(function(callArgs) { - return executeBound(func, bound, context, this, args.concat(callArgs)); - }); - return bound; -}); - -// Internal helper for collection methods to determine whether a collection -// should be iterated as an array or as an object. -// Related: https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength -// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 -var isArrayLike = createSizePropertyCheck(getLength); - -// Internal implementation of a recursive `flatten` function. -function flatten$1(input, depth, strict, output) { - output = output || []; - if (!depth && depth !== 0) { - depth = Infinity; - } else if (depth <= 0) { - return output.concat(input); - } - var idx = output.length; - for (var i = 0, length = getLength(input); i < length; i++) { - var value = input[i]; - if (isArrayLike(value) && (isArray(value) || isArguments$1(value))) { - // Flatten current level of array or arguments object. - if (depth > 1) { - flatten$1(value, depth - 1, strict, output); - idx = output.length; - } else { - var j = 0, len = value.length; - while (j < len) output[idx++] = value[j++]; - } - } else if (!strict) { - output[idx++] = value; - } - } - return output; -} - -// Bind a number of an object's methods to that object. Remaining arguments -// are the method names to be bound. Useful for ensuring that all callbacks -// defined on an object belong to it. -var bindAll = restArguments(function(obj, keys) { - keys = flatten$1(keys, false, false); - var index = keys.length; - if (index < 1) throw new Error('bindAll must be passed function names'); - while (index--) { - var key = keys[index]; - obj[key] = bind(obj[key], obj); - } - return obj; -}); - -// Memoize an expensive function by storing its results. -function memoize(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = '' + (hasher ? hasher.apply(this, arguments) : key); - if (!has$1(cache, address)) cache[address] = func.apply(this, arguments); - return cache[address]; - }; - memoize.cache = {}; - return memoize; -} - -// Delays a function for the given number of milliseconds, and then calls -// it with the arguments supplied. -var delay = restArguments(function(func, wait, args) { - return setTimeout(function() { - return func.apply(null, args); - }, wait); -}); - -// Defers a function, scheduling it to run after the current call stack has -// cleared. -var defer = partial(delay, _$1, 1); - -// Returns a function, that, when invoked, will only be triggered at most once -// during a given window of time. Normally, the throttled function will run -// as much as it can, without ever going more than once per `wait` duration; -// but if you'd like to disable the execution on the leading edge, pass -// `{leading: false}`. To disable execution on the trailing edge, ditto. -function throttle(func, wait, options) { - var timeout, context, args, result; - var previous = 0; - if (!options) options = {}; - - var later = function() { - previous = options.leading === false ? 0 : now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }; - - var throttled = function() { - var _now = now(); - if (!previous && options.leading === false) previous = _now; - var remaining = wait - (_now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = _now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; - - throttled.cancel = function() { - clearTimeout(timeout); - previous = 0; - timeout = context = args = null; - }; - - return throttled; -} - -// When a sequence of calls of the returned function ends, the argument -// function is triggered. The end of a sequence is defined by the `wait` -// parameter. If `immediate` is passed, the argument function will be -// triggered at the beginning of the sequence instead of at the end. -function debounce(func, wait, immediate) { - var timeout, previous, args, result, context; - - var later = function() { - var passed = now() - previous; - if (wait > passed) { - timeout = setTimeout(later, wait - passed); - } else { - timeout = null; - if (!immediate) result = func.apply(context, args); - // This check is needed because `func` can recursively invoke `debounced`. - if (!timeout) args = context = null; - } - }; - - var debounced = restArguments(function(_args) { - context = this; - args = _args; - previous = now(); - if (!timeout) { - timeout = setTimeout(later, wait); - if (immediate) result = func.apply(context, args); - } - return result; - }); - - debounced.cancel = function() { - clearTimeout(timeout); - timeout = args = context = null; - }; - - return debounced; -} - -// Returns the first function passed as an argument to the second, -// allowing you to adjust arguments, run code before and after, and -// conditionally execute the original function. -function wrap(func, wrapper) { - return partial(wrapper, func); -} - -// Returns a negated version of the passed-in predicate. -function negate(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; -} - -// Returns a function that is the composition of a list of functions, each -// consuming the return value of the function that follows. -function compose() { - var args = arguments; - var start = args.length - 1; - return function() { - var i = start; - var result = args[start].apply(this, arguments); - while (i--) result = args[i].call(this, result); - return result; - }; -} - -// Returns a function that will only be executed on and after the Nth call. -function after(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; -} - -// Returns a function that will only be executed up to (but not including) the -// Nth call. -function before(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } - if (times <= 1) func = null; - return memo; - }; -} - -// Returns a function that will be executed at most one time, no matter how -// often you call it. Useful for lazy initialization. -var once = partial(before, 2); - -// Returns the first key on an object that passes a truth test. -function findKey(obj, predicate, context) { - predicate = cb(predicate, context); - var _keys = keys(obj), key; - for (var i = 0, length = _keys.length; i < length; i++) { - key = _keys[i]; - if (predicate(obj[key], key, obj)) return key; - } -} - -// Internal function to generate `_.findIndex` and `_.findLastIndex`. -function createPredicateIndexFinder(dir) { - return function(array, predicate, context) { - predicate = cb(predicate, context); - var length = getLength(array); - var index = dir > 0 ? 0 : length - 1; - for (; index >= 0 && index < length; index += dir) { - if (predicate(array[index], index, array)) return index; - } - return -1; - }; -} - -// Returns the first index on an array-like that passes a truth test. -var findIndex = createPredicateIndexFinder(1); - -// Returns the last index on an array-like that passes a truth test. -var findLastIndex = createPredicateIndexFinder(-1); - -// Use a comparator function to figure out the smallest index at which -// an object should be inserted so as to maintain order. Uses binary search. -function sortedIndex(array, obj, iteratee, context) { - iteratee = cb(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = getLength(array); - while (low < high) { - var mid = Math.floor((low + high) / 2); - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; -} - -// Internal function to generate the `_.indexOf` and `_.lastIndexOf` functions. -function createIndexFinder(dir, predicateFind, sortedIndex) { - return function(array, item, idx) { - var i = 0, length = getLength(array); - if (typeof idx == 'number') { - if (dir > 0) { - i = idx >= 0 ? idx : Math.max(idx + length, i); - } else { - length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; - } - } else if (sortedIndex && idx && length) { - idx = sortedIndex(array, item); - return array[idx] === item ? idx : -1; - } - if (item !== item) { - idx = predicateFind(slice.call(array, i, length), isNaN$1); - return idx >= 0 ? idx + i : -1; - } - for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { - if (array[idx] === item) return idx; - } - return -1; - }; -} - -// Return the position of the first occurrence of an item in an array, -// or -1 if the item is not included in the array. -// If the array is large and already in sort order, pass `true` -// for **isSorted** to use binary search. -var indexOf = createIndexFinder(1, findIndex, sortedIndex); - -// Return the position of the last occurrence of an item in an array, -// or -1 if the item is not included in the array. -var lastIndexOf = createIndexFinder(-1, findLastIndex); - -// Return the first value which passes a truth test. -function find(obj, predicate, context) { - var keyFinder = isArrayLike(obj) ? findIndex : findKey; - var key = keyFinder(obj, predicate, context); - if (key !== void 0 && key !== -1) return obj[key]; -} - -// Convenience version of a common use case of `_.find`: getting the first -// object containing specific `key:value` pairs. -function findWhere(obj, attrs) { - return find(obj, matcher(attrs)); -} - -// The cornerstone for collection functions, an `each` -// implementation, aka `forEach`. -// Handles raw objects in addition to array-likes. Treats all -// sparse array-likes as if they were dense. -function each(obj, iteratee, context) { - iteratee = optimizeCb(iteratee, context); - var i, length; - if (isArrayLike(obj)) { - for (i = 0, length = obj.length; i < length; i++) { - iteratee(obj[i], i, obj); - } - } else { - var _keys = keys(obj); - for (i = 0, length = _keys.length; i < length; i++) { - iteratee(obj[_keys[i]], _keys[i], obj); - } - } - return obj; -} - -// Return the results of applying the iteratee to each element. -function map(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var _keys = !isArrayLike(obj) && keys(obj), - length = (_keys || obj).length, - results = Array(length); - for (var index = 0; index < length; index++) { - var currentKey = _keys ? _keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); - } - return results; -} - -// Internal helper to create a reducing function, iterating left or right. -function createReduce(dir) { - // Wrap code that reassigns argument variables in a separate function than - // the one that accesses `arguments.length` to avoid a perf hit. (#1991) - var reducer = function(obj, iteratee, memo, initial) { - var _keys = !isArrayLike(obj) && keys(obj), - length = (_keys || obj).length, - index = dir > 0 ? 0 : length - 1; - if (!initial) { - memo = obj[_keys ? _keys[index] : index]; - index += dir; - } - for (; index >= 0 && index < length; index += dir) { - var currentKey = _keys ? _keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - }; - - return function(obj, iteratee, memo, context) { - var initial = arguments.length >= 3; - return reducer(obj, optimizeCb(iteratee, context, 4), memo, initial); - }; -} - -// **Reduce** builds up a single result from a list of values, aka `inject`, -// or `foldl`. -var reduce = createReduce(1); - -// The right-associative version of reduce, also known as `foldr`. -var reduceRight = createReduce(-1); - -// Return all the elements that pass a truth test. -function filter(obj, predicate, context) { - var results = []; - predicate = cb(predicate, context); - each(obj, function(value, index, list) { - if (predicate(value, index, list)) results.push(value); - }); - return results; -} - -// Return all the elements for which a truth test fails. -function reject(obj, predicate, context) { - return filter(obj, negate(cb(predicate)), context); -} - -// Determine whether all of the elements pass a truth test. -function every(obj, predicate, context) { - predicate = cb(predicate, context); - var _keys = !isArrayLike(obj) && keys(obj), - length = (_keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = _keys ? _keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) return false; - } - return true; -} - -// Determine if at least one element in the object passes a truth test. -function some(obj, predicate, context) { - predicate = cb(predicate, context); - var _keys = !isArrayLike(obj) && keys(obj), - length = (_keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = _keys ? _keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) return true; - } - return false; -} - -// Determine if the array or object contains a given item (using `===`). -function contains(obj, item, fromIndex, guard) { - if (!isArrayLike(obj)) obj = values(obj); - if (typeof fromIndex != 'number' || guard) fromIndex = 0; - return indexOf(obj, item, fromIndex) >= 0; -} - -// Invoke a method (with arguments) on every item in a collection. -var invoke = restArguments(function(obj, path, args) { - var contextPath, func; - if (isFunction$1(path)) { - func = path; - } else { - path = toPath(path); - contextPath = path.slice(0, -1); - path = path[path.length - 1]; - } - return map(obj, function(context) { - var method = func; - if (!method) { - if (contextPath && contextPath.length) { - context = deepGet(context, contextPath); - } - if (context == null) return void 0; - method = context[path]; - } - return method == null ? method : method.apply(context, args); - }); -}); - -// Convenience version of a common use case of `_.map`: fetching a property. -function pluck(obj, key) { - return map(obj, property(key)); -} - -// Convenience version of a common use case of `_.filter`: selecting only -// objects containing specific `key:value` pairs. -function where(obj, attrs) { - return filter(obj, matcher(attrs)); -} - -// Return the maximum element (or element-based computation). -function max(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, - value, computed; - if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null)) { - obj = isArrayLike(obj) ? obj : values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value != null && value > result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - each(obj, function(v, index, list) { - computed = iteratee(v, index, list); - if (computed > lastComputed || (computed === -Infinity && result === -Infinity)) { - result = v; - lastComputed = computed; - } - }); - } - return result; -} - -// Return the minimum element (or element-based computation). -function min(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, - value, computed; - if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object' && obj != null)) { - obj = isArrayLike(obj) ? obj : values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value != null && value < result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - each(obj, function(v, index, list) { - computed = iteratee(v, index, list); - if (computed < lastComputed || (computed === Infinity && result === Infinity)) { - result = v; - lastComputed = computed; - } - }); - } - return result; -} - -// Safely create a real, live array from anything iterable. -var reStrSymbol = /[^\ud800-\udfff]|[\ud800-\udbff][\udc00-\udfff]|[\ud800-\udfff]/g; -function toArray(obj) { - if (!obj) return []; - if (isArray(obj)) return slice.call(obj); - if (isString(obj)) { - // Keep surrogate pair characters together. - return obj.match(reStrSymbol); - } - if (isArrayLike(obj)) return map(obj, identity); - return values(obj); -} - -// Sample **n** random values from a collection using the modern version of the -// [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher–Yates_shuffle). -// If **n** is not specified, returns a single random element. -// The internal `guard` argument allows it to work with `_.map`. -function sample(obj, n, guard) { - if (n == null || guard) { - if (!isArrayLike(obj)) obj = values(obj); - return obj[random(obj.length - 1)]; - } - var sample = toArray(obj); - var length = getLength(sample); - n = Math.max(Math.min(n, length), 0); - var last = length - 1; - for (var index = 0; index < n; index++) { - var rand = random(index, last); - var temp = sample[index]; - sample[index] = sample[rand]; - sample[rand] = temp; - } - return sample.slice(0, n); -} - -// Shuffle a collection. -function shuffle(obj) { - return sample(obj, Infinity); -} - -// Sort the object's values by a criterion produced by an iteratee. -function sortBy(obj, iteratee, context) { - var index = 0; - iteratee = cb(iteratee, context); - return pluck(map(obj, function(value, key, list) { - return { - value: value, - index: index++, - criteria: iteratee(value, key, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index - right.index; - }), 'value'); -} - -// An internal function used for aggregate "group by" operations. -function group(behavior, partition) { - return function(obj, iteratee, context) { - var result = partition ? [[], []] : {}; - iteratee = cb(iteratee, context); - each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); - return result; - }; -} - -// Groups the object's values by a criterion. Pass either a string attribute -// to group by, or a function that returns the criterion. -var groupBy = group(function(result, value, key) { - if (has$1(result, key)) result[key].push(value); else result[key] = [value]; -}); - -// Indexes the object's values by a criterion, similar to `_.groupBy`, but for -// when you know that your index values will be unique. -var indexBy = group(function(result, value, key) { - result[key] = value; -}); - -// Counts instances of an object that group by a certain criterion. Pass -// either a string attribute to count by, or a function that returns the -// criterion. -var countBy = group(function(result, value, key) { - if (has$1(result, key)) result[key]++; else result[key] = 1; -}); - -// Split a collection into two arrays: one whose elements all pass the given -// truth test, and one whose elements all do not pass the truth test. -var partition = group(function(result, value, pass) { - result[pass ? 0 : 1].push(value); -}, true); - -// Return the number of elements in a collection. -function size(obj) { - if (obj == null) return 0; - return isArrayLike(obj) ? obj.length : keys(obj).length; -} - -// Internal `_.pick` helper function to determine whether `key` is an enumerable -// property name of `obj`. -function keyInObj(value, key, obj) { - return key in obj; -} - -// Return a copy of the object only containing the allowed properties. -var pick = restArguments(function(obj, keys) { - var result = {}, iteratee = keys[0]; - if (obj == null) return result; - if (isFunction$1(iteratee)) { - if (keys.length > 1) iteratee = optimizeCb(iteratee, keys[1]); - keys = allKeys(obj); - } else { - iteratee = keyInObj; - keys = flatten$1(keys, false, false); - obj = Object(obj); - } - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i]; - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; - } - return result; -}); - -// Return a copy of the object without the disallowed properties. -var omit = restArguments(function(obj, keys) { - var iteratee = keys[0], context; - if (isFunction$1(iteratee)) { - iteratee = negate(iteratee); - if (keys.length > 1) context = keys[1]; - } else { - keys = map(flatten$1(keys, false, false), String); - iteratee = function(value, key) { - return !contains(keys, key); - }; - } - return pick(obj, iteratee, context); -}); - -// Returns everything but the last entry of the array. Especially useful on -// the arguments object. Passing **n** will return all the values in -// the array, excluding the last N. -function initial(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); -} - -// Get the first element of an array. Passing **n** will return the first N -// values in the array. The **guard** check allows it to work with `_.map`. -function first(array, n, guard) { - if (array == null || array.length < 1) return n == null || guard ? void 0 : []; - if (n == null || guard) return array[0]; - return initial(array, array.length - n); -} - -// Returns everything but the first entry of the `array`. Especially useful on -// the `arguments` object. Passing an **n** will return the rest N values in the -// `array`. -function rest(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); -} - -// Get the last element of an array. Passing **n** will return the last N -// values in the array. -function last(array, n, guard) { - if (array == null || array.length < 1) return n == null || guard ? void 0 : []; - if (n == null || guard) return array[array.length - 1]; - return rest(array, Math.max(0, array.length - n)); -} - -// Trim out all falsy values from an array. -function compact(array) { - return filter(array, Boolean); -} - -// Flatten out an array, either recursively (by default), or up to `depth`. -// Passing `true` or `false` as `depth` means `1` or `Infinity`, respectively. -function flatten(array, depth) { - return flatten$1(array, depth, false); -} - -// Take the difference between one array and a number of other arrays. -// Only the elements present in just the first array will remain. -var difference = restArguments(function(array, rest) { - rest = flatten$1(rest, true, true); - return filter(array, function(value){ - return !contains(rest, value); - }); -}); - -// Return a version of the array that does not contain the specified value(s). -var without = restArguments(function(array, otherArrays) { - return difference(array, otherArrays); -}); - -// Produce a duplicate-free version of the array. If the array has already -// been sorted, you have the option of using a faster algorithm. -// The faster algorithm will not work with an iteratee if the iteratee -// is not a one-to-one function, so providing an iteratee will disable -// the faster algorithm. -function uniq(array, isSorted, iteratee, context) { - if (!isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; - } - if (iteratee != null) iteratee = cb(iteratee, context); - var result = []; - var seen = []; - for (var i = 0, length = getLength(array); i < length; i++) { - var value = array[i], - computed = iteratee ? iteratee(value, i, array) : value; - if (isSorted && !iteratee) { - if (!i || seen !== computed) result.push(value); - seen = computed; - } else if (iteratee) { - if (!contains(seen, computed)) { - seen.push(computed); - result.push(value); - } - } else if (!contains(result, value)) { - result.push(value); - } - } - return result; -} - -// Produce an array that contains the union: each distinct element from all of -// the passed-in arrays. -var union = restArguments(function(arrays) { - return uniq(flatten$1(arrays, true, true)); -}); - -// Produce an array that contains every item shared between all the -// passed-in arrays. -function intersection(array) { - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = getLength(array); i < length; i++) { - var item = array[i]; - if (contains(result, item)) continue; - var j; - for (j = 1; j < argsLength; j++) { - if (!contains(arguments[j], item)) break; - } - if (j === argsLength) result.push(item); - } - return result; -} - -// Complement of zip. Unzip accepts an array of arrays and groups -// each array's elements on shared indices. -function unzip(array) { - var length = (array && max(array, getLength).length) || 0; - var result = Array(length); - - for (var index = 0; index < length; index++) { - result[index] = pluck(array, index); - } - return result; -} - -// Zip together multiple lists into a single array -- elements that share -// an index go together. -var zip = restArguments(unzip); - -// Converts lists into objects. Pass either a single array of `[key, value]` -// pairs, or two parallel arrays of the same length -- one of keys, and one of -// the corresponding values. Passing by pairs is the reverse of `_.pairs`. -function object(list, values) { - var result = {}; - for (var i = 0, length = getLength(list); i < length; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; -} - -// Generate an integer Array containing an arithmetic progression. A port of -// the native Python `range()` function. See -// [the Python documentation](https://docs.python.org/library/functions.html#range). -function range(start, stop, step) { - if (stop == null) { - stop = start || 0; - start = 0; - } - if (!step) { - step = stop < start ? -1 : 1; - } - - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; - } - - return range; -} - -// Chunk a single array into multiple arrays, each containing `count` or fewer -// items. -function chunk(array, count) { - if (count == null || count < 1) return []; - var result = []; - var i = 0, length = array.length; - while (i < length) { - result.push(slice.call(array, i, i += count)); - } - return result; -} - -// Helper function to continue chaining intermediate results. -function chainResult(instance, obj) { - return instance._chain ? _$1(obj).chain() : obj; -} - -// Add your own custom functions to the Underscore object. -function mixin(obj) { - each(functions(obj), function(name) { - var func = _$1[name] = obj[name]; - _$1.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return chainResult(this, func.apply(_$1, args)); - }; - }); - return _$1; -} - -// Add all mutator `Array` functions to the wrapper. -each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _$1.prototype[name] = function() { - var obj = this._wrapped; - if (obj != null) { - method.apply(obj, arguments); - if ((name === 'shift' || name === 'splice') && obj.length === 0) { - delete obj[0]; - } - } - return chainResult(this, obj); - }; -}); - -// Add all accessor `Array` functions to the wrapper. -each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _$1.prototype[name] = function() { - var obj = this._wrapped; - if (obj != null) obj = method.apply(obj, arguments); - return chainResult(this, obj); - }; -}); - -// Named Exports - -var allExports = { - __proto__: null, - VERSION: VERSION, - restArguments: restArguments, - isObject: isObject, - isNull: isNull, - isUndefined: isUndefined, - isBoolean: isBoolean, - isElement: isElement, - isString: isString, - isNumber: isNumber, - isDate: isDate, - isRegExp: isRegExp, - isError: isError, - isSymbol: isSymbol, - isArrayBuffer: isArrayBuffer, - isDataView: isDataView$1, - isArray: isArray, - isFunction: isFunction$1, - isArguments: isArguments$1, - isFinite: isFinite$1, - isNaN: isNaN$1, - isTypedArray: isTypedArray$1, - isEmpty: isEmpty, - isMatch: isMatch, - isEqual: isEqual, - isMap: isMap, - isWeakMap: isWeakMap, - isSet: isSet, - isWeakSet: isWeakSet, - keys: keys, - allKeys: allKeys, - values: values, - pairs: pairs, - invert: invert, - functions: functions, - methods: functions, - extend: extend, - extendOwn: extendOwn, - assign: extendOwn, - defaults: defaults, - create: create, - clone: clone, - tap: tap, - get: get, - has: has, - mapObject: mapObject, - identity: identity, - constant: constant, - noop: noop, - toPath: toPath$1, - property: property, - propertyOf: propertyOf, - matcher: matcher, - matches: matcher, - times: times, - random: random, - now: now, - escape: _escape, - unescape: _unescape, - templateSettings: templateSettings, - template: template, - result: result, - uniqueId: uniqueId, - chain: chain, - iteratee: iteratee, - partial: partial, - bind: bind, - bindAll: bindAll, - memoize: memoize, - delay: delay, - defer: defer, - throttle: throttle, - debounce: debounce, - wrap: wrap, - negate: negate, - compose: compose, - after: after, - before: before, - once: once, - findKey: findKey, - findIndex: findIndex, - findLastIndex: findLastIndex, - sortedIndex: sortedIndex, - indexOf: indexOf, - lastIndexOf: lastIndexOf, - find: find, - detect: find, - findWhere: findWhere, - each: each, - forEach: each, - map: map, - collect: map, - reduce: reduce, - foldl: reduce, - inject: reduce, - reduceRight: reduceRight, - foldr: reduceRight, - filter: filter, - select: filter, - reject: reject, - every: every, - all: every, - some: some, - any: some, - contains: contains, - includes: contains, - include: contains, - invoke: invoke, - pluck: pluck, - where: where, - max: max, - min: min, - shuffle: shuffle, - sample: sample, - sortBy: sortBy, - groupBy: groupBy, - indexBy: indexBy, - countBy: countBy, - partition: partition, - toArray: toArray, - size: size, - pick: pick, - omit: omit, - first: first, - head: first, - take: first, - initial: initial, - last: last, - rest: rest, - tail: rest, - drop: rest, - compact: compact, - flatten: flatten, - without: without, - uniq: uniq, - unique: uniq, - union: union, - intersection: intersection, - difference: difference, - unzip: unzip, - transpose: unzip, - zip: zip, - object: object, - range: range, - chunk: chunk, - mixin: mixin, - 'default': _$1 -}; - -// Default Export - -// Add all of the Underscore functions to the wrapper object. -var _ = mixin(allExports); -// Legacy Node.js API. -_._ = _; - -exports.VERSION = VERSION; -exports._ = _; -exports._escape = _escape; -exports._unescape = _unescape; -exports.after = after; -exports.allKeys = allKeys; -exports.before = before; -exports.bind = bind; -exports.bindAll = bindAll; -exports.chain = chain; -exports.chunk = chunk; -exports.clone = clone; -exports.compact = compact; -exports.compose = compose; -exports.constant = constant; -exports.contains = contains; -exports.countBy = countBy; -exports.create = create; -exports.debounce = debounce; -exports.defaults = defaults; -exports.defer = defer; -exports.delay = delay; -exports.difference = difference; -exports.each = each; -exports.every = every; -exports.extend = extend; -exports.extendOwn = extendOwn; -exports.filter = filter; -exports.find = find; -exports.findIndex = findIndex; -exports.findKey = findKey; -exports.findLastIndex = findLastIndex; -exports.findWhere = findWhere; -exports.first = first; -exports.flatten = flatten; -exports.functions = functions; -exports.get = get; -exports.groupBy = groupBy; -exports.has = has; -exports.identity = identity; -exports.indexBy = indexBy; -exports.indexOf = indexOf; -exports.initial = initial; -exports.intersection = intersection; -exports.invert = invert; -exports.invoke = invoke; -exports.isArguments = isArguments$1; -exports.isArray = isArray; -exports.isArrayBuffer = isArrayBuffer; -exports.isBoolean = isBoolean; -exports.isDataView = isDataView$1; -exports.isDate = isDate; -exports.isElement = isElement; -exports.isEmpty = isEmpty; -exports.isEqual = isEqual; -exports.isError = isError; -exports.isFinite = isFinite$1; -exports.isFunction = isFunction$1; -exports.isMap = isMap; -exports.isMatch = isMatch; -exports.isNaN = isNaN$1; -exports.isNull = isNull; -exports.isNumber = isNumber; -exports.isObject = isObject; -exports.isRegExp = isRegExp; -exports.isSet = isSet; -exports.isString = isString; -exports.isSymbol = isSymbol; -exports.isTypedArray = isTypedArray$1; -exports.isUndefined = isUndefined; -exports.isWeakMap = isWeakMap; -exports.isWeakSet = isWeakSet; -exports.iteratee = iteratee; -exports.keys = keys; -exports.last = last; -exports.lastIndexOf = lastIndexOf; -exports.map = map; -exports.mapObject = mapObject; -exports.matcher = matcher; -exports.max = max; -exports.memoize = memoize; -exports.min = min; -exports.mixin = mixin; -exports.negate = negate; -exports.noop = noop; -exports.now = now; -exports.object = object; -exports.omit = omit; -exports.once = once; -exports.pairs = pairs; -exports.partial = partial; -exports.partition = partition; -exports.pick = pick; -exports.pluck = pluck; -exports.property = property; -exports.propertyOf = propertyOf; -exports.random = random; -exports.range = range; -exports.reduce = reduce; -exports.reduceRight = reduceRight; -exports.reject = reject; -exports.rest = rest; -exports.restArguments = restArguments; -exports.result = result; -exports.sample = sample; -exports.shuffle = shuffle; -exports.size = size; -exports.some = some; -exports.sortBy = sortBy; -exports.sortedIndex = sortedIndex; -exports.tap = tap; -exports.template = template; -exports.templateSettings = templateSettings; -exports.throttle = throttle; -exports.times = times; -exports.toArray = toArray; -exports.toPath = toPath$1; -exports.union = union; -exports.uniq = uniq; -exports.uniqueId = uniqueId; -exports.unzip = unzip; -exports.values = values; -exports.where = where; -exports.without = without; -exports.wrap = wrap; -exports.zip = zip; -//# sourceMappingURL=underscore-node-f.cjs.map - - -/***/ }), - -/***/ 5067: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -// Underscore.js 1.13.6 -// https://underscorejs.org -// (c) 2009-2022 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -var underscoreNodeF = __nccwpck_require__(6717); - - - -module.exports = underscoreNodeF._; -//# sourceMappingURL=underscore-node.cjs.map - - /***/ }), /***/ 1907: @@ -14441,7 +12270,7 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"] /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __nccwpck_require__(2052); +/******/ var __webpack_exports__ = __nccwpck_require__(3580); /******/ module.exports = __webpack_exports__; /******/ /******/ })() diff --git a/.github/actions/javascript/postTestBuildComment/postTestBuildComment.js b/.github/actions/javascript/postTestBuildComment/postTestBuildComment.ts similarity index 80% rename from .github/actions/javascript/postTestBuildComment/postTestBuildComment.js rename to .github/actions/javascript/postTestBuildComment/postTestBuildComment.ts index 35bb44428fdf..4fba1a6cb2ad 100644 --- a/.github/actions/javascript/postTestBuildComment/postTestBuildComment.js +++ b/.github/actions/javascript/postTestBuildComment/postTestBuildComment.ts @@ -1,13 +1,9 @@ -const _ = require('underscore'); -const core = require('@actions/core'); -const {context} = require('@actions/github'); -const CONST = require('../../../libs/CONST'); -const GithubUtils = require('../../../libs/GithubUtils'); +import * as core from '@actions/core'; +import {context} from '@actions/github'; +import CONST from '@github/libs/CONST'; +import GithubUtils from '@github/libs/GithubUtils'; -/** - * @returns {String} - */ -function getTestBuildMessage() { +function getTestBuildMessage(): string { console.log('Input for android', core.getInput('ANDROID', {required: true})); const androidSuccess = core.getInput('ANDROID', {required: true}) === 'success'; const desktopSuccess = core.getInput('DESKTOP', {required: true}) === 'success'; @@ -45,37 +41,36 @@ function getTestBuildMessage() { return message; } -/** - * Comment on a single PR - * - * @param {Number} PR - * @param {String} message - * @returns {Promise} - */ -async function commentPR(PR, message) { +/** Comment on a single PR */ +async function commentPR(PR: number, message: string) { console.log(`Posting test build comment on #${PR}`); try { await GithubUtils.createComment(context.repo.repo, PR, message); console.log(`Comment created on #${PR} successfully 🎉`); } catch (err) { console.log(`Unable to write comment on #${PR} 😞`); - core.setFailed(err.message); + + if (err instanceof Error) { + core.setFailed(err.message); + } } } async function run() { - const PR_NUMBER = core.getInput('PR_NUMBER', {required: true}); + const PR_NUMBER = Number(core.getInput('PR_NUMBER', {required: true})); const comments = await GithubUtils.paginate( GithubUtils.octokit.issues.listComments, { owner: CONST.GITHUB_OWNER, repo: CONST.APP_REPO, + // eslint-disable-next-line @typescript-eslint/naming-convention issue_number: PR_NUMBER, + // eslint-disable-next-line @typescript-eslint/naming-convention per_page: 100, }, (response) => response.data, ); - const testBuildComment = _.find(comments, (comment) => comment.body.startsWith(':test_tube::test_tube: Use the links below to test this adhoc build')); + const testBuildComment = comments.find((comment) => comment.body?.startsWith(':test_tube::test_tube: Use the links below to test this adhoc build')); if (testBuildComment) { console.log('Found previous build comment, hiding it', testBuildComment); await GithubUtils.graphql(` @@ -95,4 +90,4 @@ if (require.main === module) { run(); } -module.exports = run; +export default run; diff --git a/.github/actions/javascript/reopenIssueWithComment/index.js b/.github/actions/javascript/reopenIssueWithComment/index.js index 252e772359ac..59dfa50e2a21 100644 --- a/.github/actions/javascript/reopenIssueWithComment/index.js +++ b/.github/actions/javascript/reopenIssueWithComment/index.js @@ -11443,6 +11443,77 @@ function wrappy (fn, cb) { } +/***/ }), + +/***/ 7254: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const core = __importStar(__nccwpck_require__(2186)); +const CONST_1 = __importDefault(__nccwpck_require__(4097)); +const GithubUtils_1 = __importDefault(__nccwpck_require__(9296)); +const issueNumber = Number(core.getInput('ISSUE_NUMBER', { required: true })); +const comment = core.getInput('COMMENT', { required: true }); +function reopenIssueWithComment() { + console.log(`Reopening issue #${issueNumber}`); + return GithubUtils_1.default.octokit.issues + .update({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + // eslint-disable-next-line @typescript-eslint/naming-convention + issue_number: issueNumber, + state: 'open', + }) + .then(() => { + console.log(`Commenting on issue #${issueNumber}`); + return GithubUtils_1.default.octokit.issues.createComment({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + // eslint-disable-next-line @typescript-eslint/naming-convention + issue_number: issueNumber, + body: comment, + }); + }); +} +reopenIssueWithComment() + .then(() => { + console.log(`Issue #${issueNumber} successfully reopened and commented: "${comment}"`); + process.exit(0); +}) + .catch((err) => { + console.error(`Something went wrong. The issue #${issueNumber} was not successfully reopened`, err); + core.setFailed(err); +}); + + /***/ }), /***/ 9296: @@ -11499,6 +11570,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * @@ -12105,48 +12177,12 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"] /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; /******/ /************************************************************************/ -var __webpack_exports__ = {}; -// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. -(() => { -const core = __nccwpck_require__(2186); -const CONST = __nccwpck_require__(4097); -const GithubUtils = __nccwpck_require__(9296); - -const issueNumber = core.getInput('ISSUE_NUMBER', {required: true}); -const comment = core.getInput('COMMENT', {required: true}); - -function reopenIssueWithComment() { - console.log(`Reopening issue #${issueNumber}`); - return GithubUtils.octokit.issues - .update({ - owner: CONST.GITHUB_OWNER, - repo: CONST.APP_REPO, - issue_number: issueNumber, - state: 'open', - }) - .then(() => { - console.log(`Commenting on issue #${issueNumber}`); - return GithubUtils.octokit.issues.createComment({ - owner: CONST.GITHUB_OWNER, - repo: CONST.APP_REPO, - issue_number: issueNumber, - body: comment, - }); - }); -} - -reopenIssueWithComment() - .then(() => { - console.log(`Issue #${issueNumber} successfully reopened and commented: "${comment}"`); - process.exit(0); - }) - .catch((err) => { - console.error(`Something went wrong. The issue #${issueNumber} was not successfully reopened`, err); - core.setFailed(err); - }); - -})(); - -module.exports = __webpack_exports__; +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module is referenced by other modules so it can't be inlined +/******/ var __webpack_exports__ = __nccwpck_require__(7254); +/******/ module.exports = __webpack_exports__; +/******/ /******/ })() ; diff --git a/.github/actions/javascript/reopenIssueWithComment/reopenIssueWithComment.js b/.github/actions/javascript/reopenIssueWithComment/reopenIssueWithComment.ts similarity index 64% rename from .github/actions/javascript/reopenIssueWithComment/reopenIssueWithComment.js rename to .github/actions/javascript/reopenIssueWithComment/reopenIssueWithComment.ts index 2542372ec75e..c889d0d150a2 100644 --- a/.github/actions/javascript/reopenIssueWithComment/reopenIssueWithComment.js +++ b/.github/actions/javascript/reopenIssueWithComment/reopenIssueWithComment.ts @@ -1,16 +1,18 @@ -const core = require('@actions/core'); -const CONST = require('../../../libs/CONST'); -const GithubUtils = require('../../../libs/GithubUtils'); +import * as core from '@actions/core'; +import CONST from '@github/libs/CONST'; +import GithubUtils from '@github/libs/GithubUtils'; +import type {CreateCommentResponse} from '@github/libs/GithubUtils'; -const issueNumber = core.getInput('ISSUE_NUMBER', {required: true}); +const issueNumber = Number(core.getInput('ISSUE_NUMBER', {required: true})); const comment = core.getInput('COMMENT', {required: true}); -function reopenIssueWithComment() { +function reopenIssueWithComment(): Promise { console.log(`Reopening issue #${issueNumber}`); return GithubUtils.octokit.issues .update({ owner: CONST.GITHUB_OWNER, repo: CONST.APP_REPO, + // eslint-disable-next-line @typescript-eslint/naming-convention issue_number: issueNumber, state: 'open', }) @@ -19,6 +21,7 @@ function reopenIssueWithComment() { return GithubUtils.octokit.issues.createComment({ owner: CONST.GITHUB_OWNER, repo: CONST.APP_REPO, + // eslint-disable-next-line @typescript-eslint/naming-convention issue_number: issueNumber, body: comment, }); @@ -30,7 +33,7 @@ reopenIssueWithComment() console.log(`Issue #${issueNumber} successfully reopened and commented: "${comment}"`); process.exit(0); }) - .catch((err) => { + .catch((err: Error) => { console.error(`Something went wrong. The issue #${issueNumber} was not successfully reopened`, err); core.setFailed(err); }); diff --git a/.github/actions/javascript/reviewerChecklist/index.js b/.github/actions/javascript/reviewerChecklist/index.js index b63c55ae5eb8..f8487d8001a2 100644 --- a/.github/actions/javascript/reviewerChecklist/index.js +++ b/.github/actions/javascript/reviewerChecklist/index.js @@ -11543,6 +11543,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/actions/javascript/validateReassureOutput/index.js b/.github/actions/javascript/validateReassureOutput/index.js index e70c379697cd..99881e8ad9db 100644 --- a/.github/actions/javascript/validateReassureOutput/index.js +++ b/.github/actions/javascript/validateReassureOutput/index.js @@ -4,60 +4,6 @@ /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 688: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - -const core = __nccwpck_require__(186); -const fs = __nccwpck_require__(147); - -const run = () => { - const regressionOutput = JSON.parse(fs.readFileSync('.reassure/output.json', 'utf8')); - const countDeviation = core.getInput('COUNT_DEVIATION', {required: true}); - const durationDeviation = core.getInput('DURATION_DEVIATION_PERCENTAGE', {required: true}); - - if (regressionOutput.countChanged === undefined || regressionOutput.countChanged.length === 0) { - console.log('No countChanged data available. Exiting...'); - return true; - } - - console.log(`Processing ${regressionOutput.countChanged.length} measurements...`); - - for (let i = 0; i < regressionOutput.countChanged.length; i++) { - const measurement = regressionOutput.countChanged[i]; - const baseline = measurement.baseline; - const current = measurement.current; - - console.log(`Processing measurement ${i + 1}: ${measurement.name}`); - - const renderCountDiff = current.meanCount - baseline.meanCount; - if (renderCountDiff > countDeviation) { - core.setFailed(`Render count difference exceeded the allowed deviation of ${countDeviation}. Current difference: ${renderCountDiff}`); - break; - } else { - console.log(`Render count difference ${renderCountDiff} is within the allowed deviation range of ${countDeviation}.`); - } - - const increasePercentage = ((current.meanDuration - baseline.meanDuration) / baseline.meanDuration) * 100; - if (increasePercentage > durationDeviation) { - core.setFailed(`Duration increase percentage exceeded the allowed deviation of ${durationDeviation}%. Current percentage: ${increasePercentage}%`); - break; - } else { - console.log(`Duration increase percentage ${increasePercentage}% is within the allowed deviation range of ${durationDeviation}%.`); - } - } - - return true; -}; - -if (require.main === require.cache[eval('__filename')]) { - run(); -} - -module.exports = run; - - -/***/ }), - /***/ 351: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { @@ -2743,6 +2689,81 @@ function version(uuid) { var _default = version; exports["default"] = _default; +/***/ }), + +/***/ 378: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const core = __importStar(__nccwpck_require__(186)); +const fs_1 = __importDefault(__nccwpck_require__(147)); +const run = () => { + const regressionOutput = JSON.parse(fs_1.default.readFileSync('.reassure/output.json', 'utf8')); + const countDeviation = Number(core.getInput('COUNT_DEVIATION', { required: true })); + const durationDeviation = Number(core.getInput('DURATION_DEVIATION_PERCENTAGE', { required: true })); + if (regressionOutput.countChanged === undefined || regressionOutput.countChanged.length === 0) { + console.log('No countChanged data available. Exiting...'); + return true; + } + console.log(`Processing ${regressionOutput.countChanged.length} measurements...`); + for (let i = 0; i < regressionOutput.countChanged.length; i++) { + const measurement = regressionOutput.countChanged[i]; + const baseline = measurement.baseline; + const current = measurement.current; + console.log(`Processing measurement ${i + 1}: ${measurement.name}`); + const renderCountDiff = current.meanCount - baseline.meanCount; + if (renderCountDiff > countDeviation) { + core.setFailed(`Render count difference exceeded the allowed deviation of ${countDeviation}. Current difference: ${renderCountDiff}`); + break; + } + else { + console.log(`Render count difference ${renderCountDiff} is within the allowed deviation range of ${countDeviation}.`); + } + const increasePercentage = ((current.meanDuration - baseline.meanDuration) / baseline.meanDuration) * 100; + if (increasePercentage > durationDeviation) { + core.setFailed(`Duration increase percentage exceeded the allowed deviation of ${durationDeviation}%. Current percentage: ${increasePercentage}%`); + break; + } + else { + console.log(`Duration increase percentage ${increasePercentage}% is within the allowed deviation range of ${durationDeviation}%.`); + } + } + return true; +}; +if (require.main === require.cache[eval('__filename')]) { + run(); +} +exports["default"] = run; + + /***/ }), /***/ 491: @@ -2875,7 +2896,7 @@ module.exports = require("util"); /******/ // startup /******/ // Load entry module and return exports /******/ // This entry module is referenced by other modules so it can't be inlined -/******/ var __webpack_exports__ = __nccwpck_require__(688); +/******/ var __webpack_exports__ = __nccwpck_require__(378); /******/ module.exports = __webpack_exports__; /******/ /******/ })() diff --git a/.github/actions/javascript/validateReassureOutput/validateReassureOutput.js b/.github/actions/javascript/validateReassureOutput/validateReassureOutput.ts similarity index 71% rename from .github/actions/javascript/validateReassureOutput/validateReassureOutput.js rename to .github/actions/javascript/validateReassureOutput/validateReassureOutput.ts index 214dc9e8b6d4..ad0f393a96a2 100644 --- a/.github/actions/javascript/validateReassureOutput/validateReassureOutput.js +++ b/.github/actions/javascript/validateReassureOutput/validateReassureOutput.ts @@ -1,10 +1,11 @@ -const core = require('@actions/core'); -const fs = require('fs'); +import * as core from '@actions/core'; +import type {CompareResult, PerformanceEntry} from '@callstack/reassure-compare/src/types'; +import fs from 'fs'; -const run = () => { - const regressionOutput = JSON.parse(fs.readFileSync('.reassure/output.json', 'utf8')); - const countDeviation = core.getInput('COUNT_DEVIATION', {required: true}); - const durationDeviation = core.getInput('DURATION_DEVIATION_PERCENTAGE', {required: true}); +const run = (): boolean => { + const regressionOutput: CompareResult = JSON.parse(fs.readFileSync('.reassure/output.json', 'utf8')); + const countDeviation = Number(core.getInput('COUNT_DEVIATION', {required: true})); + const durationDeviation = Number(core.getInput('DURATION_DEVIATION_PERCENTAGE', {required: true})); if (regressionOutput.countChanged === undefined || regressionOutput.countChanged.length === 0) { console.log('No countChanged data available. Exiting...'); @@ -15,8 +16,8 @@ const run = () => { for (let i = 0; i < regressionOutput.countChanged.length; i++) { const measurement = regressionOutput.countChanged[i]; - const baseline = measurement.baseline; - const current = measurement.current; + const baseline: PerformanceEntry = measurement.baseline; + const current: PerformanceEntry = measurement.current; console.log(`Processing measurement ${i + 1}: ${measurement.name}`); @@ -44,4 +45,4 @@ if (require.main === module) { run(); } -module.exports = run; +export default run; diff --git a/.github/actions/javascript/verifySignedCommits/index.js b/.github/actions/javascript/verifySignedCommits/index.js index 26c0757dcde7..2e199b82f31a 100644 --- a/.github/actions/javascript/verifySignedCommits/index.js +++ b/.github/actions/javascript/verifySignedCommits/index.js @@ -11543,6 +11543,7 @@ const POLL_RATE = 10000; exports.POLL_RATE = POLL_RATE; class GithubUtils { static internalOctokit; + static POLL_RATE; /** * Initialize internal octokit * diff --git a/.github/libs/GithubUtils.ts b/.github/libs/GithubUtils.ts index 52122702fb2d..9d536a1ac18b 100644 --- a/.github/libs/GithubUtils.ts +++ b/.github/libs/GithubUtils.ts @@ -75,6 +75,8 @@ type InternalOctokit = OctokitCore & Api & {paginate: PaginateInterface}; class GithubUtils { static internalOctokit: InternalOctokit | undefined; + static POLL_RATE: number; + /** * Initialize internal octokit * diff --git a/.github/scripts/buildActions.sh b/.github/scripts/buildActions.sh index f9ec44cc8c12..7175670ff3cf 100755 --- a/.github/scripts/buildActions.sh +++ b/.github/scripts/buildActions.sh @@ -17,14 +17,14 @@ declare -r GITHUB_ACTIONS=( "$ACTIONS_DIR/getPreviousVersion/getPreviousVersion.js" "$ACTIONS_DIR/getPullRequestDetails/getPullRequestDetails.js" "$ACTIONS_DIR/getReleaseBody/getReleaseBody.js" - "$ACTIONS_DIR/isStagingDeployLocked/isStagingDeployLocked.js" + "$ACTIONS_DIR/isStagingDeployLocked/isStagingDeployLocked.ts" "$ACTIONS_DIR/markPullRequestsAsDeployed/markPullRequestsAsDeployed.ts" - "$ACTIONS_DIR/postTestBuildComment/postTestBuildComment.js" - "$ACTIONS_DIR/reopenIssueWithComment/reopenIssueWithComment.js" + "$ACTIONS_DIR/postTestBuildComment/postTestBuildComment.ts" + "$ACTIONS_DIR/reopenIssueWithComment/reopenIssueWithComment.ts" "$ACTIONS_DIR/verifySignedCommits/verifySignedCommits.js" "$ACTIONS_DIR/authorChecklist/authorChecklist.ts" "$ACTIONS_DIR/reviewerChecklist/reviewerChecklist.js" - "$ACTIONS_DIR/validateReassureOutput/validateReassureOutput.js" + "$ACTIONS_DIR/validateReassureOutput/validateReassureOutput.ts" "$ACTIONS_DIR/getGraphiteString/getGraphiteString.ts" "$ACTIONS_DIR/getArtifactInfo/getArtifactInfo.ts" ) diff --git a/.github/scripts/createDocsRoutes.js b/.github/scripts/createDocsRoutes.ts similarity index 53% rename from .github/scripts/createDocsRoutes.js rename to .github/scripts/createDocsRoutes.ts index 7c9ac532850d..fc3f376a1774 100644 --- a/.github/scripts/createDocsRoutes.js +++ b/.github/scripts/createDocsRoutes.ts @@ -1,34 +1,66 @@ -const yaml = require('js-yaml'); -const fs = require('fs'); -const _ = require('underscore'); +import fs from 'fs'; +import yaml from 'js-yaml'; +import type {ValueOf} from 'type-fest'; -const warnMessage = (platform) => `Number of hubs in _routes.yml does not match number of hubs in docs/${platform}/articles. Please update _routes.yml with hub info.`; +type Article = { + href: string; + title: string; +}; + +type Section = { + href: string; + title: string; + articles?: Article[]; +}; + +type Hub = { + href: string; + title: string; + description: string; + icon: string; + articles?: Article[]; + sections?: Section[]; +}; + +type Platform = { + href: string; + hubs: Hub[]; +}; + +type DocsRoutes = { + platforms: Platform[]; +}; + +type HubEntriesKey = 'sections' | 'articles'; + +const warnMessage = (platform: string): string => `Number of hubs in _routes.yml does not match number of hubs in docs/${platform}/articles. Please update _routes.yml with hub info.`; const disclaimer = '# This file is auto-generated. Do not edit it directly. Use npm run createDocsRoutes instead.\n'; const docsDir = `${process.cwd()}/docs`; -const routes = yaml.load(fs.readFileSync(`${docsDir}/_data/_routes.yml`, 'utf8')); +const routes = yaml.load(fs.readFileSync(`${docsDir}/_data/_routes.yml`, 'utf8')) as DocsRoutes; const platformNames = { expensifyClassic: 'expensify-classic', newExpensify: 'new-expensify', -}; +} as const; /** - * @param {String} str - The string to convert to title case - * @returns {String} + * @param str - The string to convert to title case */ -function toTitleCase(str) { - return _.map(str.split(' '), (word, i) => { - if (i !== 0 && (word.toLowerCase() === 'a' || word.toLowerCase() === 'the' || word.toLowerCase() === 'and')) { - return word.toLowerCase(); - } - return word.charAt(0).toUpperCase() + word.substring(1); - }).join(' '); +function toTitleCase(str: string): string { + return str + .split(' ') + .map((word, index) => { + if (index !== 0 && (word.toLowerCase() === 'a' || word.toLowerCase() === 'the' || word.toLowerCase() === 'and')) { + return word.toLowerCase(); + } + return word.charAt(0).toUpperCase() + word.substring(1); + }) + .join(' '); } /** - * @param {String} filename - The name of the file - * @returns {Object} + * @param filename - The name of the file */ -function getArticleObj(filename) { +function getArticleObj(filename: string): Article { const href = filename.replace('.md', ''); return { href, @@ -39,15 +71,20 @@ function getArticleObj(filename) { /** * If the article / sections exist in the hub, then push the entry to the array. * Otherwise, create the array and push the entry to it. - * @param {*} hubs - The hubs array - * @param {*} hub - The hub we are iterating - * @param {*} key - If we want to push sections / articles - * @param {*} entry - The article / section to push + * @param hubs - The hubs array + * @param hub - The hub we are iterating + * @param key - If we want to push sections / articles + * @param entry - The article / section to push */ -function pushOrCreateEntry(hubs, hub, key, entry) { - const hubObj = _.find(hubs, (obj) => obj.href === hub); +function pushOrCreateEntry(hubs: Hub[], hub: string, key: TKey, entry: TKey extends 'sections' ? Section : Article) { + const hubObj = hubs.find((obj) => obj.href === hub); + + if (!hubObj) { + return; + } + if (hubObj[key]) { - hubObj[key].push(entry); + hubObj[key]?.push(entry); } else { hubObj[key] = [entry]; } @@ -55,12 +92,12 @@ function pushOrCreateEntry(hubs, hub, key, entry) { /** * Add articles and sections to hubs - * @param {Array} hubs - The hubs inside docs/articles/ for a platform - * @param {String} platformName - Expensify Classic or New Expensify - * @param {Array} routeHubs - The hubs insude docs/data/_routes.yml for a platform + * @param hubs - The hubs inside docs/articles/ for a platform + * @param platformName - Expensify Classic or New Expensify + * @param routeHubs - The hubs insude docs/data/_routes.yml for a platform */ -function createHubsWithArticles(hubs, platformName, routeHubs) { - _.each(hubs, (hub) => { +function createHubsWithArticles(hubs: string[], platformName: ValueOf, routeHubs: Hub[]) { + hubs.forEach((hub) => { // Iterate through each directory in articles fs.readdirSync(`${docsDir}/articles/${platformName}/${hub}`).forEach((fileOrFolder) => { // If the directory content is a markdown file, then it is an article @@ -72,7 +109,7 @@ function createHubsWithArticles(hubs, platformName, routeHubs) { // For readability, we will use the term section to refer to subfolders const section = fileOrFolder; - const articles = []; + const articles: Article[] = []; // Each subfolder will be a section containing articles fs.readdirSync(`${docsDir}/articles/${platformName}/${hub}/${section}`).forEach((subArticle) => { @@ -92,15 +129,15 @@ function run() { const expensifyClassicArticleHubs = fs.readdirSync(`${docsDir}/articles/${platformNames.expensifyClassic}`); const newExpensifyArticleHubs = fs.readdirSync(`${docsDir}/articles/${platformNames.newExpensify}`); - const expensifyClassicRoute = _.find(routes.platforms, (platform) => platform.href === platformNames.expensifyClassic); - const newExpensifyRoute = _.find(routes.platforms, (platform) => platform.href === platformNames.newExpensify); + const expensifyClassicRoute = routes.platforms.find((platform) => platform.href === platformNames.expensifyClassic); + const newExpensifyRoute = routes.platforms.find((platform) => platform.href === platformNames.newExpensify); - if (expensifyClassicArticleHubs.length !== expensifyClassicRoute.hubs.length) { + if (expensifyClassicArticleHubs.length !== expensifyClassicRoute?.hubs.length) { console.error(warnMessage(platformNames.expensifyClassic)); process.exit(1); } - if (newExpensifyArticleHubs.length !== newExpensifyRoute.hubs.length) { + if (newExpensifyArticleHubs.length !== newExpensifyRoute?.hubs.length) { console.error(warnMessage(platformNames.newExpensify)); process.exit(1); } diff --git a/.github/workflows/reassurePerformanceTests.yml b/.github/workflows/reassurePerformanceTests.yml index 9887943c77e0..98f876fd60e2 100644 --- a/.github/workflows/reassurePerformanceTests.yml +++ b/.github/workflows/reassurePerformanceTests.yml @@ -1,8 +1,11 @@ name: Reassure Performance Tests on: + push: + branches: [main] + paths-ignore: [docs/**, contributingGuides/**, jest/**, workflow_tests/**] pull_request: - types: [opened, synchronize, closed] + types: [opened, synchronize] branches-ignore: [staging, production] paths-ignore: [docs/**, .github/**, contributingGuides/**, tests/**, workflow_tests/**, '**.md', '**.sh'] diff --git a/.storybook/webpack.config.ts b/.storybook/webpack.config.ts index 2fdae76c1268..c8462db8c40b 100644 --- a/.storybook/webpack.config.ts +++ b/.storybook/webpack.config.ts @@ -31,49 +31,61 @@ switch (process.env.ENV) { } const env = dotenv.config({path: path.resolve(__dirname, `../${envFile}`)}); -const custom: CustomWebpackConfig = require('../config/webpack/webpack.common')({ +const custom: CustomWebpackConfig = require('../config/webpack/webpack.common').default({ envFile, }); const webpackConfig = ({config}: {config: Configuration}) => { - if (config.resolve && config.plugins && config.module) { - config.resolve.alias = { - 'react-native-config': 'react-web-config', - 'react-native$': 'react-native-web', - '@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.ts'), - '@react-navigation/native': path.resolve(__dirname, '../__mocks__/@react-navigation/native'), - ...custom.resolve.alias, - }; + if (!config.resolve) { + config.resolve = {}; + } + if (!config.plugins) { + config.plugins = []; + } + if (!config.module) { + config.module = {}; + } - // Necessary to overwrite the values in the existing DefinePlugin hardcoded to the Config staging values - const definePluginIndex = config.plugins.findIndex((plugin) => plugin instanceof DefinePlugin); - if (definePluginIndex !== -1 && config.plugins[definePluginIndex] instanceof DefinePlugin) { - const definePlugin = config.plugins[definePluginIndex] as DefinePlugin; - if (definePlugin.definitions) { - definePlugin.definitions.__REACT_WEB_CONFIG__ = JSON.stringify(env); - } - } - config.resolve.extensions = custom.resolve.extensions; + config.resolve.alias = { + 'react-native-config': 'react-web-config', + 'react-native$': 'react-native-web', + '@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.ts'), + '@react-navigation/native': path.resolve(__dirname, '../__mocks__/@react-navigation/native'), + ...custom.resolve.alias, + }; - const babelRulesIndex = custom.module.rules.findIndex((rule) => rule.loader === 'babel-loader'); - const babelRule = custom.module.rules[babelRulesIndex]; - if (babelRule) { - config.module.rules?.push(babelRule); - } + // We can ignore the "module not installed" warning from lottie-react-native + // because we are not using the library for JSON format of Lottie animations. + config.ignoreWarnings = [{module: new RegExp('node_modules/lottie-react-native/lib/module/LottieView/index.web.js')}]; - const fileLoaderRule = config.module.rules?.find( - (rule): rule is RuleSetRule => - typeof rule !== 'boolean' && typeof rule !== 'string' && typeof rule !== 'number' && !!rule?.test && rule.test instanceof RegExp && rule.test.test('.svg'), - ); - if (fileLoaderRule) { - fileLoaderRule.exclude = /\.svg$/; + // Necessary to overwrite the values in the existing DefinePlugin hardcoded to the Config staging values + const definePluginIndex = config.plugins.findIndex((plugin) => plugin instanceof DefinePlugin); + if (definePluginIndex !== -1 && config.plugins[definePluginIndex] instanceof DefinePlugin) { + const definePlugin = config.plugins[definePluginIndex] as DefinePlugin; + if (definePlugin.definitions) { + definePlugin.definitions.__REACT_WEB_CONFIG__ = JSON.stringify(env); } - config.module.rules?.push({ - test: /\.svg$/, - enforce: 'pre', - loader: require.resolve('@svgr/webpack'), - }); } + config.resolve.extensions = custom.resolve.extensions; + + const babelRulesIndex = custom.module.rules.findIndex((rule) => rule.loader === 'babel-loader'); + const babelRule = custom.module.rules[babelRulesIndex]; + if (babelRule) { + config.module.rules?.push(babelRule); + } + + const fileLoaderRule = config.module.rules?.find( + (rule): rule is RuleSetRule => + typeof rule !== 'boolean' && typeof rule !== 'string' && typeof rule !== 'number' && !!rule?.test && rule.test instanceof RegExp && rule.test.test('.svg'), + ); + if (fileLoaderRule) { + fileLoaderRule.exclude = /\.svg$/; + } + config.module.rules?.push({ + test: /\.svg$/, + enforce: 'pre', + loader: require.resolve('@svgr/webpack'), + }); return config; }; diff --git a/README.md b/README.md index 7019567c7acb..026a63606db0 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ If you're using another operating system, you will need to ensure `mkcert` is in ## Running the web app 🕸 * To run the **development web app**: `npm run web` -* Changes applied to Javascript will be applied automatically via WebPack as configured in `webpack.dev.js` +* Changes applied to Javascript will be applied automatically via WebPack as configured in `webpack.dev.ts` ## Running the iOS app 📱 For an M1 Mac, read this [SO](https://stackoverflow.com/questions/64901180/how-to-run-cocoapods-on-apple-silicon-m1) for installing cocoapods. diff --git a/android/app/build.gradle b/android/app/build.gradle index 143e64f6a2b4..6c89e3e2885f 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,8 +98,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001045703 - versionName "1.4.57-3" + versionCode 1001045903 + versionName "1.4.59-3" } flavorDimensions "default" diff --git a/android/app/src/main/java/com/expensify/chat/MainActivity.kt b/android/app/src/main/java/com/expensify/chat/MainActivity.kt index 935ba8c8825f..2daebb9b1c00 100644 --- a/android/app/src/main/java/com/expensify/chat/MainActivity.kt +++ b/android/app/src/main/java/com/expensify/chat/MainActivity.kt @@ -14,6 +14,8 @@ import com.facebook.react.ReactActivityDelegate import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled import com.facebook.react.defaults.DefaultReactActivityDelegate +import com.oblador.performance.RNPerformance + class MainActivity : ReactActivity() { /** * Returns the name of the main component registered from JavaScript. This is used to schedule @@ -82,4 +84,9 @@ class MainActivity : ReactActivity() { KeyCommandModule.getInstance().onKeyDownEvent(keyCode, event) return super.onKeyUp(keyCode, event) } + + override fun onStart() { + super.onStart() + RNPerformance.getInstance().mark("appCreationEnd", false); + } } diff --git a/android/app/src/main/java/com/expensify/chat/MainApplication.kt b/android/app/src/main/java/com/expensify/chat/MainApplication.kt index 2362af009979..e660a871359d 100644 --- a/android/app/src/main/java/com/expensify/chat/MainApplication.kt +++ b/android/app/src/main/java/com/expensify/chat/MainApplication.kt @@ -15,6 +15,7 @@ import com.facebook.react.defaults.DefaultReactNativeHost import com.facebook.react.modules.i18nmanager.I18nUtil import com.facebook.soloader.SoLoader import com.google.firebase.crashlytics.FirebaseCrashlytics +import com.oblador.performance.RNPerformance import expo.modules.ApplicationLifecycleDispatcher import expo.modules.ReactNativeHostWrapper @@ -42,6 +43,8 @@ class MainApplication : MultiDexApplication(), ReactApplication { override fun onCreate() { super.onCreate() + RNPerformance.getInstance().mark("appCreationStart", false); + if (isOnfidoProcess()) { return } diff --git a/assets/images/avatars/group/default-avatar_1.svg b/assets/images/avatars/group/default-avatar_1.svg new file mode 100644 index 000000000000..5d97c5bf855b --- /dev/null +++ b/assets/images/avatars/group/default-avatar_1.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_10.svg b/assets/images/avatars/group/default-avatar_10.svg new file mode 100644 index 000000000000..12c9dd76ae31 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_10.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_11.svg b/assets/images/avatars/group/default-avatar_11.svg new file mode 100644 index 000000000000..97f17f30f3a7 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_11.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_12.svg b/assets/images/avatars/group/default-avatar_12.svg new file mode 100644 index 000000000000..f917fb136582 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_12.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_13.svg b/assets/images/avatars/group/default-avatar_13.svg new file mode 100644 index 000000000000..9e59fb9123a5 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_13.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_14.svg b/assets/images/avatars/group/default-avatar_14.svg new file mode 100644 index 000000000000..ca071e488416 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_14.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_15.svg b/assets/images/avatars/group/default-avatar_15.svg new file mode 100644 index 000000000000..f227cc0717be --- /dev/null +++ b/assets/images/avatars/group/default-avatar_15.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_16.svg b/assets/images/avatars/group/default-avatar_16.svg new file mode 100644 index 000000000000..efbb85f0b13d --- /dev/null +++ b/assets/images/avatars/group/default-avatar_16.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_17.svg b/assets/images/avatars/group/default-avatar_17.svg new file mode 100644 index 000000000000..25c015c595ca --- /dev/null +++ b/assets/images/avatars/group/default-avatar_17.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_18.svg b/assets/images/avatars/group/default-avatar_18.svg new file mode 100644 index 000000000000..a58ee6e66eff --- /dev/null +++ b/assets/images/avatars/group/default-avatar_18.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_2.svg b/assets/images/avatars/group/default-avatar_2.svg new file mode 100644 index 000000000000..ff1cc3e6dd2d --- /dev/null +++ b/assets/images/avatars/group/default-avatar_2.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_3.svg b/assets/images/avatars/group/default-avatar_3.svg new file mode 100644 index 000000000000..dde31b5d02a0 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_3.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_4.svg b/assets/images/avatars/group/default-avatar_4.svg new file mode 100644 index 000000000000..f6d02801bc6b --- /dev/null +++ b/assets/images/avatars/group/default-avatar_4.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_5.svg b/assets/images/avatars/group/default-avatar_5.svg new file mode 100644 index 000000000000..fdabd36e2058 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_5.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_6.svg b/assets/images/avatars/group/default-avatar_6.svg new file mode 100644 index 000000000000..6f1c6b80eda6 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_6.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_7.svg b/assets/images/avatars/group/default-avatar_7.svg new file mode 100644 index 000000000000..62d9a8b76bb8 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_7.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_8.svg b/assets/images/avatars/group/default-avatar_8.svg new file mode 100644 index 000000000000..206b10c2322b --- /dev/null +++ b/assets/images/avatars/group/default-avatar_8.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/images/avatars/group/default-avatar_9.svg b/assets/images/avatars/group/default-avatar_9.svg new file mode 100644 index 000000000000..ffbe02ce57e8 --- /dev/null +++ b/assets/images/avatars/group/default-avatar_9.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/config/proxyConfig.js b/config/proxyConfig.ts similarity index 64% rename from config/proxyConfig.js rename to config/proxyConfig.ts index fa09c436461f..0fecef28c1cf 100644 --- a/config/proxyConfig.js +++ b/config/proxyConfig.ts @@ -3,7 +3,14 @@ * We only specify for staging URLs as API requests are sent to the production * servers by default. */ -module.exports = { +type ProxyConfig = { + STAGING: string; + STAGING_SECURE: string; +}; + +const proxyConfig: ProxyConfig = { STAGING: '/staging/', STAGING_SECURE: '/staging-secure/', }; + +export default proxyConfig; diff --git a/config/webpack/CustomVersionFilePlugin.js b/config/webpack/CustomVersionFilePlugin.js deleted file mode 100644 index ed7c0f3dca95..000000000000 --- a/config/webpack/CustomVersionFilePlugin.js +++ /dev/null @@ -1,33 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const APP_VERSION = require('../../package.json').version; - -/** - * Simple webpack plugin that writes the app version (from package.json) and the webpack hash to './version.json' - */ -class CustomVersionFilePlugin { - apply(compiler) { - compiler.hooks.done.tap( - this.constructor.name, - () => - new Promise((resolve, reject) => { - const versionPath = path.join(__dirname, '/../../dist/version.json'); - fs.mkdir(path.dirname(versionPath), {recursive: true}, (dirErr) => { - if (dirErr) { - reject(dirErr); - return; - } - fs.writeFile(versionPath, JSON.stringify({version: APP_VERSION}), 'utf8', (fileErr) => { - if (fileErr) { - reject(fileErr); - return; - } - resolve(); - }); - }); - }), - ); - } -} - -module.exports = CustomVersionFilePlugin; diff --git a/config/webpack/CustomVersionFilePlugin.ts b/config/webpack/CustomVersionFilePlugin.ts new file mode 100644 index 000000000000..96ab8e61e480 --- /dev/null +++ b/config/webpack/CustomVersionFilePlugin.ts @@ -0,0 +1,28 @@ +import fs from 'fs'; +import path from 'path'; +import type {Compiler} from 'webpack'; +import {version as APP_VERSION} from '../../package.json'; + +/** + * Simple webpack plugin that writes the app version (from package.json) and the webpack hash to './version.json' + */ +class CustomVersionFilePlugin { + apply(compiler: Compiler) { + compiler.hooks.done.tap(this.constructor.name, () => { + const versionPath = path.join(__dirname, '/../../dist/version.json'); + fs.mkdir(path.dirname(versionPath), {recursive: true}, (directoryError) => { + if (directoryError) { + throw directoryError; + } + fs.writeFile(versionPath, JSON.stringify({version: APP_VERSION}), {encoding: 'utf8'}, (error) => { + if (!error) { + return; + } + throw error; + }); + }); + }); + } +} + +export default CustomVersionFilePlugin; diff --git a/config/webpack/types.ts b/config/webpack/types.ts new file mode 100644 index 000000000000..45a81feb9bff --- /dev/null +++ b/config/webpack/types.ts @@ -0,0 +1,6 @@ +type Environment = { + file?: string; + platform?: 'web' | 'desktop'; +}; + +export default Environment; diff --git a/config/webpack/webpack.common.js b/config/webpack/webpack.common.ts similarity index 79% rename from config/webpack/webpack.common.js rename to config/webpack/webpack.common.ts index 2fed8a477aab..b0e301ef3a6c 100644 --- a/config/webpack/webpack.common.js +++ b/config/webpack/webpack.common.ts @@ -1,13 +1,17 @@ -const path = require('path'); -const fs = require('fs'); -const {IgnorePlugin, DefinePlugin, ProvidePlugin, EnvironmentPlugin} = require('webpack'); -const {CleanWebpackPlugin} = require('clean-webpack-plugin'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const CopyPlugin = require('copy-webpack-plugin'); -const dotenv = require('dotenv'); -const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer'); +import {CleanWebpackPlugin} from 'clean-webpack-plugin'; +import CopyPlugin from 'copy-webpack-plugin'; +import dotenv from 'dotenv'; +import fs from 'fs'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import path from 'path'; +import type {Configuration} from 'webpack'; +import {DefinePlugin, EnvironmentPlugin, IgnorePlugin, ProvidePlugin} from 'webpack'; +import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer'; +import CustomVersionFilePlugin from './CustomVersionFilePlugin'; +import type Environment from './types'; + +// require is necessary, there are no types for this package and the declaration file can't be seen by the build process which causes an error. const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin'); -const CustomVersionFilePlugin = require('./CustomVersionFilePlugin'); const includeModules = [ 'react-native-animatable', @@ -25,29 +29,25 @@ const includeModules = [ 'expo-av', ].join('|'); -const envToLogoSuffixMap = { +const environmentToLogoSuffixMap: Record = { production: '', staging: '-stg', dev: '-dev', adhoc: '-adhoc', }; -function mapEnvToLogoSuffix(envFile) { - let env = envFile.split('.')[2]; - if (typeof env === 'undefined') { - env = 'dev'; +function mapEnvironmentToLogoSuffix(environmentFile: string): string { + let environment = environmentFile.split('.')[2]; + if (typeof environment === 'undefined') { + environment = 'dev'; } - return envToLogoSuffixMap[env]; + return environmentToLogoSuffixMap[environment]; } /** * Get a production grade config for web or desktop - * @param {Object} env - * @param {String} env.envFile path to the env file to be used - * @param {'web'|'desktop'} env.platform - * @returns {Configuration} */ -const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ +const getCommonConfiguration = ({file = '.env', platform = 'web'}: Environment): Configuration => ({ mode: 'production', devtool: 'source-map', entry: { @@ -68,10 +68,10 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ new HtmlWebpackPlugin({ template: 'web/index.html', filename: 'index.html', - splashLogo: fs.readFileSync(path.resolve(__dirname, `../../assets/images/new-expensify${mapEnvToLogoSuffix(envFile)}.svg`), 'utf-8'), + splashLogo: fs.readFileSync(path.resolve(__dirname, `../../assets/images/new-expensify${mapEnvironmentToLogoSuffix(file)}.svg`), 'utf-8'), isWeb: platform === 'web', - isProduction: envFile === '.env.production', - isStaging: envFile === '.env.staging', + isProduction: file === '.env.production', + isStaging: file === '.env.staging', }), new PreloadWebpackPlugin({ rel: 'preload', @@ -121,12 +121,14 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ ...(platform === 'web' ? [new CustomVersionFilePlugin()] : []), new DefinePlugin({ ...(platform === 'desktop' ? {} : {process: {env: {}}}), - __REACT_WEB_CONFIG__: JSON.stringify(dotenv.config({path: envFile}).parsed), + // eslint-disable-next-line @typescript-eslint/naming-convention + __REACT_WEB_CONFIG__: JSON.stringify(dotenv.config({path: file}).parsed), // React Native JavaScript environment requires the global __DEV__ variable to be accessible. // react-native-render-html uses variable to log exclusively during development. // See https://reactnative.dev/docs/javascript-environment - __DEV__: /staging|prod|adhoc/.test(envFile) === false, + // eslint-disable-next-line @typescript-eslint/naming-convention + __DEV__: /staging|prod|adhoc/.test(file) === false, }), // This allows us to interactively inspect JS bundle contents @@ -203,21 +205,34 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ }, resolve: { alias: { + // eslint-disable-next-line @typescript-eslint/naming-convention 'react-native-config': 'react-web-config', + // eslint-disable-next-line @typescript-eslint/naming-convention 'react-native$': 'react-native-web', + // eslint-disable-next-line @typescript-eslint/naming-convention 'react-native-sound': 'react-native-web-sound', // Module alias for web & desktop // https://webpack.js.org/configuration/resolve/#resolvealias + // eslint-disable-next-line @typescript-eslint/naming-convention '@assets': path.resolve(__dirname, '../../assets'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@components': path.resolve(__dirname, '../../src/components/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@hooks': path.resolve(__dirname, '../../src/hooks/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@libs': path.resolve(__dirname, '../../src/libs/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@navigation': path.resolve(__dirname, '../../src/libs/Navigation/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@pages': path.resolve(__dirname, '../../src/pages/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@styles': path.resolve(__dirname, '../../src/styles/'), // This path is provide alias for files like `ONYXKEYS` and `CONST`. + // eslint-disable-next-line @typescript-eslint/naming-convention '@src': path.resolve(__dirname, '../../src/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@userActions': path.resolve(__dirname, '../../src/libs/actions/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@desktop': path.resolve(__dirname, '../../desktop'), }, @@ -242,6 +257,7 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ '.tsx', ], fallback: { + // eslint-disable-next-line @typescript-eslint/naming-convention 'process/browser': require.resolve('process/browser'), crypto: false, }, @@ -275,4 +291,4 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ }, }); -module.exports = webpackConfig; +export default getCommonConfiguration; diff --git a/config/webpack/webpack.desktop.js b/config/webpack/webpack.desktop.ts similarity index 56% rename from config/webpack/webpack.desktop.js rename to config/webpack/webpack.desktop.ts index 20ee4a4025df..09314a9c30db 100644 --- a/config/webpack/webpack.desktop.js +++ b/config/webpack/webpack.desktop.ts @@ -1,29 +1,28 @@ -const path = require('path'); -const webpack = require('webpack'); -const _ = require('underscore'); - -const desktopDependencies = require('../../desktop/package.json').dependencies; -const getCommonConfig = require('./webpack.common'); +import path from 'path'; +import type {Configuration} from 'webpack'; +import webpack from 'webpack'; +// eslint-disable-next-line @dword-design/import-alias/prefer-alias, import/no-relative-packages -- alias imports don't work for webpack +import {dependencies as desktopDependencies} from '../../desktop/package.json'; +import type Environment from './types'; +import getCommonConfiguration from './webpack.common'; /** * Desktop creates 2 configurations in parallel * 1. electron-main - the core that serves the app content * 2. web - the app content that would be rendered in electron * Everything is placed in desktop/dist and ready for packaging - * @param {Object} env - * @returns {webpack.Configuration[]} */ -module.exports = (env) => { - const rendererConfig = getCommonConfig({...env, platform: 'desktop'}); +const getConfiguration = (environment: Environment): Configuration[] => { + const rendererConfig = getCommonConfiguration({...environment, platform: 'desktop'}); const outputPath = path.resolve(__dirname, '../../desktop/dist'); rendererConfig.name = 'renderer'; - rendererConfig.output.path = path.join(outputPath, 'www'); + (rendererConfig.output ??= {}).path = path.join(outputPath, 'www'); // Expose react-native-config to desktop-main - const definePlugin = _.find(rendererConfig.plugins, (plugin) => plugin.constructor === webpack.DefinePlugin); + const definePlugin = rendererConfig.plugins?.find((plugin) => plugin?.constructor === webpack.DefinePlugin); - const mainProcessConfig = { + const mainProcessConfig: Configuration = { mode: 'production', name: 'desktop-main', target: 'electron-main', @@ -38,13 +37,15 @@ module.exports = (env) => { }, resolve: rendererConfig.resolve, plugins: [definePlugin], - externals: [..._.keys(desktopDependencies), 'fsevents'], + externals: [...Object.keys(desktopDependencies), 'fsevents'], node: { /** * Disables webpack processing of __dirname and __filename, so it works like in node * https://github.com/webpack/webpack/issues/2010 */ + // eslint-disable-next-line @typescript-eslint/naming-convention __dirname: false, + // eslint-disable-next-line @typescript-eslint/naming-convention __filename: false, }, module: { @@ -60,3 +61,5 @@ module.exports = (env) => { return [mainProcessConfig, rendererConfig]; }; + +export default getConfiguration; diff --git a/config/webpack/webpack.dev.js b/config/webpack/webpack.dev.ts similarity index 67% rename from config/webpack/webpack.dev.js rename to config/webpack/webpack.dev.ts index e28383eff557..8f32a2d95c99 100644 --- a/config/webpack/webpack.dev.js +++ b/config/webpack/webpack.dev.ts @@ -1,34 +1,39 @@ -const path = require('path'); -const portfinder = require('portfinder'); -const {DefinePlugin} = require('webpack'); -const {merge} = require('webpack-merge'); -const {TimeAnalyticsPlugin} = require('time-analytics-webpack-plugin'); -const getCommonConfig = require('./webpack.common'); +import path from 'path'; +import portfinder from 'portfinder'; +import {TimeAnalyticsPlugin} from 'time-analytics-webpack-plugin'; +import type {Configuration} from 'webpack'; +import {DefinePlugin} from 'webpack'; +import type {Configuration as DevServerConfiguration} from 'webpack-dev-server'; +import {merge} from 'webpack-merge'; +import type Environment from './types'; +import getCommonConfiguration from './webpack.common'; const BASE_PORT = 8082; /** * Configuration for the local dev server - * @param {Object} env - * @returns {Configuration} */ -module.exports = (env = {}) => +const getConfiguration = (environment: Environment): Promise => portfinder.getPortPromise({port: BASE_PORT}).then((port) => { // Check if the USE_WEB_PROXY variable has been provided // and rewrite any requests to the local proxy server - const proxySettings = + const proxySettings: Pick = process.env.USE_WEB_PROXY === 'false' ? {} : { proxy: { + // eslint-disable-next-line @typescript-eslint/naming-convention '/api': 'http://[::1]:9000', + // eslint-disable-next-line @typescript-eslint/naming-convention '/staging': 'http://[::1]:9000', + // eslint-disable-next-line @typescript-eslint/naming-convention '/chat-attachments': 'http://[::1]:9000', + // eslint-disable-next-line @typescript-eslint/naming-convention '/receipts': 'http://[::1]:9000', }, }; - const baseConfig = getCommonConfig(env); + const baseConfig = getCommonConfiguration(environment); const config = merge(baseConfig, { mode: 'development', @@ -55,12 +60,13 @@ module.exports = (env = {}) => }, plugins: [ new DefinePlugin({ + // eslint-disable-next-line @typescript-eslint/naming-convention 'process.env.PORT': port, }), ], cache: { type: 'filesystem', - name: env.platform || 'default', + name: environment.platform ?? 'default', buildDependencies: { // By default, webpack and loaders are build dependencies // This (also) makes all dependencies of this config file - build dependencies @@ -78,3 +84,5 @@ module.exports = (env = {}) => return TimeAnalyticsPlugin.wrap(config); }); + +export default getConfiguration; diff --git a/contributingGuides/APPLE_GOOGLE_SIGNIN.md b/contributingGuides/APPLE_GOOGLE_SIGNIN.md index 5c95dfb60950..e6b999b7cb01 100644 --- a/contributingGuides/APPLE_GOOGLE_SIGNIN.md +++ b/contributingGuides/APPLE_GOOGLE_SIGNIN.md @@ -146,7 +146,7 @@ After you've set ngrok up to be able to run on your machine (requires configurin ngrok http 8082 --host-header="dev.new.expensify.com:8082" --subdomain=mysubdomain ``` -The `--host-header` flag is there to avoid webpack errors with header validation. In addition, add `allowedHosts: 'all'` to the dev server config in `webpack.dev.js`: +The `--host-header` flag is there to avoid webpack errors with header validation. In addition, add `allowedHosts: 'all'` to the dev server config in `webpack.dev.ts`: ```js devServer: { @@ -243,9 +243,9 @@ Here's how you can re-enable the SSO buttons in development mode: => { - const devServer = `webpack-dev-server --config config/webpack/webpack.dev.js --port ${port} --env platform=desktop`; - const buildMain = 'webpack watch --config config/webpack/webpack.desktop.js --config-name desktop-main --mode=development'; + .then((port) => { + const devServer = `webpack-dev-server --config config/webpack/webpack.dev.ts --port ${port} --env platform=desktop`; + const buildMain = 'webpack watch --config config/webpack/webpack.desktop.ts --config-name desktop-main --mode=development'; const env = { PORT: port, diff --git a/docs/articles/expensify-classic/workspaces/Create-tags.md b/docs/articles/expensify-classic/workspaces/Create-tags.md new file mode 100644 index 000000000000..74967ee04c7a --- /dev/null +++ b/docs/articles/expensify-classic/workspaces/Create-tags.md @@ -0,0 +1,85 @@ +--- +title: Create tags +description: Code expenses by creating tags +--- +
+ +You can tag expenses for a specific department, project, location, cost center, customer, etc. You can also use different tags for each workspace to create customized coding for different employees. + +You can use single tags or multi-level tags: +- **Single Tags**: Employees click one dropdown to select one tag. Single tags are helpful if employees need to select only one tag from a list, for example their department. +- **Multi-level Tags**: Employees click multiple dropdowns to select more than one tag. You can also create dependent tags that only appear if another tag has already been selected. Multi-tags are helpful if you have multiple tags, for example projects, locations, cost centers, etc., for employees to select, or if you have dependent tags. For example, if an employee selects a specific department, another tag can appear where they have to select their project. + +To add your tags, you can either import them for an accounting system or spreadsheet, or add them manually. + +# Single tags + +## Import a spreadsheet + +You can add a list of single tags by importing them in a .csv, .txt, .xls, or .xlsx spreadsheet. + +1. Hover over Settings, then click **Workspaces**. +2. Click the **Group** tab on the left. +3. Click the desired workspace name. +4. Click the **Tags** tab on the left. +5. Click **Import from Spreadsheet**. +6. Review the guidelines, select the checkbox if your file has headers as the first row, and click **Upload File**. + +{% include info.html %} +Each time you upload a list of tags, it will override your previous list. To avoid losing tags, update your current spreadsheet and re-import it into Expensify. +{% include end-info.html %} + +## Manually add individual tags + +1. Hover over Settings, then click **Workspaces**. +2. Click the **Group** tab on the left. +3. Click the desired workspace name. +4. Click the **Tags** tab on the left. +5. Enter a tag name into the field and click **Add**. + +# Multi-level tags + +## Automatic import with accounting integration + +When you first connect your accounting integration (for example, QuickBooks Online, QuickBooks Desktop, Sage Intacct, Xero, or NetSuite), you’ll configure classes, customers, projects, departments locations, etc. that automatically import into Expensify as tags. + +1. To update your tags in Expensify, you must first update the tag in your accounting system. Then in Expensify, +2. Hover over Settings, then click **Workspaces**. +3. Click the **Group** tab on the left. +4. Click the desired workspace name. +5. Click the **Connections** tab on the left. +6. Click **Sync Now**. + +## Import a spreadsheet + +You can add a list of single tags by importing them in a .csv, .txt, .xls, or .xlsx spreadsheet. + +1. Determine whether you will use independent (a separate tag for department and project) or dependent tags (the project tags populate different options based on the department selected), and whether you will capture general ledge (GL) codes. Then use one of the following templates to build your tags list: + - [Dependent tags with GL codes](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fus.v-cdn.net%2F6030147%2Fuploads%2FO7G7UWJCCFXC%2Fdependant-tag-with-gl-code-template.xlsx) + - [Dependent tags without GL codes](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fus.v-cdn.net%2F6030147%2Fuploads%2FY7DCMUVLSHEO%2Fdependant-tag-without-gl-code-template.xlsx) + - [Independent tags with GL codes](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fs3-us-west-1.amazonaws.com%2Fconcierge-responses-expensify-com%2Fuploads%252F1618929581886-Independent%2Bwith%2BGL%2Bcodes%2Bformat%2B-%2BSheet1.csv) + - [Independent tags without GL codes](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fs3-us-west-1.amazonaws.com%2Fconcierge-responses-expensify-com%2Fuploads%252F1618929575401-Independent%2Bwithout%2BGL%2Bcodes%2Bformat%2B-%2BSheet1.csv) + +{% include info.html %} +If you have more than 50,000 tags, divide them into two separate files. +{% include end-info.html %} + +2. Hover over Settings, then click **Workspaces**. +3. Click the **Group** tab on the left. +4. Click the desired workspace name. +5. Click the **Tags** tab on the left. +6. Enable the “Use multiple levels of tags” option. +7. Click **Import from Spreadsheet**. +8. Select the applicable checkboxes and click **Upload Tags**. + +{% include info.html %} +Each time you upload a list of tags, it will override your previous list. To avoid losing tags, update your current spreadsheet and re-import it into Expensify. +{% include end-info.html %} + +# FAQs + +**Why can’t I see a "Do you want to use multiple level tags" option on my workspace.** + +If you are connected to an accounting integration, you will not see this feature. You will need to add those tags in your integration first, then sync the connection. + +
diff --git a/docs/articles/expensify-classic/workspaces/Tags.md b/docs/articles/expensify-classic/workspaces/Tags.md deleted file mode 100644 index d802a183c8ba..000000000000 --- a/docs/articles/expensify-classic/workspaces/Tags.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Workspace Tags ---- -# Overview -You can use tags to assign expenses to a specific department, project, location, cost center, and more. - -Note that tags function differently depending on whether or not you connect Expensify to a direct account integration (i.e., QuickBooks Online, NetSuite, etc.). With that said, this article covers tags that work for all account setups. -# How to use Tags -Tags are a workspace-level feature. They’re generally used to code expenses to things like customers, projects, locations, or departments. at the expense level. You can have different sets of tags for different workspaces, allowing you to customize coding for cohorts of employees. - -With that said, tags come in two forms: single tags and multi-level tags. - -## Single Tags -Single tags refer to the simplest version of tags, allowing users to code expenses on a single level. With a single tag setup, users will pick from the list of tags you created and make a single selection on each expense. -## Multi-Level Tags -On the other hand, Multi-Level Tags refer to a more advanced tagging system that allows you to code expenses in a hierarchical or nested manner. Unlike single tags, which are standalone labels, multi-level tags enable you to create a structured hierarchy of tags, with sub-tags nested within parent tags. This feature is particularly useful for organizations that require a more detailed and organized approach to expense tracking. -# How to import single tags (no accounting integration connected) -## Add single tags via spreadsheet -To set up Tags, follow these steps: -- Go to **Settings > Workspace > Group / Individual > [Workspace name] > Tags**. -- You can choose to add tags one by one, or upload them in bulk via a spreadsheet. - -After downloading the CSV and creating the tags you want to import, go to the Tags section in the policy editor: Settings > Workspaces > Group > [Workspace name] > Tags - Enable multi-level tags by toggling the button. -Click "Import from Spreadsheet" to bring in your CSV. - Indicate whether the first line contains the tag header. -Choose if the tag list is independent or dependent (matching your CSV). -Decide if your tags list includes GL codes. -Upload your CSV or TSV file. -Confirm your file and update your tags list. -## Manually add single tags - -If you need to add Tags to your workspace manually, you can follow the steps below. - -On web: - -1. Navigate to Settings > Workspace > Group / Individual > [Workspace name] > Tags. -2. Add new tags under Add a Category. - -On mobile: - -1. Tap the three-bar menu icon at the top left corner of the app -2. Tap on Settings in the menu on the left side -3. Scroll to the Workspace subhead and click on tags listed underneath the default policy -4. Add new categories by tapping the + button in the upper right corner. To delete a category, on iOS swipe left, on Android press and hold. Tap a category name to edit it. - -# How to import multi-level tags (no accounting integration connected) -To use multi-level tags, go to the Tags section in your workspace settings. -Toggle on "Do you want to use multiple levels of tags?" - -This feature is available for companies with group workspaces and helps accountants track more details in expenses. - -If you need to make changes to your multi-level tags, follow these steps: -1. Start by editing them in a CSV file. -2. Import the revised tags into Expensify. -3. Remember to back up your tags! Uploading a CSV will replace your existing settings. -4. Safest Option: Download the old CSV from the Tags page using 'Export to CSV,' make edits, then import it. - -## Manage multi-level tags -Once multi-level tagging has been set up, employees will be able to choose more than one tag per expense. Based on the choice made for the first tag, the second subset of tag options will appear. After the second tag is chosen, more tag lists can appear, customizable up to 5 tag levels. - -### Best Practices -- Multi-level tagging is available for companies on group workspaces and is intended to help accountants track additional information at the expense line-item level. -- If you need to make any changes to the Tags, you need to first make them on the CSV and import the revised Tags into Expensify. -- Make sure to have a backup of your tags! Every time you upload a CSV it will override your previous settings. -- The easiest way to keep the old CSV is to download it from the Tags page by clicking Export to CSV, editing the list, and then importing it to apply the changes. - - -# How to import tags with an accounting integration connected -If you have connected Expensify to a direct integration such as QuickBooks Online, QuickBooks Desktop, Sage Intacct, Xero, or NetSuite, then Expensify automatically imports XYZ from your accounting system as tags. - -When you first connect your accounting integration you’ll configure classes, customers, projects, departments locations, etc. to import as tags in Expensify. - -If you need to update your tags in Expensify, you will first need to update them in your accounting system, then sync the connection in Expensify by navigating to Settings > Workspace > Group > [Workspace Name] > Connection > Sync Now. - -Alternatively, if you update the tag details in your accounting integration, be sure to sync the policy connection so that the updated information is available on the workspace. - -# Deep Dive -## Make tags required -You can require tags for any workspace expenses by enabling People must tag expenses on the Tags page by navigating to Settings > Workspace > Group > [Workspace Name] > Tags. -{% include faq-begin.md %} - -## What are the different tag options? -If you want your second tag to depend on the first one, use dependent tags. Include GL codes if needed, especially when using accounting integrations. -For other scenarios, like not using accounting integrations, use independent tags, which can still include GL codes if necessary. - - -## Are the multi-level tags only available with a certain subscription (pricing plan)? -Multi-level tagging is only available with the Control type policy. - -## I can’t see "Do you want to use multiple level tags" feature on my company's expense workspace. Why is that? -If you are connected to an accounting integration, you will not see this feature. You will need to add those tags in your integration first, then sync the connection. - -{% include faq-end.md %} diff --git a/docs/redirects.csv b/docs/redirects.csv index f239d95187c8..9c12c4b0048a 100644 --- a/docs/redirects.csv +++ b/docs/redirects.csv @@ -67,6 +67,12 @@ https://help.expensify.com/articles/expensify-classic/settings/Merge-Accounts,ht https://help.expensify.com/articles/expensify-classic/settings/Preferences,https://help.expensify.com/expensify-classic/hubs/settings/account-settings https://help.expensify.com/articles/expensify-classic/getting-started/support/Your-Expensify-Account-Manager,https://use.expensify.com/support https://help.expensify.com/articles/expensify-classic/settings/Copilot,https://help.expensify.com/expensify-classic/hubs/copilots-and-delegates/ +https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/reports/Currency,https://help.expensify.com/articles/expensify-classic/reports/Currency +https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/reports/Report-Fields-And-Titles,https://help.expensify.com/articles/expensify-classic/workspaces/reports/Report-Fields-And-Titles +https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/reports/Scheduled-Submit,https://help.expensify.com/articles/expensify-classic/workspaces/reports/Scheduled-Submit +https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/Categories,https://help.expensify.com/articles/expensify-classic/workspaces/Categori +https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/Expenses,https://help.expensify.com/expensify-classic/hubs/expenses/ +https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/Per-Diem,https://help.expensify.com/articles/expensify-classic/expenses/Per-Diem-Expenses https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/Budgets,https://help.expensify.com/articles/expensify-classic/workspaces/Budgets https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/Reimbursement,https://help.expensify.com/articles/expensify-classic/send-payments/Reimbursing-Reports https://help.expensify.com/articles/expensify-classic/workspace-and-domain-settings/Tags,https://help.expensify.com/articles/expensify-classic/workspaces/Tags diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 99be3c26fe5e..5d6f6a7a3323 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.4.57 + 1.4.59 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.57.3 + 1.4.59.3 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index fa9307884b76..30134e79913b 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.4.57 + 1.4.59 CFBundleSignature ???? CFBundleVersion - 1.4.57.3 + 1.4.59.3 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 953c4eaff93a..feb591137812 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -11,9 +11,9 @@ CFBundleName $(PRODUCT_NAME) CFBundleShortVersionString - 1.4.57 + 1.4.59 CFBundleVersion - 1.4.57.3 + 1.4.59.3 NSExtension NSExtensionPointIdentifier diff --git a/ios/Podfile.lock b/ios/Podfile.lock index a7b017e734e2..24ef0704be25 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1363,7 +1363,7 @@ PODS: - RNGoogleSignin (10.0.1): - GoogleSignIn (~> 7.0) - React-Core - - RNLiveMarkdown (0.1.33): + - RNLiveMarkdown (0.1.35): - glog - RCT-Folly (= 2022.05.16.00) - React-Core @@ -1904,7 +1904,7 @@ SPEC CHECKSUMS: RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 RNGestureHandler: 25b969a1ffc806b9f9ad2e170d4a3b049c6af85e RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 - RNLiveMarkdown: aaf75630fb2129db43fb5a873d33125e7173f3a0 + RNLiveMarkdown: aaf5afb231515d8ddfdef5f2928581e8ff606ad4 RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 rnmapbox-maps: fcf7f1cbdc8bd7569c267d07284e8a5c7bee06ed RNPermissions: 9b086c8f05b2e2faa587fdc31f4c5ab4509728aa diff --git a/package-lock.json b/package-lock.json index 2bfb6ab35ac5..4729cffea763 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,17 @@ { "name": "new.expensify", - "version": "1.4.57-3", + "version": "1.4.59-3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.57-3", + "version": "1.4.59-3", "hasInstallScript": true, "license": "MIT", "dependencies": { "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.33", + "@expensify/react-native-live-markdown": "0.1.35", "@expo/metro-runtime": "~3.1.1", "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-listformat": "^7.2.2", @@ -50,7 +50,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#f7efbd084536c140e65b49cd15f67ad8a2a10675", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#1247a822328011083a13abc769ba1911c3586338", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", @@ -88,7 +88,7 @@ "react-native-google-places-autocomplete": "2.5.6", "react-native-haptic-feedback": "^2.2.0", "react-native-image-picker": "^7.0.3", - "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#8393b7e58df6ff65fd41f60aee8ece8822c91e2b", + "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#bf3ad41a61c4f6f80ed4d497599ef5247a2dd002", "react-native-key-command": "^1.0.6", "react-native-launch-arguments": "^4.0.2", "react-native-linear-gradient": "^2.8.1", @@ -182,6 +182,8 @@ "@types/semver": "^7.5.4", "@types/setimmediate": "^1.0.2", "@types/underscore": "^1.11.5", + "@types/webpack": "^5.28.5", + "@types/webpack-bundle-analyzer": "^4.7.0", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", "@vercel/ncc": "0.38.1", @@ -194,9 +196,9 @@ "babel-plugin-react-native-web": "^0.18.7", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-remove-console": "^6.9.4", - "clean-webpack-plugin": "^3.0.0", + "clean-webpack-plugin": "^4.0.0", "concurrently": "^8.2.2", - "copy-webpack-plugin": "^6.4.1", + "copy-webpack-plugin": "^10.1.0", "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", @@ -3095,9 +3097,9 @@ } }, "node_modules/@expensify/react-native-live-markdown": { - "version": "0.1.33", - "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.33.tgz", - "integrity": "sha512-K9WDwb7wdupGrOrZEFFQ57qNPYdGVNkF5qnhOfkhuvSL9UdZi3NLiyGzaohIIh1lXvElDgwaY0x0WtqkOXIsiw==", + "version": "0.1.35", + "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.35.tgz", + "integrity": "sha512-W0FFIiU/sT+AwIrIOUHiNAHYjODAkEdYsf75tfBbkA6v2byHPxUlbzaJrZEQc0HgbvtAfTf9iQQqGWjNqe4pog==", "engines": { "node": ">= 18.0.0" }, @@ -6792,6 +6794,61 @@ "version": "2.0.1", "license": "BSD-3-Clause" }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@mapbox/point-geometry": { "version": "0.1.0", "license": "ISC" @@ -8129,8 +8186,9 @@ } }, "node_modules/@react-native-community/cli-doctor/node_modules/ip": { - "version": "1.1.8", - "license": "MIT" + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==" }, "node_modules/@react-native-community/cli-doctor/node_modules/strip-ansi": { "version": "5.2.0", @@ -8212,8 +8270,9 @@ } }, "node_modules/@react-native-community/cli-hermes/node_modules/ip": { - "version": "1.1.8", - "license": "MIT" + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.9.tgz", + "integrity": "sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==" }, "node_modules/@react-native-community/cli-hermes/node_modules/supports-color": { "version": "7.2.0", @@ -11918,6 +11977,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/builder-webpack4/node_modules/@types/webpack": { + "version": "4.41.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/helper-buffer": { "version": "1.9.0", "dev": true, @@ -14435,6 +14507,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/core-server/node_modules/@types/webpack": { + "version": "4.41.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/@storybook/core-server/node_modules/@webassemblyjs/helper-buffer": { "version": "1.9.0", "dev": true, @@ -15411,6 +15496,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/manager-webpack4/node_modules/@types/webpack": { + "version": "4.41.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/helper-buffer": { "version": "1.9.0", "dev": true, @@ -18827,7 +18925,7 @@ } }, "node_modules/@types/source-list-map": { - "version": "0.1.2", + "version": "0.1.6", "dev": true, "license": "MIT" }, @@ -18845,7 +18943,7 @@ "license": "MIT" }, "node_modules/@types/uglify-js": { - "version": "3.17.0", + "version": "3.17.5", "dev": true, "license": "MIT", "dependencies": { @@ -18873,16 +18971,31 @@ "optional": true }, "node_modules/@types/webpack": { - "version": "4.41.32", + "version": "5.28.5", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", - "@types/tapable": "^1", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "anymatch": "^3.0.0", - "source-map": "^0.6.0" + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/webpack-bundle-analyzer": { + "version": "4.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/webpack-bundle-analyzer/node_modules/tapable": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" } }, "node_modules/@types/webpack-env": { @@ -18891,7 +19004,7 @@ "license": "MIT" }, "node_modules/@types/webpack-sources": { - "version": "3.2.0", + "version": "3.2.3", "dev": true, "license": "MIT", "dependencies": { @@ -18908,6 +19021,14 @@ "node": ">= 8" } }, + "node_modules/@types/webpack/node_modules/tapable": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/@types/ws": { "version": "8.5.3", "dev": true, @@ -19884,6 +20005,11 @@ "version": "2.0.6", "license": "BSD-3-Clause" }, + "node_modules/abbrev": { + "version": "1.1.1", + "license": "ISC", + "optional": true + }, "node_modules/abort-controller": { "version": "3.0.0", "license": "MIT", @@ -20397,7 +20523,7 @@ }, "node_modules/aproba": { "version": "1.2.0", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/archiver": { @@ -20463,7 +20589,7 @@ }, "node_modules/are-we-there-yet": { "version": "2.0.0", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "delegates": "^1.0.0", @@ -20475,7 +20601,7 @@ }, "node_modules/are-we-there-yet/node_modules/readable-stream": { "version": "3.6.2", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -22792,6 +22918,20 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvas": { + "version": "2.11.2", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/canvas-size": { "version": "1.2.6", "license": "MIT" @@ -23086,8 +23226,10 @@ }, "node_modules/classnames": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.0.tgz", - "integrity": "sha512-FQuRlyKinxrb5gwJlfVASbSrDlikDJ07426TrfPsdGLvtochowmkbnSFdQGJ2aoXrSetq5KqGV9emvWpy+91xA==" + "license": "MIT", + "workspaces": [ + "benchmarks" + ] }, "node_modules/clean-css": { "version": "5.3.2", @@ -23107,18 +23249,17 @@ } }, "node_modules/clean-webpack-plugin": { - "version": "3.0.0", + "version": "4.0.0", "dev": true, "license": "MIT", "dependencies": { - "@types/webpack": "^4.4.31", "del": "^4.1.1" }, "engines": { - "node": ">=8.9.0" + "node": ">=10.0.0" }, "peerDependencies": { - "webpack": "*" + "webpack": ">=4.0.0 <6.0.0" } }, "node_modules/cli-boxes": { @@ -23330,7 +23471,7 @@ }, "node_modules/color-support": { "version": "1.1.3", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "color-support": "bin.js" @@ -23791,7 +23932,7 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/constants-browserify": { @@ -23892,136 +24033,115 @@ } }, "node_modules/copy-webpack-plugin": { - "version": "6.4.1", + "version": "10.2.4", "dev": true, "license": "MIT", "dependencies": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 12.20.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" + "webpack": "^5.1.0" } }, - "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.2", + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", "dev": true, "license": "MIT", "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" + "fast-deep-equal": "^3.1.3" }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/copy-webpack-plugin/node_modules/find-up": { - "version": "4.1.0", + "node_modules/copy-webpack-plugin/node_modules/array-union": { + "version": "3.0.1", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/copy-webpack-plugin/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "p-locate": "^4.1.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/copy-webpack-plugin/node_modules/make-dir": { - "version": "3.1.0", + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "12.2.0", "dev": true, "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/copy-webpack-plugin/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">=8" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/copy-webpack-plugin/node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/copy-webpack-plugin/node_modules/serialize-javascript": { + "version": "6.0.2", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "randombytes": "^2.1.0" } }, - "node_modules/copy-webpack-plugin/node_modules/path-exists": { + "node_modules/copy-webpack-plugin/node_modules/slash": { "version": "4.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/copy-webpack-plugin/node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" + "node": ">=12" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/copy-webpack-plugin/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/core-js": { @@ -25151,7 +25271,7 @@ }, "node_modules/delegates": { "version": "1.0.0", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/denodeify": { @@ -25214,6 +25334,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/detect-libc": { + "version": "2.0.1", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "license": "MIT", @@ -27367,8 +27495,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#f7efbd084536c140e65b49cd15f67ad8a2a10675", - "integrity": "sha512-aLrSTuLNmp9yNJUhik/Uia5KaNVBKp7m+DStcPoed4hSe+tMBDT8HMez7PqO5uRC6GPFrbBr77Aa2AQOB7DVqQ==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#1247a822328011083a13abc769ba1911c3586338", + "integrity": "sha512-YqFwbL3B5XzdQ+4wmZqWcdAbRerGvP0ZvcJV2YTHETxlZdjc39AZ2gviaJhqmz8E4kTQIfgO6ii3n4bWSYKt5A==", "license": "MIT", "dependencies": { "classnames": "2.5.0", @@ -27523,14 +27651,16 @@ }, "node_modules/expo-image-loader": { "version": "4.6.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-4.6.0.tgz", + "integrity": "sha512-RHQTDak7/KyhWUxikn2yNzXL7i2cs16cMp6gEAgkHOjVhoCJQoOJ0Ljrt4cKQ3IowxgCuOrAgSUzGkqs7omj8Q==", "peerDependencies": { "expo": "*" } }, "node_modules/expo-image-manipulator": { "version": "11.8.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/expo-image-manipulator/-/expo-image-manipulator-11.8.0.tgz", + "integrity": "sha512-ZWVrHnYmwJq6h7auk+ropsxcNi+LyZcPFKQc8oy+JA0SaJosfShvkCm7RADWAunHmfPCmjHrhwPGEu/rs7WG/A==", "dependencies": { "expo-image-loader": "~4.6.0" }, @@ -28751,7 +28881,7 @@ }, "node_modules/gauge": { "version": "3.0.2", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", @@ -29225,7 +29355,7 @@ }, "node_modules/has-unicode": { "version": "2.0.1", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/has-value": { @@ -30442,9 +30572,10 @@ } }, "node_modules/ip": { - "version": "2.0.0", - "dev": true, - "license": "MIT" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", + "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==", + "dev": true }, "node_modules/ip-regex": { "version": "2.1.0", @@ -36353,7 +36484,6 @@ }, "node_modules/nan": { "version": "2.17.0", - "dev": true, "license": "MIT", "optional": true }, @@ -36673,7 +36803,7 @@ }, "node_modules/npmlog": { "version": "5.0.1", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "are-we-there-yet": "^2.0.0", @@ -37029,8 +37159,7 @@ }, "node_modules/onfido-sdk-ui": { "version": "14.15.0", - "resolved": "https://registry.npmjs.org/onfido-sdk-ui/-/onfido-sdk-ui-14.15.0.tgz", - "integrity": "sha512-4Z+tnH6pQjK4SyazlzJq17NXO8AnhGcwEACbA3PVbAo90LBpGu1WAZ1r6VidlxFr/oPbu6sg/hisYvfXiqOtTg==" + "license": "SEE LICENSE in LICENSE" }, "node_modules/open": { "version": "8.4.2", @@ -39277,8 +39406,7 @@ }, "node_modules/react-native-image-size": { "version": "1.1.3", - "resolved": "git+ssh://git@github.com/Expensify/react-native-image-size.git#8393b7e58df6ff65fd41f60aee8ece8822c91e2b", - "integrity": "sha512-TDqeqGrxL+iRweaiDxg0jlMOmW8/7bti9PFi8rSRgGdiyu7loiuq4tmTGPAOefQtgDxoNRdSviH5isUyd3FV8g==", + "resolved": "git+ssh://git@github.com/Expensify/react-native-image-size.git#bf3ad41a61c4f6f80ed4d497599ef5247a2dd002", "license": "MIT" }, "node_modules/react-native-key-command": { @@ -39494,8 +39622,10 @@ }, "node_modules/react-native-release-profiler": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/react-native-release-profiler/-/react-native-release-profiler-0.1.6.tgz", - "integrity": "sha512-kSAPYjO3PDzV4xbjgj2NoiHtL7EaXmBira/WOcyz6S7mz1MVBoF0Bj74z5jAZo6BoBJRKqmQWI4ep+m0xvoF+g==", + "license": "MIT", + "workspaces": [ + "example" + ], "dependencies": { "@react-native-community/cli": "^12.2.1", "commander": "^11.1.0" @@ -39513,8 +39643,7 @@ }, "node_modules/react-native-release-profiler/node_modules/commander": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", "engines": { "node": ">=16" } @@ -39582,8 +39711,7 @@ }, "node_modules/react-native-share": { "version": "10.0.2", - "resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-10.0.2.tgz", - "integrity": "sha512-EZs4MtsyauAI1zP8xXT1hIFB/pXOZJNDCKcgCpEfTZFXgCUzz8MDVbI1ocP2hA59XHRSkqAQdbJ0BFTpjxOBlg==", + "license": "MIT", "engines": { "node": ">=16" } @@ -41925,6 +42053,57 @@ "version": "3.0.7", "license": "ISC" }, + "node_modules/simple-concat": { + "version": "1.0.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "3.1.1", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "4.2.1", + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/simple-get/node_modules/mimic-response": { + "version": "2.1.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/simple-git": { "version": "3.19.0", "license": "MIT", @@ -46190,7 +46369,7 @@ }, "node_modules/wide-align": { "version": "1.1.5", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" diff --git a/package.json b/package.json index 3abf8e2be02a..61e3557bbe67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.57-3", + "version": "1.4.59-3", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", @@ -20,14 +20,14 @@ "start": "npx react-native start", "web": "scripts/set-pusher-suffix.sh && concurrently npm:web-proxy npm:web-server", "web-proxy": "ts-node web/proxy.ts", - "web-server": "webpack-dev-server --open --config config/webpack/webpack.dev.js", - "build": "webpack --config config/webpack/webpack.common.js --env envFile=.env.production", - "build-staging": "webpack --config config/webpack/webpack.common.js --env envFile=.env.staging", - "build-adhoc": "webpack --config config/webpack/webpack.common.js --env envFile=.env.adhoc", + "web-server": "webpack-dev-server --open --config config/webpack/webpack.dev.ts", + "build": "webpack --config config/webpack/webpack.common.ts --env file=.env.production", + "build-staging": "webpack --config config/webpack/webpack.common.ts --env file=.env.staging", + "build-adhoc": "webpack --config config/webpack/webpack.common.ts --env file=.env.adhoc", "desktop": "scripts/set-pusher-suffix.sh && ts-node desktop/start.ts", "desktop-build": "scripts/build-desktop.sh production", "desktop-build-staging": "scripts/build-desktop.sh staging", - "createDocsRoutes": "ts-node .github/scripts/createDocsRoutes.js", + "createDocsRoutes": "ts-node .github/scripts/createDocsRoutes.ts", "desktop-build-adhoc": "scripts/build-desktop.sh adhoc", "ios-build": "fastlane ios build", "android-build": "fastlane android build", @@ -47,7 +47,7 @@ "storybook-build-staging": "ENV=staging build-storybook -o dist/docs", "gh-actions-build": "./.github/scripts/buildActions.sh", "gh-actions-validate": "./.github/scripts/validateActionsAndWorkflows.sh", - "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env envFile=.env.production", + "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.ts --env file=.env.production", "symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map", "symbolicate:ios": "npx metro-symbolicate main.jsbundle.map", "symbolicate-release:ios": "scripts/release-profile.ts --platform=ios", @@ -62,7 +62,7 @@ }, "dependencies": { "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.33", + "@expensify/react-native-live-markdown": "0.1.35", "@expo/metro-runtime": "~3.1.1", "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-listformat": "^7.2.2", @@ -101,7 +101,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#f7efbd084536c140e65b49cd15f67ad8a2a10675", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#1247a822328011083a13abc769ba1911c3586338", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", @@ -139,7 +139,7 @@ "react-native-google-places-autocomplete": "2.5.6", "react-native-haptic-feedback": "^2.2.0", "react-native-image-picker": "^7.0.3", - "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#8393b7e58df6ff65fd41f60aee8ece8822c91e2b", + "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#bf3ad41a61c4f6f80ed4d497599ef5247a2dd002", "react-native-key-command": "^1.0.6", "react-native-launch-arguments": "^4.0.2", "react-native-linear-gradient": "^2.8.1", @@ -233,6 +233,8 @@ "@types/semver": "^7.5.4", "@types/setimmediate": "^1.0.2", "@types/underscore": "^1.11.5", + "@types/webpack": "^5.28.5", + "@types/webpack-bundle-analyzer": "^4.7.0", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", "@vercel/ncc": "0.38.1", @@ -245,9 +247,9 @@ "babel-plugin-react-native-web": "^0.18.7", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-remove-console": "^6.9.4", - "clean-webpack-plugin": "^3.0.0", + "clean-webpack-plugin": "^4.0.0", + "copy-webpack-plugin": "^10.1.0", "concurrently": "^8.2.2", - "copy-webpack-plugin": "^6.4.1", "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", diff --git a/scripts/build-desktop.sh b/scripts/build-desktop.sh index efbca35a498c..791f59d73330 100755 --- a/scripts/build-desktop.sh +++ b/scripts/build-desktop.sh @@ -30,7 +30,7 @@ title "Bundling Desktop js Bundle Using Webpack" info " • ELECTRON_ENV: $ELECTRON_ENV" info " • ENV file: $ENV_FILE" info "" -npx webpack --config config/webpack/webpack.desktop.js --env envFile=$ENV_FILE +npx webpack --config config/webpack/webpack.desktop.ts --env file=$ENV_FILE title "Building Desktop App Archive Using Electron" info "" diff --git a/src/CONST.ts b/src/CONST.ts index c57ac575f7e6..e7358b382f14 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -46,6 +46,7 @@ const KEYBOARD_SHORTCUT_NAVIGATION_TYPE = 'NAVIGATION_SHORTCUT'; const chatTypes = { POLICY_ANNOUNCE: 'policyAnnounce', POLICY_ADMINS: 'policyAdmins', + GROUP: 'group', DOMAIN_ALL: 'domainAll', POLICY_ROOM: 'policyRoom', POLICY_EXPENSE_CHAT: 'policyExpenseChat', @@ -58,6 +59,9 @@ const cardActiveStates: number[] = [2, 3, 4, 7]; const CONST = { MERGED_ACCOUNT_PREFIX: 'MERGED_', DEFAULT_POLICY_ROOM_CHAT_TYPES: [chatTypes.POLICY_ADMINS, chatTypes.POLICY_ANNOUNCE, chatTypes.DOMAIN_ALL], + + // Note: Group and Self-DM excluded as these are not tied to a Workspace + WORKSPACE_ROOM_TYPES: [chatTypes.POLICY_ADMINS, chatTypes.POLICY_ANNOUNCE, chatTypes.DOMAIN_ALL, chatTypes.POLICY_ROOM, chatTypes.POLICY_EXPENSE_CHAT], ANDROID_PACKAGE_NAME, ANIMATED_TRANSITION: 300, ANIMATED_TRANSITION_FROM_VALUE: 100, @@ -117,6 +121,7 @@ const CONST = { NORMAL: 'normal', }, + DEFAULT_GROUP_AVATAR_COUNT: 18, DEFAULT_AVATAR_COUNT: 24, OLD_DEFAULT_AVATAR_COUNT: 8, @@ -329,7 +334,6 @@ const CONST = { ALL: 'all', CHRONOS_IN_CASH: 'chronosInCash', DEFAULT_ROOMS: 'defaultRooms', - BETA_COMMENT_LINKING: 'commentLinking', VIOLATIONS: 'violations', REPORT_FIELDS: 'reportFields', TRACK_EXPENSE: 'trackExpense', @@ -606,6 +610,10 @@ const CONST = { MAX_REPORT_PREVIEW_RECEIPTS: 3, }, REPORT: { + ROLE: { + ADMIN: 'admin', + MEMBER: 'member', + }, MAX_COUNT_BEFORE_FOCUS_UPDATE: 30, MAXIMUM_PARTICIPANTS: 8, SPLIT_REPORTID: '-2', @@ -1818,6 +1826,8 @@ const CONST = { RECEIPT: 'receipt', DISTANCE: 'distance', TAG: 'tag', + TAX_RATE: 'taxRate', + TAX_AMOUNT: 'taxAmount', }, FOOTER: { EXPENSE_MANAGEMENT_URL: `${USE_EXPENSIFY_URL}/expense-management`, @@ -3326,7 +3336,16 @@ const CONST = { }, /** - * Constants for types of violations. + * Constants for types of violation. + */ + VIOLATION_TYPES: { + VIOLATION: 'violation', + NOTICE: 'notice', + WARNING: 'warning', + }, + + /** + * Constants for types of violation names. * Defined here because they need to be referenced by the type system to generate the * ViolationNames type. */ diff --git a/src/Expensify.tsx b/src/Expensify.tsx index 026025593aef..6a57d6fdcc10 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -26,6 +26,7 @@ import NavigationRoot from './libs/Navigation/NavigationRoot'; import NetworkConnection from './libs/NetworkConnection'; import PushNotification from './libs/Notification/PushNotification'; import './libs/Notification/PushNotification/subscribePushNotification'; +import Performance from './libs/Performance'; import StartupTimer from './libs/StartupTimer'; // This lib needs to be imported, but it has nothing to export since all it contains is an Onyx connection import './libs/UnreadIndicatorUpdater'; @@ -130,6 +131,7 @@ function Expensify({ const onSplashHide = useCallback(() => { setIsSplashHidden(true); + Performance.markEnd(CONST.TIMING.SIDEBAR_LOADED); }, []); useLayoutEffect(() => { diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 41b030cf761f..46b2c5f8055c 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -294,6 +294,9 @@ const ONYXKEYS = { /** Indicates whether we should store logs or not */ SHOULD_STORE_LOGS: 'shouldStoreLogs', + /** Stores new group chat draft */ + NEW_GROUP_CHAT_DRAFT: 'newGroupChatDraft', + // Paths of PDF file that has been cached during one session CACHED_PDF_PATHS: 'cachedPDFPaths', @@ -532,7 +535,7 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT]: OnyxTypes.Transaction; [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags; [ONYXKEYS.COLLECTION.OLD_POLICY_RECENTLY_USED_TAGS]: OnyxTypes.RecentlyUsedTags; - [ONYXKEYS.COLLECTION.SELECTED_TAB]: string; + [ONYXKEYS.COLLECTION.SELECTED_TAB]: OnyxTypes.SelectedTabRequest; [ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string; [ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStep; [ONYXKEYS.COLLECTION.POLICY_JOIN_MEMBER]: OnyxTypes.PolicyJoinMember; @@ -552,6 +555,7 @@ type OnyxValuesMapping = { [ONYXKEYS.IOU]: OnyxTypes.IOU; [ONYXKEYS.MODAL]: OnyxTypes.Modal; [ONYXKEYS.NETWORK]: OnyxTypes.Network; + [ONYXKEYS.NEW_GROUP_CHAT_DRAFT]: OnyxTypes.NewGroupChatDraft; [ONYXKEYS.CUSTOM_STATUS_DRAFT]: OnyxTypes.CustomStatusDraft; [ONYXKEYS.INPUT_FOCUSED]: boolean; [ONYXKEYS.PERSONAL_DETAILS_LIST]: OnyxTypes.PersonalDetailsList; @@ -628,7 +632,7 @@ type OnyxValuesMapping = { [ONYXKEYS.RECENTLY_USED_REPORT_FIELDS]: OnyxTypes.RecentlyUsedReportFields; [ONYXKEYS.UPDATE_REQUIRED]: boolean; [ONYXKEYS.PLAID_CURRENT_EVENT]: string; - [ONYXKEYS.LOGS]: Record; + [ONYXKEYS.LOGS]: OnyxTypes.CapturedLogs; [ONYXKEYS.SHOULD_STORE_LOGS]: boolean; [ONYXKEYS.CACHED_PDF_PATHS]: Record; [ONYXKEYS.POLICY_OWNERSHIP_CHANGE_CHECKS]: Record; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 23bb2ee845ad..8130c271a2db 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -131,6 +131,16 @@ const ROUTES = { route: 'settings/profile/address/country', getRoute: (country: string, backTo?: string) => getUrlWithBackToParam(`settings/profile/address/country?country=${country}`, backTo), }, + SETTINGS_ADDRESS_STATE: { + route: 'settings/profile/address/state', + + getRoute: (state?: string, backTo?: string, label?: string) => + `${getUrlWithBackToParam(`settings/profile/address/state${state ? `?state=${encodeURIComponent(state)}` : ''}`, backTo)}${ + // the label param can be an empty string so we cannot use a nullish ?? operator + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + label ? `${backTo || state ? '&' : '?'}label=${encodeURIComponent(label)}` : '' + }` as const, + }, SETTINGS_CONTACT_METHODS: { route: 'settings/profile/contact-methods', getRoute: (backTo?: string) => getUrlWithBackToParam('settings/profile/contact-methods', backTo), @@ -174,6 +184,7 @@ const ROUTES = { NEW: 'new', NEW_CHAT: 'new/chat', + NEW_CHAT_CONFIRM: 'new/chat/confirm', NEW_ROOM: 'new/room', REPORT: 'r', @@ -276,18 +287,10 @@ const ROUTES = { route: 'r/:reportID/invite', getRoute: (reportID: string) => `r/${reportID}/invite` as const, }, - MONEY_REQUEST_AMOUNT: { - route: ':iouType/new/amount/:reportID?', - getRoute: (iouType: string, reportID = '') => `${iouType}/new/amount/${reportID}` as const, - }, MONEY_REQUEST_PARTICIPANTS: { route: ':iouType/new/participants/:reportID?', getRoute: (iouType: string, reportID = '') => `${iouType}/new/participants/${reportID}` as const, }, - MONEY_REQUEST_CONFIRMATION: { - route: ':iouType/new/confirmation/:reportID?', - getRoute: (iouType: string, reportID = '') => `${iouType}/new/confirmation/${reportID}` as const, - }, MONEY_REQUEST_CURRENCY: { route: ':iouType/new/currency/:reportID?', getRoute: (iouType: string, reportID: string, currency: string, backTo: string) => `${iouType}/new/currency/${reportID}?currency=${currency}&backTo=${backTo}` as const, @@ -307,16 +310,17 @@ const ROUTES = { MONEY_REQUEST_CREATE: { route: ':action/:iouType/start/:transactionID/:reportID', getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => - `create/${iouType}/start/${transactionID}/${reportID}` as const, + `${action}/${iouType}/start/${transactionID}/${reportID}` as const, }, MONEY_REQUEST_STEP_CONFIRMATION: { - route: 'create/:iouType/confirmation/:transactionID/:reportID', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string) => `create/${iouType}/confirmation/${transactionID}/${reportID}` as const, + route: ':action/:iouType/confirmation/:transactionID/:reportID', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => + `${action}/${iouType}/confirmation/${transactionID}/${reportID}` as const, }, MONEY_REQUEST_STEP_AMOUNT: { - route: 'create/:iouType/amount/:transactionID/:reportID', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => - getUrlWithBackToParam(`create/${iouType}/amount/${transactionID}/${reportID}`, backTo), + route: ':action/:iouType/amount/:transactionID/:reportID', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string, backTo = '') => + getUrlWithBackToParam(`${action}/${iouType}/amount/${transactionID}/${reportID}`, backTo), }, MONEY_REQUEST_STEP_TAX_RATE: { route: 'create/:iouType/taxRate/:transactionID/:reportID?', @@ -334,9 +338,9 @@ const ROUTES = { getUrlWithBackToParam(`${action}/${iouType}/category/${transactionID}/${reportID}${reportActionID ? `/${reportActionID}` : ''}`, backTo), }, MONEY_REQUEST_STEP_CURRENCY: { - route: 'create/:iouType/currency/:transactionID/:reportID/:pageIndex?', - getRoute: (iouType: ValueOf, transactionID: string, reportID: string, pageIndex = '', backTo = '') => - getUrlWithBackToParam(`create/${iouType}/currency/${transactionID}/${reportID}/${pageIndex}`, backTo), + route: ':action/:iouType/currency/:transactionID/:reportID/:pageIndex?', + getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string, pageIndex = '', backTo = '') => + getUrlWithBackToParam(`${action}/${iouType}/currency/${transactionID}/${reportID}/${pageIndex}`, backTo), }, MONEY_REQUEST_STEP_DATE: { route: ':action/:iouType/date/:transactionID/:reportID', @@ -399,7 +403,7 @@ const ROUTES = { MONEY_REQUEST_CREATE_TAB_MANUAL: { route: ':action/:iouType/start/:transactionID/:reportID/manual', getRoute: (action: ValueOf, iouType: ValueOf, transactionID: string, reportID: string) => - `create/${iouType}/start/${transactionID}/${reportID}/manual` as const, + `${action}/${iouType}/start/${transactionID}/${reportID}/manual` as const, }, MONEY_REQUEST_CREATE_TAB_SCAN: { route: ':action/:iouType/start/:transactionID/:reportID/scan', @@ -407,6 +411,16 @@ const ROUTES = { `create/${iouType}/start/${transactionID}/${reportID}/scan` as const, }, + MONEY_REQUEST_STATE_SELECTOR: { + route: 'request/state', + + getRoute: (state?: string, backTo?: string, label?: string) => + `${getUrlWithBackToParam(`request/state${state ? `?state=${encodeURIComponent(state)}` : ''}`, backTo)}${ + // the label param can be an empty string so we cannot use a nullish ?? operator + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + label ? `${backTo || state ? '&' : '?'}label=${encodeURIComponent(label)}` : '' + }` as const, + }, IOU_REQUEST: 'request/new', IOU_SEND: 'send/new', IOU_SEND_ADD_BANK_ACCOUNT: 'send/new/add-bank-account', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index ffb18391c980..cf864fd96b3e 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -56,6 +56,7 @@ const SCREENS = { DATE_OF_BIRTH: 'Settings_DateOfBirth', ADDRESS: 'Settings_Address', ADDRESS_COUNTRY: 'Settings_Address_Country', + ADDRESS_STATE: 'Settings_Address_State', }, PREFERENCES: { @@ -149,13 +150,12 @@ const SCREENS = { STEP_WAYPOINT: 'Money_Request_Step_Waypoint', STEP_TAX_AMOUNT: 'Money_Request_Step_Tax_Amount', STEP_TAX_RATE: 'Money_Request_Step_Tax_Rate', - AMOUNT: 'Money_Request_Amount', PARTICIPANTS: 'Money_Request_Participants', - CONFIRMATION: 'Money_Request_Confirmation', CURRENCY: 'Money_Request_Currency', WAYPOINT: 'Money_Request_Waypoint', EDIT_WAYPOINT: 'Money_Request_Edit_Waypoint', RECEIPT: 'Money_Request_Receipt', + STATE_SELECTOR: 'Money_Request_State_Selector', }, IOU_SEND: { @@ -261,6 +261,7 @@ const SCREENS = { NEW_CHAT: { ROOT: 'NewChat_Root', NEW_CHAT: 'chat', + NEW_CHAT_CONFIRM: 'NewChat_Confirm', NEW_ROOM: 'room', }, diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index 626da4cfd5d4..a4d1c2dd6bd6 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -16,7 +16,7 @@ import CountrySelector from './CountrySelector'; import FormProvider from './Form/FormProvider'; import InputWrapper from './Form/InputWrapper'; import type {FormOnyxValues} from './Form/types'; -import StatePicker from './StatePicker'; +import StateSelector from './StateSelector'; import TextInput from './TextInput'; type CountryZipRegex = { @@ -190,7 +190,7 @@ function AddressForm({ {isUSAForm ? ( { + ImageSize.getSize(fileDataUri).then(({width, height}) => { fileDataObject.width = width; fileDataObject.height = height; validateAndCompleteAttachmentSelection(fileDataObject); diff --git a/src/components/AvatarCropModal/AvatarCropModal.tsx b/src/components/AvatarCropModal/AvatarCropModal.tsx index eac41b6d627a..dcec2e14a9e7 100644 --- a/src/components/AvatarCropModal/AvatarCropModal.tsx +++ b/src/components/AvatarCropModal/AvatarCropModal.tsx @@ -1,8 +1,9 @@ import React, {useCallback, useEffect, useState} from 'react'; -import {ActivityIndicator, Image, View} from 'react-native'; +import {ActivityIndicator, View} from 'react-native'; import type {LayoutChangeEvent} from 'react-native'; import {Gesture, GestureHandlerRootView} from 'react-native-gesture-handler'; import type {GestureUpdateEvent, PanGestureChangeEventPayload, PanGestureHandlerEventPayload} from 'react-native-gesture-handler'; +import ImageSize from 'react-native-image-size'; import {interpolate, runOnUI, useSharedValue, useWorkletCallback} from 'react-native-reanimated'; import Button from '@components/Button'; import HeaderGap from '@components/HeaderGap'; @@ -118,7 +119,7 @@ function AvatarCropModal({imageUri = '', imageName = '', imageType = '', onClose if (!imageUri) { return; } - Image.getSize(imageUri, (width, height) => { + ImageSize.getSize(imageUri).then(({width, height}) => { // We need to have image sizes in shared values to properly calculate position/size/animation originalImageHeight.value = height; originalImageWidth.value = width; diff --git a/src/components/AvatarWithDisplayName.tsx b/src/components/AvatarWithDisplayName.tsx index f6afb4dae2d6..396c10151fbf 100644 --- a/src/components/AvatarWithDisplayName.tsx +++ b/src/components/AvatarWithDisplayName.tsx @@ -141,7 +141,6 @@ function AvatarWithDisplayName({ )} diff --git a/src/components/BlockingViews/BlockingView.tsx b/src/components/BlockingViews/BlockingView.tsx index 7b33c8054950..363342778fc0 100644 --- a/src/components/BlockingViews/BlockingView.tsx +++ b/src/components/BlockingViews/BlockingView.tsx @@ -1,9 +1,12 @@ -import React from 'react'; -import type {ImageSourcePropType} from 'react-native'; +import React, {useMemo} from 'react'; +import type {ImageSourcePropType, StyleProp, ViewStyle, WebStyle} from 'react-native'; import {View} from 'react-native'; import type {SvgProps} from 'react-native-svg'; +import type {MergeExclusive} from 'type-fest'; import AutoEmailLink from '@components/AutoEmailLink'; import Icon from '@components/Icon'; +import Lottie from '@components/Lottie'; +import type DotLottieAnimation from '@components/LottieAnimations/types'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; @@ -12,13 +15,7 @@ import Navigation from '@libs/Navigation/Navigation'; import variables from '@styles/variables'; import type {TranslationPaths} from '@src/languages/types'; -type BlockingViewProps = { - /** Expensicon for the page */ - icon: React.FC | ImageSourcePropType; - - /** Color for the icon (should be from theme) */ - iconColor?: string; - +type BaseBlockingViewProps = { /** Title message below the icon */ title: string; @@ -31,20 +28,46 @@ type BlockingViewProps = { /** Whether we should show a link to navigate elsewhere */ shouldShowLink?: boolean; + /** Function to call when pressing the navigation link */ + onLinkPress?: () => void; + + /** Whether we should embed the link with subtitle */ + shouldEmbedLinkWithSubtitle?: boolean; + + /** Render custom subtitle */ + CustomSubtitle?: React.ReactElement; +}; + +type BlockingViewIconProps = { + /** Expensicon for the page */ + icon: React.FC | ImageSourcePropType; + /** The custom icon width */ iconWidth?: number; /** The custom icon height */ iconHeight?: number; - /** Function to call when pressing the navigation link */ - onLinkPress?: () => void; + /** Color for the icon (should be from theme) */ + iconColor?: string; +}; - /** Whether we should embed the link with subtitle */ - shouldEmbedLinkWithSubtitle?: boolean; +type BlockingViewAnimationProps = { + /** Animation for the page */ + animation: DotLottieAnimation; + + /** Style for the animation */ + animationStyles?: StyleProp; + + /** Style for the animation on web */ + animationWebStyle?: WebStyle; }; +// This page requires either an icon or an animation, but not both +type BlockingViewProps = BaseBlockingViewProps & MergeExclusive; + function BlockingView({ + animation, icon, iconColor, title, @@ -55,11 +78,15 @@ function BlockingView({ iconHeight = variables.iconSizeSuperLarge, onLinkPress = () => Navigation.dismissModal(), shouldEmbedLinkWithSubtitle = false, + animationStyles = [], + animationWebStyle = {}, + CustomSubtitle, }: BlockingViewProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); - function renderContent() { - return ( + + const subtitleText = useMemo( + () => ( <> ) : null} + ), + [styles, subtitle, shouldShowLink, linkKey, onLinkPress, translate], + ); + + const subtitleContent = useMemo(() => { + if (CustomSubtitle) { + return CustomSubtitle; + } + return shouldEmbedLinkWithSubtitle ? ( + {subtitleText} + ) : ( + {subtitleText} ); - } + }, [styles, subtitleText, shouldEmbedLinkWithSubtitle, CustomSubtitle]); return ( - + {animation && ( + + )} + {icon && ( + + )} {title} - {shouldEmbedLinkWithSubtitle ? ( - {renderContent()} - ) : ( - {renderContent()} - )} + {subtitleContent} ); diff --git a/src/components/ButtonWithDropdownMenu/index.tsx b/src/components/ButtonWithDropdownMenu/index.tsx index 896330f5e77e..a4e6e2c87fec 100644 --- a/src/components/ButtonWithDropdownMenu/index.tsx +++ b/src/components/ButtonWithDropdownMenu/index.tsx @@ -8,7 +8,6 @@ import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import variables from '@styles/variables'; import CONST from '@src/CONST'; import type {AnchorPosition} from '@src/styles'; import type {ButtonWithDropdownMenuProps} from './types'; @@ -100,12 +99,12 @@ function ButtonWithDropdownMenu({ > - + diff --git a/src/components/ClientSideLoggingToolMenu/BaseClientSideLoggingToolMenu.tsx b/src/components/ClientSideLoggingToolMenu/BaseClientSideLoggingToolMenu.tsx new file mode 100644 index 000000000000..fcad770908a6 --- /dev/null +++ b/src/components/ClientSideLoggingToolMenu/BaseClientSideLoggingToolMenu.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import {Alert} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import type {OnyxEntry} from 'react-native-onyx'; +import Button from '@components/Button'; +import Switch from '@components/Switch'; +import TestToolRow from '@components/TestToolRow'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as Console from '@libs/actions/Console'; +import {parseStringifiedMessages} from '@libs/Console'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {CapturedLogs, Log} from '@src/types/onyx'; + +type BaseClientSideLoggingToolMenuOnyxProps = { + /** Logs captured on the current device */ + capturedLogs: OnyxEntry; + + /** Whether or not logs should be stored */ + shouldStoreLogs: OnyxEntry; +}; + +type BaseClientSideLoggingToolProps = { + /** Locally created file */ + file?: {path: string; newFileName: string; size: number}; + /** Action to run when pressing Share button */ + onShareLogs?: () => void; + /** Action to run when disabling the switch */ + onDisableLogging: (logs: Log[]) => void; + /** Action to run when enabling logging */ + onEnableLogging?: () => void; +} & BaseClientSideLoggingToolMenuOnyxProps; + +function BaseClientSideLoggingToolMenu({shouldStoreLogs, capturedLogs, file, onShareLogs, onDisableLogging, onEnableLogging}: BaseClientSideLoggingToolProps) { + const {translate} = useLocalize(); + + const onToggle = () => { + if (!shouldStoreLogs) { + Console.setShouldStoreLogs(true); + + if (onEnableLogging) { + onEnableLogging(); + } + + return; + } + + if (!capturedLogs) { + Alert.alert(translate('initialSettingsPage.troubleshoot.noLogsToShare')); + Console.disableLoggingAndFlushLogs(); + return; + } + + const logs = Object.values(capturedLogs); + const logsWithParsedMessages = parseStringifiedMessages(logs); + + onDisableLogging(logsWithParsedMessages); + Console.disableLoggingAndFlushLogs(); + }; + const styles = useThemeStyles(); + return ( + <> + + + + {!!file && ( + <> + {`path: ${file.path}`} + +