diff --git a/.eslintignore b/.eslintignore index 5338df11c520..aa8b769dfede 100644 --- a/.eslintignore +++ b/.eslintignore @@ -9,3 +9,4 @@ android/**/build/** docs/vendor/** docs/assets/** web/gtm.js +**/.expo/** diff --git a/.eslintrc.js b/.eslintrc.js index 9f839e45ce75..d8f8c15eb878 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,5 @@ +const path = require('path'); + const restrictedImportPaths = [ { name: 'react-native', @@ -96,7 +98,7 @@ module.exports = { plugins: ['@typescript-eslint', 'jsdoc', 'you-dont-need-lodash-underscore', 'react-native-a11y', 'react', 'testing-library'], parser: '@typescript-eslint/parser', parserOptions: { - project: './tsconfig.json', + project: path.resolve(__dirname, './tsconfig.json'), }, env: { jest: true, @@ -105,10 +107,9 @@ module.exports = { __DEV__: 'readonly', }, rules: { + // TypeScript specific rules '@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-unsafe-assignment': 'off', - - // TypeScript specific rules '@typescript-eslint/prefer-enum-initializers': 'error', '@typescript-eslint/no-var-requires': 'off', '@typescript-eslint/no-non-null-assertion': 'error', @@ -215,6 +216,8 @@ module.exports = { // Other rules curly: 'error', 'you-dont-need-lodash-underscore/throttle': 'off', + // The suggested alternative (structuredClone) is not supported in Hermes:https://github.com/facebook/hermes/issues/684 + 'you-dont-need-lodash-underscore/clone-deep': 'off', 'prefer-regex-literals': 'off', 'valid-jsdoc': 'off', 'jsdoc/no-types': 'error', @@ -257,6 +260,7 @@ module.exports = { // Remove once no JS files are left { files: ['*.js', '*.jsx'], + extends: ['plugin:@typescript-eslint/disable-type-checked'], rules: { '@typescript-eslint/prefer-nullish-coalescing': 'off', '@typescript-eslint/no-unsafe-return': 'off', diff --git a/.github/actions/javascript/authorChecklist/index.js b/.github/actions/javascript/authorChecklist/index.js index 1dace19d0a01..84624b6bfc6f 100644 --- a/.github/actions/javascript/authorChecklist/index.js +++ b/.github/actions/javascript/authorChecklist/index.js @@ -11710,7 +11710,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -17557,27 +17557,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/awaitStagingDeploys/index.js b/.github/actions/javascript/awaitStagingDeploys/index.js index c5ba4d9ca936..6ec9bbf06aeb 100644 --- a/.github/actions/javascript/awaitStagingDeploys/index.js +++ b/.github/actions/javascript/awaitStagingDeploys/index.js @@ -7373,7 +7373,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12822,27 +12822,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/bumpVersion/bumpVersion.ts b/.github/actions/javascript/bumpVersion/bumpVersion.ts index eba79c7c9edb..ff43ab9ee5c5 100644 --- a/.github/actions/javascript/bumpVersion/bumpVersion.ts +++ b/.github/actions/javascript/bumpVersion/bumpVersion.ts @@ -5,6 +5,7 @@ import type {PackageJson} from 'type-fest'; import {promisify} from 'util'; import {generateAndroidVersionCode, updateAndroidVersion, updateiOSVersion} from '@github/libs/nativeVersionUpdater'; import * as versionUpdater from '@github/libs/versionUpdater'; +import type {SemverLevel} from '@github/libs/versionUpdater'; const exec = promisify(originalExec); @@ -43,7 +44,7 @@ function updateNativeVersions(version: string) { } let semanticVersionLevel = core.getInput('SEMVER_LEVEL', {required: true}); -if (!semanticVersionLevel || !Object.keys(versionUpdater.SEMANTIC_VERSION_LEVELS).includes(semanticVersionLevel)) { +if (!semanticVersionLevel || !versionUpdater.isValidSemverLevel(semanticVersionLevel)) { semanticVersionLevel = versionUpdater.SEMANTIC_VERSION_LEVELS.BUILD; console.log(`Invalid input for 'SEMVER_LEVEL': ${semanticVersionLevel}`, `Defaulting to: ${semanticVersionLevel}`); } @@ -53,7 +54,7 @@ if (!previousVersion) { core.setFailed('Error: Could not read package.json'); } -const newVersion = versionUpdater.incrementVersion(previousVersion ?? '', semanticVersionLevel); +const newVersion = versionUpdater.incrementVersion(previousVersion ?? '', semanticVersionLevel as SemverLevel); console.log(`Previous version: ${previousVersion}`, `New version: ${newVersion}`); updateNativeVersions(newVersion); diff --git a/.github/actions/javascript/bumpVersion/index.js b/.github/actions/javascript/bumpVersion/index.js index e1a5cf13a8d9..93ea47bed2ae 100644 --- a/.github/actions/javascript/bumpVersion/index.js +++ b/.github/actions/javascript/bumpVersion/index.js @@ -3473,7 +3473,7 @@ function updateNativeVersions(version) { } } let semanticVersionLevel = core.getInput('SEMVER_LEVEL', { required: true }); -if (!semanticVersionLevel || !Object.keys(versionUpdater.SEMANTIC_VERSION_LEVELS).includes(semanticVersionLevel)) { +if (!semanticVersionLevel || !versionUpdater.isValidSemverLevel(semanticVersionLevel)) { semanticVersionLevel = versionUpdater.SEMANTIC_VERSION_LEVELS.BUILD; console.log(`Invalid input for 'SEMVER_LEVEL': ${semanticVersionLevel}`, `Defaulting to: ${semanticVersionLevel}`); } @@ -3589,7 +3589,7 @@ exports.updateiOSVersion = updateiOSVersion; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getPreviousVersion = exports.incrementPatch = exports.incrementMinor = exports.SEMANTIC_VERSION_LEVELS = exports.MAX_INCREMENTS = exports.incrementVersion = exports.getVersionStringFromNumber = exports.getVersionNumberFromString = void 0; +exports.getPreviousVersion = exports.incrementPatch = exports.incrementMinor = exports.SEMANTIC_VERSION_LEVELS = exports.MAX_INCREMENTS = exports.incrementVersion = exports.getVersionStringFromNumber = exports.getVersionNumberFromString = exports.isValidSemverLevel = void 0; const SEMANTIC_VERSION_LEVELS = { MAJOR: 'MAJOR', MINOR: 'MINOR', @@ -3599,6 +3599,10 @@ const SEMANTIC_VERSION_LEVELS = { exports.SEMANTIC_VERSION_LEVELS = SEMANTIC_VERSION_LEVELS; const MAX_INCREMENTS = 99; exports.MAX_INCREMENTS = MAX_INCREMENTS; +function isValidSemverLevel(str) { + return Object.keys(SEMANTIC_VERSION_LEVELS).includes(str); +} +exports.isValidSemverLevel = isValidSemverLevel; /** * Transforms a versions string into a number */ diff --git a/.github/actions/javascript/checkDeployBlockers/index.js b/.github/actions/javascript/checkDeployBlockers/index.js index 0817a8130adc..c6518f4e61c9 100644 --- a/.github/actions/javascript/checkDeployBlockers/index.js +++ b/.github/actions/javascript/checkDeployBlockers/index.js @@ -6679,7 +6679,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12050,27 +12050,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index 12b3165c1ead..260dd0847c8d 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -9434,7 +9434,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -14401,7 +14401,66 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); const child_process_1 = __nccwpck_require__(2081); const CONST_1 = __importDefault(__nccwpck_require__(9873)); const sanitizeStringForJSONParse_1 = __importDefault(__nccwpck_require__(3902)); -const VERSION_UPDATER = __importStar(__nccwpck_require__(8982)); +const VersionUpdater = __importStar(__nccwpck_require__(8982)); +/** + * Check if a tag exists locally or in the remote. + */ +function tagExists(tag) { + try { + // Check if the tag exists locally + (0, child_process_1.execSync)(`git show-ref --tags ${tag}`, { stdio: 'ignore' }); + return true; // Tag exists locally + } + catch (error) { + // Tag does not exist locally, check in remote + let shouldRetry = true; + let needsRepack = false; + let doesTagExist = false; + while (shouldRetry) { + try { + if (needsRepack) { + // We have seen some scenarios where this fixes the git fetch. + // Why? Who knows... https://github.com/Expensify/App/pull/31459 + (0, child_process_1.execSync)('git repack -d', { stdio: 'inherit' }); + } + (0, child_process_1.execSync)(`git ls-remote --exit-code --tags origin ${tag}`, { stdio: 'ignore' }); + doesTagExist = true; + shouldRetry = false; + } + catch (e) { + if (!needsRepack) { + console.log('Attempting to repack and retry...'); + needsRepack = true; + } + else { + console.error("Repack didn't help, giving up..."); + shouldRetry = false; + } + } + } + return doesTagExist; + } +} +/** + * This essentially just calls getPreviousVersion in a loop, until it finds a version for which a tag exists. + * It's useful if we manually perform a version bump, because in that case a tag may not exist for the previous version. + * + * @param tag the current tag + * @param level the Semver level to step backward by + */ +function getPreviousExistingTag(tag, level) { + let previousVersion = VersionUpdater.getPreviousVersion(tag, level); + let tagExistsForPreviousVersion = false; + while (!tagExistsForPreviousVersion) { + if (tagExists(previousVersion)) { + tagExistsForPreviousVersion = true; + break; + } + console.log(`Tag for previous version ${previousVersion} does not exist. Checking for an older version...`); + previousVersion = VersionUpdater.getPreviousVersion(previousVersion, level); + } + return previousVersion; +} /** * @param [shallowExcludeTag] When fetching the given tag, exclude all history reachable by the shallowExcludeTag (used to make fetch much faster) */ @@ -14444,8 +14503,8 @@ function fetchTag(tag, shallowExcludeTag = '') { * Get merge logs between two tags (inclusive) as a JavaScript object. */ function getCommitHistoryAsJSON(fromTag, toTag) { - // Fetch tags, exclude commits reachable from the previous patch version (i.e: previous checklist), so that we don't have to fetch the full history - const previousPatchVersion = VERSION_UPDATER.getPreviousVersion(fromTag, VERSION_UPDATER.SEMANTIC_VERSION_LEVELS.PATCH); + // Fetch tags, excluding commits reachable from the previous patch version (i.e: previous checklist), so that we don't have to fetch the full history + const previousPatchVersion = getPreviousExistingTag(fromTag, VersionUpdater.SEMANTIC_VERSION_LEVELS.PATCH); fetchTag(fromTag, previousPatchVersion); fetchTag(toTag, previousPatchVersion); console.log('Getting pull requests merged between the following tags:', fromTag, toTag); @@ -14517,6 +14576,7 @@ async function getPullRequestsMergedBetween(fromTag, toTag) { return pullRequestNumbers; } exports["default"] = { + getPreviousExistingTag, getValidMergedPRs, getPullRequestsMergedBetween, }; @@ -15026,7 +15086,7 @@ exports["default"] = sanitizeStringForJSONParse; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getPreviousVersion = exports.incrementPatch = exports.incrementMinor = exports.SEMANTIC_VERSION_LEVELS = exports.MAX_INCREMENTS = exports.incrementVersion = exports.getVersionStringFromNumber = exports.getVersionNumberFromString = void 0; +exports.getPreviousVersion = exports.incrementPatch = exports.incrementMinor = exports.SEMANTIC_VERSION_LEVELS = exports.MAX_INCREMENTS = exports.incrementVersion = exports.getVersionStringFromNumber = exports.getVersionNumberFromString = exports.isValidSemverLevel = void 0; const SEMANTIC_VERSION_LEVELS = { MAJOR: 'MAJOR', MINOR: 'MINOR', @@ -15036,6 +15096,10 @@ const SEMANTIC_VERSION_LEVELS = { exports.SEMANTIC_VERSION_LEVELS = SEMANTIC_VERSION_LEVELS; const MAX_INCREMENTS = 99; exports.MAX_INCREMENTS = MAX_INCREMENTS; +function isValidSemverLevel(str) { + return Object.keys(SEMANTIC_VERSION_LEVELS).includes(str); +} +exports.isValidSemverLevel = isValidSemverLevel; /** * Transforms a versions string into a number */ @@ -15152,14 +15216,6 @@ function arrayDifference(array1, array2) { exports["default"] = arrayDifference; -/***/ }), - -/***/ 2877: -/***/ ((module) => { - -module.exports = eval("require")("encoding"); - - /***/ }), /***/ 9491: @@ -15186,6 +15242,14 @@ module.exports = require("crypto"); /***/ }), +/***/ 3975: +/***/ ((module) => { + +"use strict"; +module.exports = require("encoding"); + +/***/ }), + /***/ 2361: /***/ ((module) => { diff --git a/.github/actions/javascript/getArtifactInfo/index.js b/.github/actions/javascript/getArtifactInfo/index.js index 9a7a0ae62e53..cde9cf8748db 100644 --- a/.github/actions/javascript/getArtifactInfo/index.js +++ b/.github/actions/javascript/getArtifactInfo/index.js @@ -6679,7 +6679,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12011,27 +12011,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index f63cd2a14f5b..6b956f17be25 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -6723,7 +6723,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -11665,7 +11665,66 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); const child_process_1 = __nccwpck_require__(2081); const CONST_1 = __importDefault(__nccwpck_require__(9873)); const sanitizeStringForJSONParse_1 = __importDefault(__nccwpck_require__(3902)); -const VERSION_UPDATER = __importStar(__nccwpck_require__(8982)); +const VersionUpdater = __importStar(__nccwpck_require__(8982)); +/** + * Check if a tag exists locally or in the remote. + */ +function tagExists(tag) { + try { + // Check if the tag exists locally + (0, child_process_1.execSync)(`git show-ref --tags ${tag}`, { stdio: 'ignore' }); + return true; // Tag exists locally + } + catch (error) { + // Tag does not exist locally, check in remote + let shouldRetry = true; + let needsRepack = false; + let doesTagExist = false; + while (shouldRetry) { + try { + if (needsRepack) { + // We have seen some scenarios where this fixes the git fetch. + // Why? Who knows... https://github.com/Expensify/App/pull/31459 + (0, child_process_1.execSync)('git repack -d', { stdio: 'inherit' }); + } + (0, child_process_1.execSync)(`git ls-remote --exit-code --tags origin ${tag}`, { stdio: 'ignore' }); + doesTagExist = true; + shouldRetry = false; + } + catch (e) { + if (!needsRepack) { + console.log('Attempting to repack and retry...'); + needsRepack = true; + } + else { + console.error("Repack didn't help, giving up..."); + shouldRetry = false; + } + } + } + return doesTagExist; + } +} +/** + * This essentially just calls getPreviousVersion in a loop, until it finds a version for which a tag exists. + * It's useful if we manually perform a version bump, because in that case a tag may not exist for the previous version. + * + * @param tag the current tag + * @param level the Semver level to step backward by + */ +function getPreviousExistingTag(tag, level) { + let previousVersion = VersionUpdater.getPreviousVersion(tag, level); + let tagExistsForPreviousVersion = false; + while (!tagExistsForPreviousVersion) { + if (tagExists(previousVersion)) { + tagExistsForPreviousVersion = true; + break; + } + console.log(`Tag for previous version ${previousVersion} does not exist. Checking for an older version...`); + previousVersion = VersionUpdater.getPreviousVersion(previousVersion, level); + } + return previousVersion; +} /** * @param [shallowExcludeTag] When fetching the given tag, exclude all history reachable by the shallowExcludeTag (used to make fetch much faster) */ @@ -11708,8 +11767,8 @@ function fetchTag(tag, shallowExcludeTag = '') { * Get merge logs between two tags (inclusive) as a JavaScript object. */ function getCommitHistoryAsJSON(fromTag, toTag) { - // Fetch tags, exclude commits reachable from the previous patch version (i.e: previous checklist), so that we don't have to fetch the full history - const previousPatchVersion = VERSION_UPDATER.getPreviousVersion(fromTag, VERSION_UPDATER.SEMANTIC_VERSION_LEVELS.PATCH); + // Fetch tags, excluding commits reachable from the previous patch version (i.e: previous checklist), so that we don't have to fetch the full history + const previousPatchVersion = getPreviousExistingTag(fromTag, VersionUpdater.SEMANTIC_VERSION_LEVELS.PATCH); fetchTag(fromTag, previousPatchVersion); fetchTag(toTag, previousPatchVersion); console.log('Getting pull requests merged between the following tags:', fromTag, toTag); @@ -11781,6 +11840,7 @@ async function getPullRequestsMergedBetween(fromTag, toTag) { return pullRequestNumbers; } exports["default"] = { + getPreviousExistingTag, getValidMergedPRs, getPullRequestsMergedBetween, }; @@ -12290,7 +12350,7 @@ exports["default"] = sanitizeStringForJSONParse; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getPreviousVersion = exports.incrementPatch = exports.incrementMinor = exports.SEMANTIC_VERSION_LEVELS = exports.MAX_INCREMENTS = exports.incrementVersion = exports.getVersionStringFromNumber = exports.getVersionNumberFromString = void 0; +exports.getPreviousVersion = exports.incrementPatch = exports.incrementMinor = exports.SEMANTIC_VERSION_LEVELS = exports.MAX_INCREMENTS = exports.incrementVersion = exports.getVersionStringFromNumber = exports.getVersionNumberFromString = exports.isValidSemverLevel = void 0; const SEMANTIC_VERSION_LEVELS = { MAJOR: 'MAJOR', MINOR: 'MINOR', @@ -12300,6 +12360,10 @@ const SEMANTIC_VERSION_LEVELS = { exports.SEMANTIC_VERSION_LEVELS = SEMANTIC_VERSION_LEVELS; const MAX_INCREMENTS = 99; exports.MAX_INCREMENTS = MAX_INCREMENTS; +function isValidSemverLevel(str) { + return Object.keys(SEMANTIC_VERSION_LEVELS).includes(str); +} +exports.isValidSemverLevel = isValidSemverLevel; /** * Transforms a versions string into a number */ @@ -12416,14 +12480,6 @@ function arrayDifference(array1, array2) { exports["default"] = arrayDifference; -/***/ }), - -/***/ 2877: -/***/ ((module) => { - -module.exports = eval("require")("encoding"); - - /***/ }), /***/ 9491: @@ -12450,6 +12506,14 @@ module.exports = require("crypto"); /***/ }), +/***/ 3975: +/***/ ((module) => { + +"use strict"; +module.exports = require("encoding"); + +/***/ }), + /***/ 2361: /***/ ((module) => { diff --git a/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts b/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts index 262b603124fa..a178d4073cbb 100644 --- a/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts +++ b/.github/actions/javascript/getPreviousVersion/getPreviousVersion.ts @@ -1,17 +1,29 @@ import * as core from '@actions/core'; import {readFileSync} from 'fs'; import type {PackageJson} from 'type-fest'; +import GitUtils from '@github/libs/GitUtils'; import * as versionUpdater from '@github/libs/versionUpdater'; +import type {SemverLevel} from '@github/libs/versionUpdater'; -const semverLevel = core.getInput('SEMVER_LEVEL', {required: true}); -if (!semverLevel || !Object.values(versionUpdater.SEMANTIC_VERSION_LEVELS).includes(semverLevel)) { - core.setFailed(`'Error: Invalid input for 'SEMVER_LEVEL': ${semverLevel}`); +function run() { + const semverLevel = core.getInput('SEMVER_LEVEL', {required: true}); + if (!semverLevel || !versionUpdater.isValidSemverLevel(semverLevel)) { + core.setFailed(`'Error: Invalid input for 'SEMVER_LEVEL': ${semverLevel}`); + } + + const {version: currentVersion}: PackageJson = JSON.parse(readFileSync('./package.json', 'utf8')); + if (!currentVersion) { + core.setFailed('Error: Could not read package.json'); + } + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const previousVersion = GitUtils.getPreviousExistingTag(currentVersion!, semverLevel as SemverLevel); + core.setOutput('PREVIOUS_VERSION', previousVersion); + return previousVersion; } -const {version: currentVersion}: PackageJson = JSON.parse(readFileSync('./package.json', 'utf8')); -if (!currentVersion) { - core.setFailed('Error: Could not read package.json'); +if (require.main === module) { + run(); } -const previousVersion = versionUpdater.getPreviousVersion(currentVersion ?? '', semverLevel); -core.setOutput('PREVIOUS_VERSION', previousVersion); +export default run; diff --git a/.github/actions/javascript/getPreviousVersion/index.js b/.github/actions/javascript/getPreviousVersion/index.js index 8eac2f62f03e..29d02cc4dbac 100644 --- a/.github/actions/javascript/getPreviousVersion/index.js +++ b/.github/actions/javascript/getPreviousVersion/index.js @@ -2719,20 +2719,316 @@ var __importStar = (this && this.__importStar) || function (mod) { __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 = __nccwpck_require__(147); +const GitUtils_1 = __importDefault(__nccwpck_require__(547)); const versionUpdater = __importStar(__nccwpck_require__(982)); -const semverLevel = core.getInput('SEMVER_LEVEL', { required: true }); -if (!semverLevel || !Object.values(versionUpdater.SEMANTIC_VERSION_LEVELS).includes(semverLevel)) { - core.setFailed(`'Error: Invalid input for 'SEMVER_LEVEL': ${semverLevel}`); +function run() { + const semverLevel = core.getInput('SEMVER_LEVEL', { required: true }); + if (!semverLevel || !versionUpdater.isValidSemverLevel(semverLevel)) { + core.setFailed(`'Error: Invalid input for 'SEMVER_LEVEL': ${semverLevel}`); + } + const { version: currentVersion } = JSON.parse((0, fs_1.readFileSync)('./package.json', 'utf8')); + if (!currentVersion) { + core.setFailed('Error: Could not read package.json'); + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const previousVersion = GitUtils_1.default.getPreviousExistingTag(currentVersion, semverLevel); + core.setOutput('PREVIOUS_VERSION', previousVersion); + return previousVersion; +} +if (require.main === require.cache[eval('__filename')]) { + run(); +} +exports["default"] = run; + + +/***/ }), + +/***/ 873: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const GITHUB_BASE_URL_REGEX = new RegExp('https?://(?:github\\.com|api\\.github\\.com)'); +const GIT_CONST = { + GITHUB_OWNER: 'Expensify', + APP_REPO: 'App', +}; +const CONST = { + ...GIT_CONST, + APPLAUSE_BOT: 'applausebot', + OS_BOTIFY: 'OSBotify', + LABELS: { + STAGING_DEPLOY: 'StagingDeployCash', + DEPLOY_BLOCKER: 'DeployBlockerCash', + INTERNAL_QA: 'InternalQA', + }, + DATE_FORMAT_STRING: 'yyyy-MM-dd', + PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), + ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), + ISSUE_OR_PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/(?:pull|issues)/([0-9]+).*`), + POLL_RATE: 10000, + APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, + APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, +}; +exports["default"] = CONST; + + +/***/ }), + +/***/ 547: +/***/ (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 child_process_1 = __nccwpck_require__(81); +const CONST_1 = __importDefault(__nccwpck_require__(873)); +const sanitizeStringForJSONParse_1 = __importDefault(__nccwpck_require__(902)); +const VersionUpdater = __importStar(__nccwpck_require__(982)); +/** + * Check if a tag exists locally or in the remote. + */ +function tagExists(tag) { + try { + // Check if the tag exists locally + (0, child_process_1.execSync)(`git show-ref --tags ${tag}`, { stdio: 'ignore' }); + return true; // Tag exists locally + } + catch (error) { + // Tag does not exist locally, check in remote + let shouldRetry = true; + let needsRepack = false; + let doesTagExist = false; + while (shouldRetry) { + try { + if (needsRepack) { + // We have seen some scenarios where this fixes the git fetch. + // Why? Who knows... https://github.com/Expensify/App/pull/31459 + (0, child_process_1.execSync)('git repack -d', { stdio: 'inherit' }); + } + (0, child_process_1.execSync)(`git ls-remote --exit-code --tags origin ${tag}`, { stdio: 'ignore' }); + doesTagExist = true; + shouldRetry = false; + } + catch (e) { + if (!needsRepack) { + console.log('Attempting to repack and retry...'); + needsRepack = true; + } + else { + console.error("Repack didn't help, giving up..."); + shouldRetry = false; + } + } + } + return doesTagExist; + } +} +/** + * This essentially just calls getPreviousVersion in a loop, until it finds a version for which a tag exists. + * It's useful if we manually perform a version bump, because in that case a tag may not exist for the previous version. + * + * @param tag the current tag + * @param level the Semver level to step backward by + */ +function getPreviousExistingTag(tag, level) { + let previousVersion = VersionUpdater.getPreviousVersion(tag, level); + let tagExistsForPreviousVersion = false; + while (!tagExistsForPreviousVersion) { + if (tagExists(previousVersion)) { + tagExistsForPreviousVersion = true; + break; + } + console.log(`Tag for previous version ${previousVersion} does not exist. Checking for an older version...`); + previousVersion = VersionUpdater.getPreviousVersion(previousVersion, level); + } + return previousVersion; } -const { version: currentVersion } = JSON.parse((0, fs_1.readFileSync)('./package.json', 'utf8')); -if (!currentVersion) { - core.setFailed('Error: Could not read package.json'); +/** + * @param [shallowExcludeTag] When fetching the given tag, exclude all history reachable by the shallowExcludeTag (used to make fetch much faster) + */ +function fetchTag(tag, shallowExcludeTag = '') { + let shouldRetry = true; + let needsRepack = false; + while (shouldRetry) { + try { + let command = ''; + if (needsRepack) { + // We have seen some scenarios where this fixes the git fetch. + // Why? Who knows... https://github.com/Expensify/App/pull/31459 + command = 'git repack -d'; + console.log(`Running command: ${command}`); + (0, child_process_1.execSync)(command); + } + command = `git fetch origin tag ${tag} --no-tags`; + // Note that this condition is only ever NOT true in the 1.0.0-0 edge case + if (shallowExcludeTag && shallowExcludeTag !== tag) { + command += ` --shallow-exclude=${shallowExcludeTag}`; + } + console.log(`Running command: ${command}`); + (0, child_process_1.execSync)(command); + shouldRetry = false; + } + catch (e) { + console.error(e); + if (!needsRepack) { + console.log('Attempting to repack and retry...'); + needsRepack = true; + } + else { + console.error("Repack didn't help, giving up..."); + shouldRetry = false; + } + } + } +} +/** + * Get merge logs between two tags (inclusive) as a JavaScript object. + */ +function getCommitHistoryAsJSON(fromTag, toTag) { + // Fetch tags, excluding commits reachable from the previous patch version (i.e: previous checklist), so that we don't have to fetch the full history + const previousPatchVersion = getPreviousExistingTag(fromTag, VersionUpdater.SEMANTIC_VERSION_LEVELS.PATCH); + fetchTag(fromTag, previousPatchVersion); + fetchTag(toTag, previousPatchVersion); + console.log('Getting pull requests merged between the following tags:', fromTag, toTag); + return new Promise((resolve, reject) => { + let stdout = ''; + let stderr = ''; + const args = ['log', '--format={"commit": "%H", "authorName": "%an", "subject": "%s"},', `${fromTag}...${toTag}`]; + console.log(`Running command: git ${args.join(' ')}`); + const spawnedProcess = (0, child_process_1.spawn)('git', args); + spawnedProcess.on('message', console.log); + spawnedProcess.stdout.on('data', (chunk) => { + console.log(chunk.toString()); + stdout += chunk.toString(); + }); + spawnedProcess.stderr.on('data', (chunk) => { + console.error(chunk.toString()); + stderr += chunk.toString(); + }); + spawnedProcess.on('close', (code) => { + if (code !== 0) { + return reject(new Error(`${stderr}`)); + } + resolve(stdout); + }); + spawnedProcess.on('error', (err) => reject(err)); + }).then((stdout) => { + // Sanitize just the text within commit subjects as that's the only potentially un-parseable text. + const sanitizedOutput = stdout.replace(/(?<="subject": ").*?(?="})/g, (subject) => (0, sanitizeStringForJSONParse_1.default)(subject)); + // Then remove newlines, format as JSON and convert to a proper JS object + const json = `[${sanitizedOutput}]`.replace(/(\r\n|\n|\r)/gm, '').replace('},]', '}]'); + return JSON.parse(json); + }); +} +/** + * Parse merged PRs, excluding those from irrelevant branches. + */ +function getValidMergedPRs(commits) { + const mergedPRs = new Set(); + commits.forEach((commit) => { + const author = commit.authorName; + if (author === CONST_1.default.OS_BOTIFY) { + return; + } + const match = commit.subject.match(/Merge pull request #(\d+) from (?!Expensify\/.*-cherry-pick-staging)/); + if (!Array.isArray(match) || match.length < 2) { + return; + } + const pr = Number.parseInt(match[1], 10); + if (mergedPRs.has(pr)) { + // If a PR shows up in the log twice, that means that the PR was deployed in the previous checklist. + // That also means that we don't want to include it in the current checklist, so we remove it now. + mergedPRs.delete(pr); + return; + } + mergedPRs.add(pr); + }); + return Array.from(mergedPRs); } -const previousVersion = versionUpdater.getPreviousVersion(currentVersion ?? '', semverLevel); -core.setOutput('PREVIOUS_VERSION', previousVersion); +/** + * Takes in two git tags and returns a list of PR numbers of all PRs merged between those two tags + */ +async function getPullRequestsMergedBetween(fromTag, toTag) { + console.log(`Looking for commits made between ${fromTag} and ${toTag}...`); + const commitList = await getCommitHistoryAsJSON(fromTag, toTag); + console.log(`Commits made between ${fromTag} and ${toTag}:`, commitList); + // Find which commit messages correspond to merged PR's + const pullRequestNumbers = getValidMergedPRs(commitList).sort((a, b) => a - b); + console.log(`List of pull requests merged between ${fromTag} and ${toTag}`, pullRequestNumbers); + return pullRequestNumbers; +} +exports["default"] = { + getPreviousExistingTag, + getValidMergedPRs, + getPullRequestsMergedBetween, +}; + + +/***/ }), + +/***/ 902: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +/* eslint-disable @typescript-eslint/naming-convention */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +const replacer = (str) => ({ + '\\': '\\\\', + '\t': '\\t', + '\n': '\\n', + '\r': '\\r', + '\f': '\\f', + '"': '\\"', +}[str] ?? ''); +/** + * Replace any characters in the string that will break JSON.parse for our Git Log output + * + * Solution partly taken from SO user Gabriel Rodríguez Flores 🙇 + * https://stackoverflow.com/questions/52789718/how-to-remove-special-characters-before-json-parse-while-file-reading + */ +const sanitizeStringForJSONParse = (inputString) => { + if (typeof inputString !== 'string') { + throw new TypeError('Input must me of type String'); + } + // Replace any newlines and escape backslashes + return inputString.replace(/\\|\t|\n|\r|\f|"/g, replacer); +}; +exports["default"] = sanitizeStringForJSONParse; /***/ }), @@ -2743,7 +3039,7 @@ core.setOutput('PREVIOUS_VERSION', previousVersion); "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getPreviousVersion = exports.incrementPatch = exports.incrementMinor = exports.SEMANTIC_VERSION_LEVELS = exports.MAX_INCREMENTS = exports.incrementVersion = exports.getVersionStringFromNumber = exports.getVersionNumberFromString = void 0; +exports.getPreviousVersion = exports.incrementPatch = exports.incrementMinor = exports.SEMANTIC_VERSION_LEVELS = exports.MAX_INCREMENTS = exports.incrementVersion = exports.getVersionStringFromNumber = exports.getVersionNumberFromString = exports.isValidSemverLevel = void 0; const SEMANTIC_VERSION_LEVELS = { MAJOR: 'MAJOR', MINOR: 'MINOR', @@ -2753,6 +3049,10 @@ const SEMANTIC_VERSION_LEVELS = { exports.SEMANTIC_VERSION_LEVELS = SEMANTIC_VERSION_LEVELS; const MAX_INCREMENTS = 99; exports.MAX_INCREMENTS = MAX_INCREMENTS; +function isValidSemverLevel(str) { + return Object.keys(SEMANTIC_VERSION_LEVELS).includes(str); +} +exports.isValidSemverLevel = isValidSemverLevel; /** * Transforms a versions string into a number */ @@ -2846,6 +3146,14 @@ module.exports = require("assert"); /***/ }), +/***/ 81: +/***/ ((module) => { + +"use strict"; +module.exports = require("child_process"); + +/***/ }), + /***/ 113: /***/ ((module) => { diff --git a/.github/actions/javascript/getPullRequestDetails/index.js b/.github/actions/javascript/getPullRequestDetails/index.js index 7cb768941711..8fa081de17fa 100644 --- a/.github/actions/javascript/getPullRequestDetails/index.js +++ b/.github/actions/javascript/getPullRequestDetails/index.js @@ -6679,7 +6679,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12113,27 +12113,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/getReleaseBody/index.js b/.github/actions/javascript/getReleaseBody/index.js index f6ba78030927..81b73876db95 100644 --- a/.github/actions/javascript/getReleaseBody/index.js +++ b/.github/actions/javascript/getReleaseBody/index.js @@ -6679,7 +6679,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12057,27 +12057,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/isStagingDeployLocked/index.js b/.github/actions/javascript/isStagingDeployLocked/index.js index 29c010f086c3..feccd44beb1a 100644 --- a/.github/actions/javascript/isStagingDeployLocked/index.js +++ b/.github/actions/javascript/isStagingDeployLocked/index.js @@ -6679,7 +6679,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12011,27 +12011,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/markPullRequestsAsDeployed/index.js b/.github/actions/javascript/markPullRequestsAsDeployed/index.js index 1256b6425640..ba474583a2fe 100644 --- a/.github/actions/javascript/markPullRequestsAsDeployed/index.js +++ b/.github/actions/javascript/markPullRequestsAsDeployed/index.js @@ -6723,7 +6723,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -11598,15 +11598,25 @@ async function run() { * 1. For regular staging deploys, the person who merged the PR. * 2. For CPs, the person who committed the cherry-picked commit (not necessarily the author of the commit). */ - const { data: pr } = await GithubUtils_1.default.octokit.pulls.get({ - owner: CONST_1.default.GITHUB_OWNER, - repo: CONST_1.default.APP_REPO, - pull_number: prNumber, - }); - const deployer = isCP ? commit.committer.name : pr.merged_by?.login; - const title = pr.title; - const deployMessage = deployer ? getDeployMessage(deployer, isCP ? 'Cherry-picked' : 'Deployed', title) : ''; - await commentPR(prNumber, deployMessage); + try { + const { data: pr } = await GithubUtils_1.default.octokit.pulls.get({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + pull_number: prNumber, + }); + const deployer = isCP ? commit.committer.name : pr.merged_by?.login; + const title = pr.title; + const deployMessage = deployer ? getDeployMessage(deployer, isCP ? 'Cherry-picked' : 'Deployed', title) : ''; + await commentPR(prNumber, deployMessage); + } + catch (error) { + if (error.status === 404) { + console.log(`Unable to comment on PR #${prNumber}. GitHub responded with 404.`); + } + else { + throw error; + } + } } } if (require.main === require.cache[eval('__filename')]) { @@ -12208,27 +12218,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/markPullRequestsAsDeployed/markPullRequestsAsDeployed.ts b/.github/actions/javascript/markPullRequestsAsDeployed/markPullRequestsAsDeployed.ts index a312bae7e7df..53018cbb035e 100644 --- a/.github/actions/javascript/markPullRequestsAsDeployed/markPullRequestsAsDeployed.ts +++ b/.github/actions/javascript/markPullRequestsAsDeployed/markPullRequestsAsDeployed.ts @@ -1,6 +1,7 @@ /* eslint-disable @typescript-eslint/naming-convention, import/no-import-module-exports */ import * as core from '@actions/core'; import {context} from '@actions/github'; +import type {RequestError} from '@octokit/types'; import * as ActionUtils from '@github/libs/ActionUtils'; import CONST from '@github/libs/CONST'; import GithubUtils from '@github/libs/GithubUtils'; @@ -113,16 +114,24 @@ async function run() { * 1. For regular staging deploys, the person who merged the PR. * 2. For CPs, the person who committed the cherry-picked commit (not necessarily the author of the commit). */ - const {data: pr} = await GithubUtils.octokit.pulls.get({ - owner: CONST.GITHUB_OWNER, - repo: CONST.APP_REPO, - pull_number: prNumber, - }); - const deployer = isCP ? commit.committer.name : pr.merged_by?.login; - - const title = pr.title; - const deployMessage = deployer ? getDeployMessage(deployer, isCP ? 'Cherry-picked' : 'Deployed', title) : ''; - await commentPR(prNumber, deployMessage); + try { + const {data: pr} = await GithubUtils.octokit.pulls.get({ + owner: CONST.GITHUB_OWNER, + repo: CONST.APP_REPO, + pull_number: prNumber, + }); + const deployer = isCP ? commit.committer.name : pr.merged_by?.login; + + const title = pr.title; + const deployMessage = deployer ? getDeployMessage(deployer, isCP ? 'Cherry-picked' : 'Deployed', title) : ''; + await commentPR(prNumber, deployMessage); + } catch (error) { + if ((error as RequestError).status === 404) { + console.log(`Unable to comment on PR #${prNumber}. GitHub responded with 404.`); + } else { + throw error; + } + } } } diff --git a/.github/actions/javascript/postTestBuildComment/index.js b/.github/actions/javascript/postTestBuildComment/index.js index fef09bc25c56..68f3b11f45f1 100644 --- a/.github/actions/javascript/postTestBuildComment/index.js +++ b/.github/actions/javascript/postTestBuildComment/index.js @@ -6723,7 +6723,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12110,27 +12110,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/reopenIssueWithComment/index.js b/.github/actions/javascript/reopenIssueWithComment/index.js index b211f301eb67..461f576e4691 100644 --- a/.github/actions/javascript/reopenIssueWithComment/index.js +++ b/.github/actions/javascript/reopenIssueWithComment/index.js @@ -6679,7 +6679,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12021,27 +12021,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/reviewerChecklist/index.js b/.github/actions/javascript/reviewerChecklist/index.js index b53863ef0c26..5be97363a21c 100644 --- a/.github/actions/javascript/reviewerChecklist/index.js +++ b/.github/actions/javascript/reviewerChecklist/index.js @@ -6723,7 +6723,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12113,27 +12113,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/actions/javascript/verifySignedCommits/index.js b/.github/actions/javascript/verifySignedCommits/index.js index e3507f897933..c932e0c4c618 100644 --- a/.github/actions/javascript/verifySignedCommits/index.js +++ b/.github/actions/javascript/verifySignedCommits/index.js @@ -6723,7 +6723,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = (__nccwpck_require__(2877).convert); + convert = (__nccwpck_require__(3975).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -12053,27 +12053,27 @@ exports["default"] = arrayDifference; /***/ }), -/***/ 2877: +/***/ 9491: /***/ ((module) => { -module.exports = eval("require")("encoding"); - +"use strict"; +module.exports = require("assert"); /***/ }), -/***/ 9491: +/***/ 6113: /***/ ((module) => { "use strict"; -module.exports = require("assert"); +module.exports = require("crypto"); /***/ }), -/***/ 6113: +/***/ 3975: /***/ ((module) => { "use strict"; -module.exports = require("crypto"); +module.exports = require("encoding"); /***/ }), diff --git a/.github/libs/GitUtils.ts b/.github/libs/GitUtils.ts index dc8ae037be28..ab4a81f96adf 100644 --- a/.github/libs/GitUtils.ts +++ b/.github/libs/GitUtils.ts @@ -1,7 +1,8 @@ import {execSync, spawn} from 'child_process'; import CONST from './CONST'; import sanitizeStringForJSONParse from './sanitizeStringForJSONParse'; -import * as VERSION_UPDATER from './versionUpdater'; +import * as VersionUpdater from './versionUpdater'; +import type {SemverLevel} from './versionUpdater'; type CommitType = { commit: string; @@ -9,6 +10,64 @@ type CommitType = { authorName: string; }; +/** + * Check if a tag exists locally or in the remote. + */ +function tagExists(tag: string) { + try { + // Check if the tag exists locally + execSync(`git show-ref --tags ${tag}`, {stdio: 'ignore'}); + return true; // Tag exists locally + } catch (error) { + // Tag does not exist locally, check in remote + let shouldRetry = true; + let needsRepack = false; + let doesTagExist = false; + while (shouldRetry) { + try { + if (needsRepack) { + // We have seen some scenarios where this fixes the git fetch. + // Why? Who knows... https://github.com/Expensify/App/pull/31459 + execSync('git repack -d', {stdio: 'inherit'}); + } + execSync(`git ls-remote --exit-code --tags origin ${tag}`, {stdio: 'ignore'}); + doesTagExist = true; + shouldRetry = false; + } catch (e) { + if (!needsRepack) { + console.log('Attempting to repack and retry...'); + needsRepack = true; + } else { + console.error("Repack didn't help, giving up..."); + shouldRetry = false; + } + } + } + return doesTagExist; + } +} + +/** + * This essentially just calls getPreviousVersion in a loop, until it finds a version for which a tag exists. + * It's useful if we manually perform a version bump, because in that case a tag may not exist for the previous version. + * + * @param tag the current tag + * @param level the Semver level to step backward by + */ +function getPreviousExistingTag(tag: string, level: SemverLevel) { + let previousVersion = VersionUpdater.getPreviousVersion(tag, level); + let tagExistsForPreviousVersion = false; + while (!tagExistsForPreviousVersion) { + if (tagExists(previousVersion)) { + tagExistsForPreviousVersion = true; + break; + } + console.log(`Tag for previous version ${previousVersion} does not exist. Checking for an older version...`); + previousVersion = VersionUpdater.getPreviousVersion(previousVersion, level); + } + return previousVersion; +} + /** * @param [shallowExcludeTag] When fetching the given tag, exclude all history reachable by the shallowExcludeTag (used to make fetch much faster) */ @@ -53,8 +112,8 @@ function fetchTag(tag: string, shallowExcludeTag = '') { * Get merge logs between two tags (inclusive) as a JavaScript object. */ function getCommitHistoryAsJSON(fromTag: string, toTag: string): Promise { - // Fetch tags, exclude commits reachable from the previous patch version (i.e: previous checklist), so that we don't have to fetch the full history - const previousPatchVersion = VERSION_UPDATER.getPreviousVersion(fromTag, VERSION_UPDATER.SEMANTIC_VERSION_LEVELS.PATCH); + // Fetch tags, excluding commits reachable from the previous patch version (i.e: previous checklist), so that we don't have to fetch the full history + const previousPatchVersion = getPreviousExistingTag(fromTag, VersionUpdater.SEMANTIC_VERSION_LEVELS.PATCH); fetchTag(fromTag, previousPatchVersion); fetchTag(toTag, previousPatchVersion); @@ -138,6 +197,7 @@ async function getPullRequestsMergedBetween(fromTag: string, toTag: string) { } export default { + getPreviousExistingTag, getValidMergedPRs, getPullRequestsMergedBetween, }; diff --git a/.github/libs/versionUpdater.ts b/.github/libs/versionUpdater.ts index 9b60fb82bd43..d9b24f532d8e 100644 --- a/.github/libs/versionUpdater.ts +++ b/.github/libs/versionUpdater.ts @@ -1,11 +1,18 @@ +import type {ValueOf} from 'type-fest'; + const SEMANTIC_VERSION_LEVELS = { MAJOR: 'MAJOR', MINOR: 'MINOR', PATCH: 'PATCH', BUILD: 'BUILD', } as const; +type SemverLevel = ValueOf; + +const MAX_INCREMENTS = 99; -const MAX_INCREMENTS = 99 as const; +function isValidSemverLevel(str: string): str is SemverLevel { + return Object.keys(SEMANTIC_VERSION_LEVELS).includes(str); +} /** * Transforms a versions string into a number @@ -46,7 +53,7 @@ const incrementPatch = (major: number, minor: number, patch: number): string => /** * Increments a build version */ -const incrementVersion = (version: string, level: string): string => { +const incrementVersion = (version: string, level: SemverLevel): string => { const [major, minor, patch, build] = getVersionNumberFromString(version); // Majors will always be incremented @@ -99,7 +106,9 @@ function getPreviousVersion(currentVersion: string, level: string): string { return getVersionStringFromNumber(major, minor, patch, build - 1); } +export type {SemverLevel}; export { + isValidSemverLevel, getVersionNumberFromString, getVersionStringFromNumber, incrementVersion, diff --git a/.github/scripts/buildActions.sh b/.github/scripts/buildActions.sh index 30c284a776be..27d65ca99c9b 100755 --- a/.github/scripts/buildActions.sh +++ b/.github/scripts/buildActions.sh @@ -43,7 +43,7 @@ for ((i=0; i < ${#GITHUB_ACTIONS[@]}; i++)); do ACTION_DIR=$(dirname "$ACTION") # Build the action in the background - ncc build -t "$ACTION" -o "$ACTION_DIR" & + npx ncc build --transpile-only --external encoding "$ACTION" -o "$ACTION_DIR" & ASYNC_BUILDS[i]=$! done diff --git a/.github/scripts/verifyActions.sh b/.github/scripts/verifyActions.sh index ddc8fa0a3226..17316e1aac70 100755 --- a/.github/scripts/verifyActions.sh +++ b/.github/scripts/verifyActions.sh @@ -22,7 +22,7 @@ if [[ EXIT_CODE -eq 0 ]]; then echo -e "${GREEN}Github Actions are up to date!${NC}" exit 0 else - echo -e "${RED}Error: Diff found when Github Actions were rebuilt. Did you forget to run \`npm run gh-actions-build\` after a clean install (\`rm -rf node_modules && npm i\`)? Do you need to merge main? Did you try running \`git config --global core.autocrlf false\` then \`npm run gh-actions-build\` again?${NC}" + echo -e "${RED}Error: Diff found when Github Actions were rebuilt. Did you forget to run \`npm run gh-actions-build\` after a clean install (\`rm -rf node_modules && npm i\`)? Do you need to merge main? Did you try running \`git config --global core.autocrlf false\` then \`npm run gh-actions-build\` again? Did you try running \`npx ncc cache clean\`?${NC}" echo "$DIFF_OUTPUT" | "$LIB_PATH/diff-so-fancy" | less --tabs=4 -RFX exit 1 fi diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d6b346cb3995..36d4248fcc3c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,7 +5,7 @@ on: pull_request: types: [opened, synchronize] branches-ignore: [staging, production] - paths: ['**.js', '**.ts', '**.tsx', '**.sh', 'package.json', 'package-lock.json'] + paths: ['**.js', '**.ts', '**.tsx', 'package.json', 'package-lock.json'] concurrency: group: ${{ github.ref == 'refs/heads/main' && format('{0}-{1}', github.ref, github.sha) || github.ref }}-jest @@ -54,20 +54,3 @@ jobs: - name: Storybook run run: npm run storybook -- --smoke-test --ci - - shellTests: - if: ${{ github.actor != 'OSBotify' && github.actor != 'imgbot[bot]' || github.event_name == 'workflow_call' }} - runs-on: ubuntu-latest - name: Shell tests - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node - uses: ./.github/actions/composite/setupNode - - - name: Install ts-node - run: npm i -g ts-node - - - name: Test CI git logic - run: tests/unit/CIGitLogicTest.sh diff --git a/android/app/build.gradle b/android/app/build.gradle index d005d82471a9..70c06d5bf9f6 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -107,8 +107,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009000004 - versionName "9.0.0-4" + versionCode 1009000100 + versionName "9.0.1-0" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/assets/images/simple-illustrations/simple-illustration__treasurechest.svg b/assets/images/simple-illustrations/simple-illustration__treasurechest.svg index 51718aa5112a..622c611a9dc5 100644 --- a/assets/images/simple-illustrations/simple-illustration__treasurechest.svg +++ b/assets/images/simple-illustrations/simple-illustration__treasurechest.svg @@ -1,59 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/contributingGuides/CONTRIBUTING.md b/contributingGuides/CONTRIBUTING.md index aec527edabe0..d6ab46c809ef 100644 --- a/contributingGuides/CONTRIBUTING.md +++ b/contributingGuides/CONTRIBUTING.md @@ -48,7 +48,7 @@ We hire and pay external contributors via [Upwork.com](https://www.upwork.com). Payment for your contributions will be made no less than 7 days after the pull request is deployed to production to allow for [regression](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions) testing. If you have not received payment after 8 days of the PR being deployed to production, and there are no [regressions](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#regressions), please add a comment to the issue mentioning the BugZero team member (Look for the melvin-bot "Triggered auto assignment to... (`Bug`)" to see who this is). -New contributors are limited to working on one job at a time, however experienced contributors may work on numerous jobs simultaneously. +New contributors are limited to working on one job at a time, **do not submit proposals for new jobs until your first PR has been merged**. Experienced contributors may work on numerous jobs simultaneously. Please be aware that compensation for any support in solving an issue is provided **entirely at Expensify’s discretion**. Personal time or resources applied towards investigating a proposal **will not guarantee compensation**. Compensation is only guaranteed to those who **[propose a solution and get hired for that job](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#propose-a-solution-for-the-job)**. We understand there may be cases where a selected proposal may take inspiration from a previous proposal. Unfortunately, it’s not possible for us to evaluate every individual case and we have no process that can efficiently do so. Issues with higher rewards come with higher risk factors so try to keep things civil and make the best proposal you can. Once again, **any information provided may not necessarily lead to you getting hired for that issue or compensated in any way.** diff --git a/docs/articles/new-expensify/expenses/Connect-a-Business-Bank-Account.md b/docs/articles/new-expensify/expenses/Connect-a-Business-Bank-Account.md index 64ae3997c4f9..516497c9dce7 100644 --- a/docs/articles/new-expensify/expenses/Connect-a-Business-Bank-Account.md +++ b/docs/articles/new-expensify/expenses/Connect-a-Business-Bank-Account.md @@ -20,7 +20,7 @@ To connect a bank account in New Expensify, you must first enable the Make or Tr 2. Select either Connect online with Plaid (preferred) or Connect manually 3. Enter bank details -# Step 4: Upload ID +# Step 3: Upload ID After entering your personal details, you’ll be prompted to click a link or scan a QR code so that you can do the following: 1. Upload a photo of the front and back of your ID (this cannot be a photo of an existing image) 2. Use your device to take a selfie and record a short video of yourself @@ -29,14 +29,14 @@ After entering your personal details, you’ll be prompted to click a link or sc - Issued in the US - Current (ie: the expiration date must be in the future) -# Step 5: Enter company information +# Step 4: Enter company information This is where you’ll add the legal business name as well as several other company details. - **Company address:** The company address must be located in the US and a physical location (If you input a maildrop address, PO box, or UPS Store, the address will be flagged for review, and adding the bank account to Expensify will be delayed) - **Tax Identification Number:** This is the identification number that was assigned to the business by the IRS - **Company website:** A company website is required to use most of Expensify’s payment features. - **Industry Classification Code:** You can locate a list of Industry Classification Codes [here](https://www.census.gov/naics/?input=software&year=2022). -# Step 6: Additional Information +# Step 5: Additional Information Check the appropriate box under Additional Information, accept the agreement terms, and verify that all of the information is true and accurate: - A Beneficial Owner refers to an individual who owns 25% or more of the business. - If you or another individual owns 25% or more of the business, please check the appropriate box diff --git a/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_1.png b/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_1.png index baa3f8734e8e..4487e10d9719 100644 Binary files a/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_1.png and b/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_1.png differ diff --git a/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_2.png b/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_2.png index 83eaadff3bdc..600e5a7788ed 100644 Binary files a/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_2.png and b/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_2.png differ diff --git a/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_3.png b/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_3.png index 6b43c41c39cf..dd0996a7eecd 100644 Binary files a/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_3.png and b/docs/assets/images/ExpensifyHelp_R1_CreateWorkspace_3.png differ diff --git a/docs/assets/images/ExpensifyHelp_R1_InviteMembers_1.png b/docs/assets/images/ExpensifyHelp_R1_InviteMembers_1.png index 0f1883bd8f69..874fb307f067 100644 Binary files a/docs/assets/images/ExpensifyHelp_R1_InviteMembers_1.png and b/docs/assets/images/ExpensifyHelp_R1_InviteMembers_1.png differ diff --git a/docs/assets/images/ExpensifyHelp_R1_InviteMembers_2.png b/docs/assets/images/ExpensifyHelp_R1_InviteMembers_2.png index c3b8c035c9ed..f5dae55fdcd4 100644 Binary files a/docs/assets/images/ExpensifyHelp_R1_InviteMembers_2.png and b/docs/assets/images/ExpensifyHelp_R1_InviteMembers_2.png differ diff --git a/docs/assets/images/ExpensifyHelp_R1_InviteMembers_3.png b/docs/assets/images/ExpensifyHelp_R1_InviteMembers_3.png index 515a111847f8..1d646d3d5001 100644 Binary files a/docs/assets/images/ExpensifyHelp_R1_InviteMembers_3.png and b/docs/assets/images/ExpensifyHelp_R1_InviteMembers_3.png differ diff --git a/docs/assets/images/ExpensifyHelp_R2_Profile_1.png b/docs/assets/images/ExpensifyHelp_R2_Profile_1.png index 0419c66e7563..7e3e6ac181be 100644 Binary files a/docs/assets/images/ExpensifyHelp_R2_Profile_1.png and b/docs/assets/images/ExpensifyHelp_R2_Profile_1.png differ diff --git a/docs/assets/images/ExpensifyHelp_R3_Categories_1.png b/docs/assets/images/ExpensifyHelp_R3_Categories_1.png index d82757866d3d..47997df920de 100644 Binary files a/docs/assets/images/ExpensifyHelp_R3_Categories_1.png and b/docs/assets/images/ExpensifyHelp_R3_Categories_1.png differ diff --git a/docs/assets/images/ExpensifyHelp_R4_Tags_1.png b/docs/assets/images/ExpensifyHelp_R4_Tags_1.png index a14ea8343578..c8540d93423f 100644 Binary files a/docs/assets/images/ExpensifyHelp_R4_Tags_1.png and b/docs/assets/images/ExpensifyHelp_R4_Tags_1.png differ diff --git a/docs/assets/images/ExpensifyHelp_R4_Tags_2.png b/docs/assets/images/ExpensifyHelp_R4_Tags_2.png index 889d845e931a..a83d748ea12b 100644 Binary files a/docs/assets/images/ExpensifyHelp_R4_Tags_2.png and b/docs/assets/images/ExpensifyHelp_R4_Tags_2.png differ diff --git a/docs/assets/images/ExpensifyHelp_R5_Wallet_1.png b/docs/assets/images/ExpensifyHelp_R5_Wallet_1.png index 64ff3730e695..695dceb52581 100644 Binary files a/docs/assets/images/ExpensifyHelp_R5_Wallet_1.png and b/docs/assets/images/ExpensifyHelp_R5_Wallet_1.png differ diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 3360f1adfad7..2f9a259edbd4 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 9.0.0 + 9.0.1 CFBundleSignature ???? CFBundleURLTypes @@ -40,7 +40,7 @@ CFBundleVersion - 9.0.0.4 + 9.0.1.0 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 796437f37280..d406249b9a7f 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 9.0.0 + 9.0.1 CFBundleSignature ???? CFBundleVersion - 9.0.0.4 + 9.0.1.0 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 5a4f6310d225..c3a760235416 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -11,9 +11,9 @@ CFBundleName $(PRODUCT_NAME) CFBundleShortVersionString - 9.0.0 + 9.0.1 CFBundleVersion - 9.0.0.4 + 9.0.1.0 NSExtension NSExtensionPointIdentifier diff --git a/ios/Podfile.lock b/ios/Podfile.lock index ddab159714fc..35dccc2de393 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1865,7 +1865,7 @@ PODS: - RNGoogleSignin (10.0.1): - GoogleSignIn (~> 7.0) - React-Core - - RNLiveMarkdown (0.1.85): + - RNLiveMarkdown (0.1.88): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -1883,9 +1883,9 @@ PODS: - React-utils - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNLiveMarkdown/common (= 0.1.85) + - RNLiveMarkdown/common (= 0.1.88) - Yoga - - RNLiveMarkdown/common (0.1.85): + - RNLiveMarkdown/common (0.1.88): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -2606,7 +2606,7 @@ SPEC CHECKSUMS: RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 RNGestureHandler: 74b7b3d06d667ba0bbf41da7718f2607ae0dfe8f RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 - RNLiveMarkdown: fff70dc755ed8199a449f61e76cbadec7cd20440 + RNLiveMarkdown: e33d2c97863d5480f8f4b45f8b25f801cc43c7f5 RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 rnmapbox-maps: df8fe93dbd251f25022f4023d31bc04160d4d65c RNPermissions: 0b61d30d21acbeafe25baaa47d9bae40a0c65216 diff --git a/package-lock.json b/package-lock.json index 2ef901f63d43..9af174f0846b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "new.expensify", - "version": "9.0.0-4", + "version": "9.0.1-0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.0-4", + "version": "9.0.1-0", "hasInstallScript": true, "license": "MIT", "dependencies": { "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.85", + "@expensify/react-native-live-markdown": "0.1.88", "@expo/metro-runtime": "~3.1.1", "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-listformat": "^7.2.2", @@ -60,11 +60,12 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "2.0.17", + "expensify-common": "2.0.19", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", "expo-image-manipulator": "11.8.0", + "fast-equals": "^4.0.3", "focus-trap-react": "^10.2.3", "htmlparser2": "^7.2.0", "idb-keyval": "^6.2.1", @@ -152,14 +153,14 @@ "@babel/runtime": "^7.20.0", "@babel/traverse": "^7.22.20", "@babel/types": "^7.22.19", - "@dword-design/eslint-plugin-import-alias": "^4.0.8", + "@dword-design/eslint-plugin-import-alias": "^5.0.0", "@electron/notarize": "^2.1.0", "@jest/globals": "^29.5.0", "@ngneat/falso": "^7.1.1", "@octokit/core": "4.0.4", "@octokit/plugin-paginate-rest": "3.1.0", "@octokit/plugin-throttling": "4.1.0", - "@react-native-community/eslint-config": "3.0.0", + "@react-native-community/eslint-config": "3.2.0", "@react-native/babel-preset": "^0.73.21", "@react-native/metro-config": "^0.73.5", "@react-navigation/devtools": "^6.0.10", @@ -187,12 +188,11 @@ "@types/setimmediate": "^1.0.2", "@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", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", "@vercel/ncc": "0.38.1", "@welldone-software/why-did-you-render": "7.0.1", "ajv-cli": "^5.0.0", - "babel-eslint": "^10.1.0", "babel-jest": "29.4.1", "babel-loader": "^9.1.3", "babel-plugin-module-resolver": "^5.0.0", @@ -208,18 +208,16 @@ "dotenv": "^16.0.3", "electron": "^29.4.1", "electron-builder": "24.13.2", - "eslint": "^7.6.0", - "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-config-expensify": "^2.0.51", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^24.1.0", + "eslint": "^8.57.0", + "eslint-config-airbnb-typescript": "^18.0.0", + "eslint-config-expensify": "^2.0.52", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-jest": "^28.6.0", "eslint-plugin-jsdoc": "^46.2.6", - "eslint-plugin-jsx-a11y": "^6.6.1", "eslint-plugin-react-native-a11y": "^3.3.0", "eslint-plugin-storybook": "^0.8.0", "eslint-plugin-testing-library": "^6.2.2", - "eslint-plugin-you-dont-need-lodash-underscore": "^6.12.0", + "eslint-plugin-you-dont-need-lodash-underscore": "^6.14.0", "html-webpack-plugin": "^5.5.0", "jest": "29.4.1", "jest-circus": "29.4.1", @@ -466,10 +464,10 @@ } }, "node_modules/@babel/eslint-parser": { - "version": "7.23.10", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.24.7.tgz", + "integrity": "sha512-SO5E3bVxDuxyNxM5agFv480YA2HO6ohZbGxbazZdIk3KQOPOGVNw6q78I9/lbviIf95eq6tPozeYnJLbjnC8IA==", "dev": true, - "license": "MIT", - "peer": true, "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", @@ -480,14 +478,13 @@ }, "peerDependencies": { "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0" + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/@babel/eslint-parser/node_modules/semver": { "version": "6.3.1", "dev": true, "license": "ISC", - "peer": true, "bin": { "semver": "bin/semver.js" } @@ -2866,16 +2863,18 @@ }, "node_modules/@dword-design/dedent": { "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@dword-design/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha512-OFmAmzKiDUh9m7WRMYcoEOPI7b5tS5hdqQmtKDwF+ZssVJv8a+GHo9VOtFsmlw3h8Roh/9QzFWIsjSFZyQUMdg==", "dev": true, - "license": "MIT", "dependencies": { "babel-plugin-add-module-exports": "^1.0.2" } }, "node_modules/@dword-design/endent": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@dword-design/endent/-/endent-1.4.1.tgz", + "integrity": "sha512-e2sCTzth5kyRdM0o+yEb5wBVzUdJL8Y6HblRGRV0Bif0knf1ZjRLhUjdCrqM+Muirb68X/xJzgdRDJVmLqgXGA==", "dev": true, - "license": "MIT", "dependencies": { "@dword-design/dedent": "^0.7.0", "fast-json-parse": "^1.0.3", @@ -2883,35 +2882,37 @@ } }, "node_modules/@dword-design/eslint-plugin-import-alias": { - "version": "4.0.8", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@dword-design/eslint-plugin-import-alias/-/eslint-plugin-import-alias-5.0.0.tgz", + "integrity": "sha512-QbY2hA+YvhKiPJnAd9fOwT7gNV8OvaGLHdUsC6uVtyoUVjzx55WbUlzlEZzurlwDamXDlIB81IxbHgHT32Lx0w==", "dev": true, - "license": "MIT", "dependencies": { "@babel/core": "^7.10.2", - "@dword-design/functions": "^5.0.22", + "@dword-design/functions": "^6.0.0", "babel-plugin-module-resolver": "^5.0.0", "deepmerge": "^4.3.1", "jiti": "^1.18.2" }, "engines": { - "node": ">=16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/dword-design" } }, "node_modules/@dword-design/functions": { - "version": "5.0.26", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@dword-design/functions/-/functions-6.0.0.tgz", + "integrity": "sha512-22X9eviXAbaz8xdYrp5Tj6KjDPiT+m3fppAP+wEqA3gecAlCyExABesA1bEZ57aXrXrbhNk88M8PvdAO/PLg3A==", "dev": true, - "license": "MIT", "dependencies": { "@dword-design/endent": "^1.0.0", - "delay": "^5.0.0", + "delay": "^6.0.0", "lodash": "^4.17.15", "tinycolor2": "^1.4.1" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/dword-design" @@ -3474,36 +3475,42 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", "dev": true, - "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "0.4.3", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@eslint/eslintrc/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3515,10 +3522,17 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.21.0", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, - "license": "MIT", "dependencies": { "type-fest": "^0.20.2" }, @@ -3529,23 +3543,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/@eslint/eslintrc/node_modules/type-fest": { "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -3563,9 +3583,9 @@ } }, "node_modules/@expensify/react-native-live-markdown": { - "version": "0.1.85", - "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.85.tgz", - "integrity": "sha512-jeP4JBzN34pGSpjHKM7Zj3d0cqcKbID3//WrqC+SI7SK/1iJT4SdhZptVCxUg+Dcxq5XwzYIhdnhTNimeya0Fg==", + "version": "0.1.88", + "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.88.tgz", + "integrity": "sha512-78X5ACV+OL+aL6pfJAXyHkNuMGUc4Rheo4qLkIwLpmUIAiAxmY0B2lch5XHSNGf1a5ofvVbdQ6kl84+4E6DwlQ==", "workspaces": [ "parser", "example", @@ -5673,13 +5693,15 @@ "license": "Apache-2.0" }, "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" @@ -5699,9 +5721,11 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "dev": true, - "license": "BSD-3-Clause" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true }, "node_modules/@invertase/react-native-apple-authentication": { "version": "2.2.2", @@ -7387,7 +7411,6 @@ "version": "5.1.1-v1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "eslint-scope": "5.1.1" } @@ -8692,52 +8715,57 @@ } }, "node_modules/@react-native-community/eslint-config": { - "version": "3.0.0", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@react-native-community/eslint-config/-/eslint-config-3.2.0.tgz", + "integrity": "sha512-ZjGvoeiBtCbd506hQqwjKmkWPgynGUoJspG8/MuV/EfKnkjCtBmeJvq2n+sWbWEvL9LWXDp2GJmPzmvU5RSvKQ==", "dev": true, - "license": "MIT", "dependencies": { + "@babel/core": "^7.14.0", + "@babel/eslint-parser": "^7.18.2", "@react-native-community/eslint-plugin": "^1.1.0", - "@typescript-eslint/eslint-plugin": "^4.22.1", - "@typescript-eslint/parser": "^4.22.1", - "babel-eslint": "^10.1.0", - "eslint-config-prettier": "^6.10.1", - "eslint-plugin-eslint-comments": "^3.1.2", - "eslint-plugin-flowtype": "2.50.3", - "eslint-plugin-jest": "22.4.1", - "eslint-plugin-prettier": "3.1.2", - "eslint-plugin-react": "^7.20.0", - "eslint-plugin-react-hooks": "^4.0.7", - "eslint-plugin-react-native": "^3.10.0", - "prettier": "^2.0.2" + "@typescript-eslint/eslint-plugin": "^5.30.5", + "@typescript-eslint/parser": "^5.30.5", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-ft-flow": "^2.0.1", + "eslint-plugin-jest": "^26.5.3", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.30.1", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-native": "^4.0.0" }, "peerDependencies": { - "eslint": ">=7" + "eslint": ">=8", + "prettier": ">=2" } }, "node_modules/@react-native-community/eslint-config/node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.33.0", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/experimental-utils": "4.33.0", - "@typescript-eslint/scope-manager": "4.33.0", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.1.0", - "semver": "^7.3.5", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", "tsutils": "^3.21.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -8746,24 +8774,25 @@ } }, "node_modules/@react-native-community/eslint-config/node_modules/@typescript-eslint/parser": { - "version": "4.33.0", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "debug": "^4.3.1" + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -8771,29 +8800,153 @@ } } }, - "node_modules/@react-native-community/eslint-config/node_modules/eslint-config-prettier": { - "version": "6.15.0", + "node_modules/@react-native-community/eslint-config/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, - "license": "MIT", "dependencies": { - "get-stdin": "^6.0.0" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@react-native-community/eslint-config/node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@react-native-community/eslint-config/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@react-native-community/eslint-config/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@react-native-community/eslint-config/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@react-native-community/eslint-config/node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, "bin": { - "eslint-config-prettier-check": "bin/cli.js" + "eslint-config-prettier": "bin/cli.js" }, "peerDependencies": { - "eslint": ">=3.14.1" + "eslint": ">=7.0.0" } }, "node_modules/@react-native-community/eslint-config/node_modules/eslint-plugin-jest": { - "version": "22.4.1", + "version": "26.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz", + "integrity": "sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==", "dev": true, - "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "peerDependencies": { - "eslint": ">=5" + "@typescript-eslint/eslint-plugin": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/@react-native-community/eslint-config/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/@react-native-community/eslint-plugin": { @@ -12778,86 +12931,31 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.13.2", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", + "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", "dev": true, - "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/type-utils": "6.13.2", - "@typescript-eslint/utils": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/type-utils": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.13.2", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -12866,153 +12964,48 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.13.2", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", "dev": true, - "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.13.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.33.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "*" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "6.13.2", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", + "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "debug": "^4.3.4" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.13.2", - "dev": true, - "license": "MIT", - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.2", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -13020,43 +13013,17 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "6.13.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "4.33.0", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", + "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0" + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1" }, "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -13064,24 +13031,25 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.13.2", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", + "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "6.13.2", - "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/utils": "7.13.1", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -13089,49 +13057,58 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.2", + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2" + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.13.2", + "node_modules/@typescript-eslint/types": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", "dev": true, - "license": "MIT", "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.2", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", + "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/visitor-keys": "6.13.2", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^16.0.0 || >=18.0.0" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", @@ -13143,93 +13120,28 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.13.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.2", - "@typescript-eslint/types": "6.13.2", - "@typescript-eslint/typescript-estree": "6.13.2", - "semver": "^7.5.4" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.2", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.13.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^16.0.0 || >=18.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.33.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "balanced-match": "^1.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.33.0", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16 || 14 >=14.17" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@typescript-eslint/utils": { @@ -13345,21 +13257,34 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.33.0", + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", + "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/types": "4.33.0", - "eslint-visitor-keys": "^2.0.0" + "@typescript-eslint/types": "7.13.1", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" + "node": "^18.18.0 || >=20.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@ua/react-native-airship": { "version": "17.2.1", "resolved": "https://registry.npmjs.org/@ua/react-native-airship/-/react-native-airship-17.2.1.tgz", @@ -13940,14 +13865,6 @@ "version": "1.4.10", "license": "MIT" }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", "license": "MIT", @@ -14537,6 +14454,7 @@ "version": "2.0.0", "dev": true, "license": "MIT", + "optional": true, "engines": { "node": ">=8" } @@ -14989,8 +14907,9 @@ }, "node_modules/babel-plugin-add-module-exports": { "version": "1.0.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.4.tgz", + "integrity": "sha512-g+8yxHUZ60RcyaUpfNzy56OtWW+x9cyEe9j+CranqLiqbju2yf/Cy6ZtYK40EZxtrdHllzlVZgLmcOUCTlJ7Jg==", + "dev": true }, "node_modules/babel-plugin-istanbul": { "version": "6.1.1", @@ -18122,11 +18041,12 @@ } }, "node_modules/delay": { - "version": "5.0.0", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-6.0.0.tgz", + "integrity": "sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==", "dev": true, - "license": "MIT", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -18888,17 +18808,6 @@ "node": ">=10.13.0" } }, - "node_modules/enquirer": { - "version": "2.3.6", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/entities": { "version": "2.2.0", "license": "BSD-2-Clause", @@ -19214,420 +19123,6 @@ } }, "node_modules/eslint": { - "version": "7.32.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-airbnb": { - "version": "19.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-config-airbnb-base": "^15.0.0", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5" - }, - "engines": { - "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.3", - "eslint-plugin-jsx-a11y": "^6.5.1", - "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0" - } - }, - "node_modules/eslint-config-airbnb-base": { - "version": "15.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "confusing-browser-globals": "^1.0.10", - "object.assign": "^4.1.2", - "object.entries": "^1.1.5", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.2" - } - }, - "node_modules/eslint-config-airbnb-base/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-config-airbnb-typescript": { - "version": "17.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-config-airbnb-base": "^15.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.13.0 || ^6.0.0", - "@typescript-eslint/parser": "^5.0.0 || ^6.0.0", - "eslint": "^7.32.0 || ^8.2.0", - "eslint-plugin-import": "^2.25.3" - } - }, - "node_modules/eslint-config-expensify": { - "version": "2.0.51", - "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-2.0.51.tgz", - "integrity": "sha512-qEUPCI9vsAi5c5E6zM4QEYal13hIRHFvonf4U/x0JI4ceMdAejOoq/Zvt9r1ZwKT1RmA8eRoGWWIQ/4O/9hJPg==", - "dev": true, - "dependencies": { - "@lwc/eslint-plugin-lwc": "^1.7.2", - "@typescript-eslint/parser": "^7.12.0", - "@typescript-eslint/utils": "^7.12.0", - "babel-eslint": "^10.1.0", - "eslint": "^8.56.0", - "eslint-config-airbnb": "19.0.4", - "eslint-config-airbnb-base": "15.0.0", - "eslint-plugin-es": "^4.1.0", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-jsx-a11y": "^6.2.3", - "eslint-plugin-react": "^7.18.0", - "eslint-plugin-react-hooks": "^4.6.0", - "eslint-plugin-rulesdir": "^0.2.2", - "lodash": "^4.17.21", - "underscore": "^1.13.6" - } - }, - "node_modules/eslint-config-expensify/node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-expensify/node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/eslint-config-expensify/node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, - "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/parser": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.12.0.tgz", - "integrity": "sha512-dm/J2UDY3oV3TKius2OUZIFHsomQmpHtsV0FTh1WO8EKgHLQ1QCADUqscPgTpU+ih1e21FQSRjXckHn3txn6kQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/scope-manager": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", - "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/types": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", - "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/typescript-estree": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", - "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/visitor-keys": "7.12.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/utils": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", - "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.12.0", - "@typescript-eslint/types": "7.12.0", - "@typescript-eslint/typescript-estree": "7.12.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/visitor-keys": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", - "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.12.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/eslint-config-expensify/node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/eslint-config-expensify/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint-config-expensify/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint-config-expensify/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/eslint-config-expensify/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/eslint-config-expensify/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint-config-expensify/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint-config-expensify/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint-config-expensify/node_modules/eslint": { "version": "8.57.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", @@ -19682,142 +19177,227 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-config-expensify/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/eslint-config-airbnb": { + "version": "19.0.4", "dev": true, + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" } }, - "node_modules/eslint-config-expensify/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", "dev": true, + "license": "MIT", + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^10.12.0 || >=12.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" } }, - "node_modules/eslint-config-expensify/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/eslint-config-airbnb-base/node_modules/semver": { + "version": "6.3.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-config-airbnb-typescript": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-18.0.0.tgz", + "integrity": "sha512-oc+Lxzgzsu8FQyFVa4QFaVKiitTYiiW3frB9KYW5OWdPrqFc7FzxgB20hP4cHMlr+MBzGcLl3jnCOVOydL9mIg==", "dev": true, "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "eslint-config-airbnb-base": "^15.0.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" } }, - "node_modules/eslint-config-expensify/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/eslint-config-expensify": { + "version": "2.0.52", + "resolved": "https://registry.npmjs.org/eslint-config-expensify/-/eslint-config-expensify-2.0.52.tgz", + "integrity": "sha512-TUhtgsb+EUsfqhEGhSbUVgIypEhZjloYC8PEPxKKniaaG14SW/z1G3C5E4NJQ05xVdRwJ4H+shF7ZzOYbVcraQ==", "dev": true, "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" + "@lwc/eslint-plugin-lwc": "^1.7.2", + "@typescript-eslint/parser": "^7.12.0", + "@typescript-eslint/utils": "^7.12.0", + "babel-eslint": "^10.1.0", + "eslint": "^8.56.0", + "eslint-config-airbnb": "19.0.4", + "eslint-config-airbnb-base": "15.0.0", + "eslint-plugin-es": "^4.1.0", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-jsx-a11y": "^6.2.3", + "eslint-plugin-react": "^7.18.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-rulesdir": "^0.2.2", + "lodash": "^4.17.21", + "underscore": "^1.13.6" } }, - "node_modules/eslint-config-expensify/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/scope-manager": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.12.0.tgz", + "integrity": "sha512-itF1pTnN6F3unPak+kutH9raIkL3lhH1YRPGgt7QQOh43DQKVJXmWkpb+vpc/TiDHs6RSd9CTbDsc/Y+Ygq7kg==", "dev": true, "dependencies": { - "type-fest": "^0.20.2" + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-config-expensify/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/types": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.12.0.tgz", + "integrity": "sha512-o+0Te6eWp2ppKY3mLCU+YA9pVJxhUJE15FV7kxuD9jgwIAa+w/ycGJBMrYDTpVGUM/tgpa9SeMOugSabWFq7bg==", "dev": true, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-config-expensify/node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.12.0.tgz", + "integrity": "sha512-5bwqLsWBULv1h6pn7cMW5dXX/Y2amRqLaKqsASVwbBHMZSnHqE/HN4vT4fE0aFsiwxYvr98kqOWh1a8ZKXalCQ==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/visitor-keys": "7.12.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/eslint-config-expensify/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", "dev": true, "dependencies": { - "argparse": "^2.0.1" + "brace-expansion": "^2.0.1" }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/eslint-config-expensify/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/utils": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.12.0.tgz", + "integrity": "sha512-Y6hhwxwDx41HNpjuYswYp6gDbkiZ8Hin9Bf5aJQn1bpTs3afYY4GX+MPYxma8jtoIV2GRwTM/UJm/2uGCVv+DQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.12.0", + "@typescript-eslint/types": "7.12.0", + "@typescript-eslint/typescript-estree": "7.12.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } }, - "node_modules/eslint-config-expensify/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/eslint-config-expensify/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.12.0.tgz", + "integrity": "sha512-uZk7DevrQLL3vSnfFl5bj4sL75qC9D6EdjemIdbtkuUmIheWpuiiylSY01JxJE7+zGrOWDZrp1WxOuDntvKrHQ==", "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@typescript-eslint/types": "7.12.0", + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=8" + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/eslint-config-expensify/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "node_modules/eslint-config-expensify/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/eslint-config-expensify/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-config-prettier": { - "version": "8.10.0", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, - "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -19933,18 +19513,21 @@ "node": ">=0.8.0" } }, - "node_modules/eslint-plugin-flowtype": { - "version": "2.50.3", + "node_modules/eslint-plugin-ft-flow": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-2.0.3.tgz", + "integrity": "sha512-Vbsd/b+LYA99jUbsL6viEUWShFaYQt2YQs3QN3f+aeszOhh2sgdcU0mjzDyD4yyBvMc8qy2uwvBBWfMzEX06tg==", "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "lodash": "^4.17.10" + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" }, "engines": { - "node": ">=4" + "node": ">=12.22.0" }, "peerDependencies": { - "eslint": ">=2.0.0" + "@babel/eslint-parser": "^7.12.0", + "eslint": "^8.1.0" } }, "node_modules/eslint-plugin-import": { @@ -20038,25 +19621,52 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "24.7.0", + "version": "28.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-28.6.0.tgz", + "integrity": "sha512-YG28E1/MIKwnz+e2H7VwYPzHUYU4aMa19w0yGcwXnnmJH6EfgHahTJ2un3IyraUxNfnz/KUhJAFXNNwWPo12tg==", "dev": true, - "license": "MIT", "dependencies": { - "@typescript-eslint/experimental-utils": "^4.0.1" + "@typescript-eslint/utils": "^6.0.0 || ^7.0.0" }, "engines": { - "node": ">=10" + "node": "^16.10.0 || ^18.12.0 || >=20.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": ">= 4", - "eslint": ">=5" + "@typescript-eslint/eslint-plugin": "^6.0.0 || ^7.0.0", + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0", + "jest": "*" }, "peerDependenciesMeta": { "@typescript-eslint/eslint-plugin": { "optional": true + }, + "jest": { + "optional": true } } }, + "node_modules/eslint-plugin-jest/node_modules/@typescript-eslint/utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, "node_modules/eslint-plugin-jsdoc": { "version": "46.2.6", "dev": true, @@ -20130,18 +19740,24 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "3.1.2", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", "dev": true, - "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=12.0.0" }, "peerDependencies": { - "eslint": ">= 5.0.0", - "prettier": ">= 1.13.0" + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, "node_modules/eslint-plugin-react": { @@ -20185,15 +19801,15 @@ } }, "node_modules/eslint-plugin-react-native": { - "version": "3.11.0", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-native/-/eslint-plugin-react-native-4.1.0.tgz", + "integrity": "sha512-QLo7rzTBOl43FvVqDdq5Ql9IoElIuTdjrz9SKAXCvULvBoRZ44JGSkx9z4999ZusCsb4rK3gjS8gOGyeYqZv2Q==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/traverse": "^7.7.4", "eslint-plugin-react-native-globals": "^0.1.1" }, "peerDependencies": { - "eslint": "^3.17.0 || ^4 || ^5 || ^6 || ^7" + "eslint": "^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8" } }, "node_modules/eslint-plugin-react-native-a11y": { @@ -20214,8 +19830,9 @@ }, "node_modules/eslint-plugin-react-native-globals": { "version": "0.1.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz", + "integrity": "sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g==", + "dev": true }, "node_modules/eslint-plugin-react/node_modules/doctrine": { "version": "2.1.0", @@ -20303,9 +19920,9 @@ } }, "node_modules/eslint-plugin-you-dont-need-lodash-underscore": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-you-dont-need-lodash-underscore/-/eslint-plugin-you-dont-need-lodash-underscore-6.12.0.tgz", - "integrity": "sha512-WF4mNp+k2532iswT6iUd1BX6qjd3AV4cFy/09VC82GY9SsRtvkxhUIx7JNGSe0/bLyd57oTr4inPFiIaENXhGw==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-you-dont-need-lodash-underscore/-/eslint-plugin-you-dont-need-lodash-underscore-6.14.0.tgz", + "integrity": "sha512-3zkkU/O1agczP7szJGHmisZJS/AknfVl6mb0Zqoc95dvFsdmfK+cbhrn+Ffy0UWB1pgDJwQr7kIO3rPstWs3Dw==", "dev": true, "dependencies": { "kebab-case": "^1.0.0" @@ -20332,23 +19949,6 @@ "node": ">=4.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, "node_modules/eslint-visitor-keys": { "version": "2.1.0", "dev": true, @@ -20357,14 +19957,6 @@ "node": ">=10" } }, - "node_modules/eslint/node_modules/@babel/code-frame": { - "version": "7.12.11", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, "node_modules/eslint/node_modules/ajv": { "version": "6.12.6", "dev": true, @@ -20394,6 +19986,12 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/eslint/node_modules/chalk": { "version": "4.1.2", "dev": true, @@ -20425,26 +20023,44 @@ "dev": true, "license": "MIT" }, - "node_modules/eslint/node_modules/eslint-utils": { - "version": "2.1.0", + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, - "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^1.1.0" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/mysticatea" + "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" } }, "node_modules/eslint/node_modules/globals": { @@ -20469,12 +20085,25 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", + "node_modules/eslint/node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 4" + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, "node_modules/eslint/node_modules/json-schema-traverse": { @@ -20505,24 +20134,44 @@ } }, "node_modules/espree": { - "version": "7.3.1", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/acorn": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" } }, "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "Apache-2.0", "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/esprima": { @@ -20782,9 +20431,9 @@ } }, "node_modules/expensify-common": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/expensify-common/-/expensify-common-2.0.17.tgz", - "integrity": "sha512-W7xO10/bYF/p0/cUOtzejXJDiLCB/U6JTXVltzOE70xjGgzTSyRotPkEtEItHTvXOS2Wz8jJ262nrGfFMpfisA==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/expensify-common/-/expensify-common-2.0.19.tgz", + "integrity": "sha512-GdWlYiHOAapy/jxjcvL9NKGOofhoEuKIwvJNGNVHbDXcA+0NxVCNYrHt1yrLnVcE4KtK6PGT6fQ2Lp8NTCoA+g==", "dependencies": { "awesome-phonenumber": "^5.4.0", "classnames": "2.5.0", @@ -22062,11 +21711,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/functions-have-names": { "version": "1.2.3", "dev": true, @@ -23352,8 +22996,9 @@ "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.2.4", - "license": "MIT", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "engines": { "node": ">= 4" } @@ -27702,11 +27347,6 @@ "version": "4.1.1", "license": "MIT" }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.union": { "version": "4.6.0", "dev": true, @@ -29179,6 +28819,12 @@ "version": "1.4.0", "license": "MIT" }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/ncp": { "version": "2.0.0", "license": "MIT", @@ -30833,8 +30479,9 @@ }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, - "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -35153,6 +34800,12 @@ "node": ">=10" } }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "dev": true + }, "node_modules/string-width": { "version": "4.2.3", "license": "MIT", @@ -35594,67 +35247,6 @@ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" }, - "node_modules/table": { - "version": "6.8.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/table/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/table/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/table/node_modules/slice-ansi": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -36098,8 +35690,9 @@ }, "node_modules/tinycolor2": { "version": "1.6.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "dev": true }, "node_modules/tinyqueue": { "version": "2.0.3", @@ -37030,11 +36623,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "dev": true, - "license": "MIT" - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "devOptional": true, diff --git a/package.json b/package.json index 590972f64299..3d679bd79557 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.0-4", + "version": "9.0.1-0", "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.", @@ -66,7 +66,7 @@ "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.85", + "@expensify/react-native-live-markdown": "0.1.88", "@expo/metro-runtime": "~3.1.1", "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-listformat": "^7.2.2", @@ -113,11 +113,12 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "2.0.17", + "expensify-common": "2.0.19", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", "expo-image-manipulator": "11.8.0", + "fast-equals": "^4.0.3", "focus-trap-react": "^10.2.3", "htmlparser2": "^7.2.0", "idb-keyval": "^6.2.1", @@ -205,14 +206,14 @@ "@babel/runtime": "^7.20.0", "@babel/traverse": "^7.22.20", "@babel/types": "^7.22.19", - "@dword-design/eslint-plugin-import-alias": "^4.0.8", + "@dword-design/eslint-plugin-import-alias": "^5.0.0", "@electron/notarize": "^2.1.0", "@jest/globals": "^29.5.0", "@ngneat/falso": "^7.1.1", "@octokit/core": "4.0.4", "@octokit/plugin-paginate-rest": "3.1.0", "@octokit/plugin-throttling": "4.1.0", - "@react-native-community/eslint-config": "3.0.0", + "@react-native-community/eslint-config": "3.2.0", "@react-native/babel-preset": "^0.73.21", "@react-native/metro-config": "^0.73.5", "@react-navigation/devtools": "^6.0.10", @@ -240,12 +241,11 @@ "@types/setimmediate": "^1.0.2", "@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", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", "@vercel/ncc": "0.38.1", "@welldone-software/why-did-you-render": "7.0.1", "ajv-cli": "^5.0.0", - "babel-eslint": "^10.1.0", "babel-jest": "29.4.1", "babel-loader": "^9.1.3", "babel-plugin-module-resolver": "^5.0.0", @@ -261,18 +261,16 @@ "dotenv": "^16.0.3", "electron": "^29.4.1", "electron-builder": "24.13.2", - "eslint": "^7.6.0", - "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-config-expensify": "^2.0.51", - "eslint-config-prettier": "^8.8.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^24.1.0", + "eslint": "^8.57.0", + "eslint-config-airbnb-typescript": "^18.0.0", + "eslint-config-expensify": "^2.0.52", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-jest": "^28.6.0", "eslint-plugin-jsdoc": "^46.2.6", - "eslint-plugin-jsx-a11y": "^6.6.1", "eslint-plugin-react-native-a11y": "^3.3.0", "eslint-plugin-storybook": "^0.8.0", "eslint-plugin-testing-library": "^6.2.2", - "eslint-plugin-you-dont-need-lodash-underscore": "^6.12.0", + "eslint-plugin-you-dont-need-lodash-underscore": "^6.14.0", "html-webpack-plugin": "^5.5.0", "jest": "29.4.1", "jest-circus": "29.4.1", diff --git a/patches/@expensify+react-native-live-markdown+0.1.85.patch b/patches/@expensify+react-native-live-markdown+0.1.85.patch new file mode 100644 index 000000000000..f745786a088e --- /dev/null +++ b/patches/@expensify+react-native-live-markdown+0.1.85.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/@expensify/react-native-live-markdown/lib/module/web/cursorUtils.js b/node_modules/@expensify/react-native-live-markdown/lib/module/web/cursorUtils.js +index e975fb2..6a4b510 100644 +--- a/node_modules/@expensify/react-native-live-markdown/lib/module/web/cursorUtils.js ++++ b/node_modules/@expensify/react-native-live-markdown/lib/module/web/cursorUtils.js +@@ -53,7 +53,7 @@ function setCursorPosition(target, start, end = null) { + // 3. Caret at the end of whole input, when pressing enter + // 4. All other placements + if (prevChar === '\n' && prevTextLength !== undefined && prevTextLength < textCharacters.length) { +- if (nextChar !== '\n') { ++ if (nextChar !== '\n' && i !== n - 1 && nextChar) { + range.setStart(textNodes[i + 1], 0); + } else if (i !== textNodes.length - 1) { + range.setStart(textNodes[i], 1); diff --git a/src/CONST.ts b/src/CONST.ts index 71ef5e26f7ae..c485268b55e2 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1555,6 +1555,7 @@ const CONST = { }, IOU: { + MAX_RECENT_REPORTS_TO_SHOW: 5, // This is the transactionID used when going through the create expense flow so that it mimics a real transaction (like the edit flow) OPTIMISTIC_TRANSACTION_ID: '1', // Note: These payment types are used when building IOU reportAction message values in the server and should @@ -1833,6 +1834,21 @@ const CONST = { XERO_SYNC_IMPORT_TAX_RATES: 'xeroSyncImportTaxRates', XERO_CHECK_CONNECTION: 'xeroCheckConnection', XERO_SYNC_TITLE: 'xeroSyncTitle', + NETSUITE_SYNC_CONNECTION: 'netSuiteSyncConnection', + NETSUITE_SYNC_CUSTOMERS: 'netSuiteSyncCustomers', + NETSUITE_SYNC_INIT_DATA: 'netSuiteSyncInitData', + NETSUITE_SYNC_IMPORT_TAXES: 'netSuiteSyncImportTaxes', + NETSUITE_SYNC_IMPORT_ITEMS: 'netSuiteSyncImportItems', + NETSUITE_SYNC_DATA: 'netSuiteSyncData', + NETSUITE_SYNC_ACCOUNTS: 'netSuiteSyncAccounts', + NETSUITE_SYNC_CURRENCIES: 'netSuiteSyncCurrencies', + NETSUITE_SYNC_CATEGORIES: 'netSuiteSyncCategories', + NETSUITE_SYNC_IMPORT_EMPLOYEES: 'netSuiteSyncImportEmployees', + NETSUITE_SYNC_REPORT_FIELDS: 'netSuiteSyncReportFields', + NETSUITE_SYNC_TAGS: 'netSuiteSyncTags', + NETSUITE_SYNC_UPDATE_DATA: 'netSuiteSyncUpdateConnectionData', + NETSUITE_SYNC_NETSUITE_REIMBURSED_REPORTS: 'netSuiteSyncNetSuiteReimbursedReports', + NETSUITE_SYNC_EXPENSIFY_REIMBURSED_REPORTS: 'netSuiteSyncExpensifyReimbursedReports', }, SYNC_STAGE_TIMEOUT_MINUTES: 20, }, @@ -2126,6 +2142,8 @@ const CONST = { SETTINGS: 'settings', LEAVE_ROOM: 'leaveRoom', PRIVATE_NOTES: 'privateNotes', + DELETE: 'delete', + MARK_AS_INCOMPLETE: 'markAsIncomplete', }, EDIT_REQUEST_FIELD: { AMOUNT: 'amount', @@ -3735,6 +3753,14 @@ const CONST = { REPORT: 'REPORT', }, + PROMOTED_ACTIONS: { + PIN: 'pin', + SHARE: 'share', + JOIN: 'join', + MESSAGE: 'message', + HOLD: 'hold', + }, + THUMBNAIL_IMAGE: { SMALL_SCREEN: { SIZE: 250, diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 8a20032b4f91..b5eea4228042 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -339,6 +339,9 @@ const ONYXKEYS = { /** Holds the checks used while transferring the ownership of the workspace */ POLICY_OWNERSHIP_CHANGE_CHECKS: 'policyOwnershipChangeChecks', + /** Stores info during review duplicates flow */ + REVIEW_DUPLICATES: 'reviewDuplicates', + /** Collection Keys */ COLLECTION: { DOWNLOAD: 'download_', @@ -719,6 +722,7 @@ type OnyxValuesMapping = { [ONYXKEYS.CACHED_PDF_PATHS]: Record; [ONYXKEYS.POLICY_OWNERSHIP_CHANGE_CHECKS]: Record; [ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE]: OnyxTypes.QuickAction; + [ONYXKEYS.REVIEW_DUPLICATES]: OnyxTypes.ReviewDuplicates; [ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL]: string; [ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL]: string; [ONYXKEYS.NVP_BILLING_FUND_ID]: number; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index c1fdd68951fa..f39e4b5aa431 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -823,6 +823,11 @@ const ROUTES = { route: 'r/:reportID/transaction/:transactionID/receipt', getRoute: (reportID: string, transactionID: string) => `r/${reportID}/transaction/${transactionID}/receipt` as const, }, + TRANSACTION_DUPLICATE_REVIEW_PAGE: { + route: 'r/:threadReportID/duplicates/review', + getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review` as const, + }, + POLICY_ACCOUNTING_XERO_IMPORT: { route: 'settings/workspaces/:policyID/accounting/xero/import', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/xero/import` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index f884cca94ef5..f89469873ac7 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -138,6 +138,7 @@ const SCREENS = { ROOM_INVITE: 'RoomInvite', REFERRAL: 'Referral', PROCESS_MONEY_REQUEST_HOLD: 'ProcessMoneyRequestHold', + TRANSACTION_DUPLICATE: 'TransactionDuplicate', TRAVEL: 'Travel', SEARCH_REPORT: 'SearchReport', SETTINGS_CATEGORIES: 'SettingsCategories', @@ -179,6 +180,10 @@ const SCREENS = { STATE_SELECTOR: 'Money_Request_State_Selector', }, + TRANSACTION_DUPLICATE: { + REVIEW: 'Transaction_Duplicate_Review', + }, + IOU_SEND: { ADD_BANK_ACCOUNT: 'IOU_Send_Add_Bank_Account', ADD_DEBIT_CARD: 'IOU_Send_Add_Debit_Card', diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index 3a8a4e724948..d37c4348e510 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -20,6 +20,7 @@ import updateIsFullComposerAvailable from '@libs/ComposerUtils/updateIsFullCompo import * as EmojiUtils from '@libs/EmojiUtils'; import * as FileUtils from '@libs/fileDownload/FileUtils'; import isEnterWhileComposition from '@libs/KeyboardShortcut/isEnterWhileComposition'; +import Log from '@libs/Log'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; import CONST from '@src/CONST'; import type {ComposerProps} from './types'; @@ -106,11 +107,22 @@ function Composer( const isScrollBarVisible = useIsScrollBarVisible(textInput, value ?? ''); const [prevScroll, setPrevScroll] = useState(); + // Those useEffects track changes of `shouldClear` and `onClear` independently. + useEffect(() => { + Log.info('[Composer] `shouldClear` value changed', true, {shouldClear}); + }, [shouldClear]); + + useEffect(() => { + Log.info('[Composer] `onClear` value changed', true, {shouldClear}); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [onClear]); + useEffect(() => { if (!shouldClear) { return; } textInput.current?.clear(); + Log.info('[Composer] `textInput` cleared', true, {shouldClear}); onClear(); }, [shouldClear, onClear]); diff --git a/src/components/ConfirmedRoute.tsx b/src/components/ConfirmedRoute.tsx index b6d6bb13213c..315afd2dbddc 100644 --- a/src/components/ConfirmedRoute.tsx +++ b/src/components/ConfirmedRoute.tsx @@ -118,6 +118,7 @@ function ConfirmedRoute({mapboxAccessToken, transaction, isSmallerIcon, shouldHa style={[styles.mapView, shouldHaveBorderRadius && styles.br4]} waypoints={waypointMarkers} styleURL={CONST.MAPBOX.STYLE_URL} + requireRouteToDisplayMap={requireRouteToDisplayMap} /> ) : ( Navigation.goBack()} /> diff --git a/src/components/CustomStylesForChildrenProvider.tsx b/src/components/CustomStylesForChildrenProvider.tsx new file mode 100644 index 000000000000..6fc7efa81ed8 --- /dev/null +++ b/src/components/CustomStylesForChildrenProvider.tsx @@ -0,0 +1,21 @@ +import React, {useMemo} from 'react'; +import type {StyleProp, TextStyle, ViewStyle} from 'react-native'; + +type CustomStylesForChildrenContextType = StyleProp | null; + +const CustomStylesForChildrenContext = React.createContext(null); + +type CustomStylesForChildrenProviderProps = React.PropsWithChildren & { + style: StyleProp | null; +}; + +function CustomStylesForChildrenProvider({children, style}: CustomStylesForChildrenProviderProps) { + const value = useMemo(() => style, [style]); + + return {children}; +} + +CustomStylesForChildrenProvider.displayName = 'CustomStylesForChildrenProvider'; + +export default CustomStylesForChildrenProvider; +export {CustomStylesForChildrenContext}; diff --git a/src/components/DistanceMapView/index.android.tsx b/src/components/DistanceMapView/index.android.tsx index 629b05d7bccf..930b08cad2d5 100644 --- a/src/components/DistanceMapView/index.android.tsx +++ b/src/components/DistanceMapView/index.android.tsx @@ -3,18 +3,21 @@ import {View} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; import * as Expensicons from '@components/Icon/Expensicons'; import MapView from '@components/MapView'; +import PendingMapView from '@components/MapView/PendingMapView'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; +import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import type DistanceMapViewProps from './types'; -function DistanceMapView({overlayStyle, ...rest}: DistanceMapViewProps) { +function DistanceMapView({overlayStyle, requireRouteToDisplayMap, ...rest}: DistanceMapViewProps) { const styles = useThemeStyles(); const [isMapReady, setIsMapReady] = useState(false); const {isOffline} = useNetwork(); const {translate} = useLocalize(); const theme = useTheme(); + const StyleUtils = useStyleUtils(); return ( <> @@ -29,14 +32,22 @@ function DistanceMapView({overlayStyle, ...rest}: DistanceMapViewProps) { }} /> {!isMapReady && ( - - + + {/* The "map pending" text should only be shown in the IOU create flow. In the created IOU preview, only the icon should be shown. */} + {!requireRouteToDisplayMap ? ( + + ) : ( + + )} )} diff --git a/src/components/DistanceMapView/types.ts b/src/components/DistanceMapView/types.ts index 18213235445f..1621870d70ed 100644 --- a/src/components/DistanceMapView/types.ts +++ b/src/components/DistanceMapView/types.ts @@ -3,6 +3,10 @@ import type {MapViewProps} from '@components/MapView/MapViewTypes'; type DistanceMapViewProps = MapViewProps & { overlayStyle?: StyleProp; + + /** Whether it should display the Mapbox map only when the route/coordinates exist otherwise + * it will display pending map icon */ + requireRouteToDisplayMap?: boolean; }; export default DistanceMapViewProps; diff --git a/src/components/FeedbackSurvey.tsx b/src/components/FeedbackSurvey.tsx index 925448046076..a7b0732be1fb 100644 --- a/src/components/FeedbackSurvey.tsx +++ b/src/components/FeedbackSurvey.tsx @@ -92,7 +92,7 @@ function FeedbackSurvey({title, description, onSubmit, optionRowStyles}: Feedbac diff --git a/src/components/Form/FormProvider.tsx b/src/components/Form/FormProvider.tsx index bed4cea31829..9df94e4c6114 100644 --- a/src/components/Form/FormProvider.tsx +++ b/src/components/Form/FormProvider.tsx @@ -350,7 +350,7 @@ function FormProvider( }); if (inputProps.shouldSaveDraft && !formID.includes('Draft')) { - FormActions.setDraftValues(formID as OnyxFormKey, {[inputKey]: value}); + FormActions.setDraftValues(formID, {[inputKey]: value}); } inputProps.onValueChange?.(value, inputKey); }, diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer.tsx index 27c7f229a247..49850d73e2d7 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer.tsx @@ -33,7 +33,7 @@ const getMentionDetails = (htmlAttributeReportID: string, currentReport: OnyxEnt // Get mention details based on reportID from tag attribute if (!isEmpty(htmlAttributeReportID)) { - const report = reports?.[htmlAttributeReportID]; + const report = reports?.[`${ONYXKEYS.COLLECTION.REPORT}${htmlAttributeReportID}`]; reportID = report?.reportID ?? htmlAttributeReportID; mentionDisplayText = removeLeadingLTRAndHash(report?.reportName ?? report?.displayName ?? htmlAttributeReportID); // Get mention details from name inside tnode diff --git a/src/components/MoneyRequestHeader.tsx b/src/components/MoneyRequestHeader.tsx index b10a09e4f7e8..82b33a674b18 100644 --- a/src/components/MoneyRequestHeader.tsx +++ b/src/components/MoneyRequestHeader.tsx @@ -80,7 +80,6 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow const isApprover = ReportUtils.isMoneyRequestReport(moneyRequestReport) && moneyRequestReport?.managerID !== null && session?.accountID === moneyRequestReport?.managerID; const hasAllPendingRTERViolations = TransactionUtils.allHavePendingRTERViolation([transaction?.transactionID ?? '-1']); const shouldShowMarkAsCashButton = isDraft && hasAllPendingRTERViolations; - const deleteTransaction = useCallback(() => { if (parentReportAction) { const iouTransactionID = ReportActionsUtils.isMoneyRequestAction(parentReportAction) ? ReportActionsUtils.getOriginalMessage(parentReportAction)?.IOUTransactionID ?? '-1' : '-1'; @@ -245,6 +244,9 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow medium text={translate('iou.reviewDuplicates')} style={[styles.p0]} + onPress={() => { + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_PAGE.getRoute(report.reportID)); + }} /> )} @@ -266,6 +268,9 @@ function MoneyRequestHeader({report, parentReportAction, policy, shouldUseNarrow medium text={translate('iou.reviewDuplicates')} style={[styles.w100, styles.pr0]} + onPress={() => { + Navigation.navigate(ROUTES.TRANSACTION_DUPLICATE_REVIEW_PAGE.getRoute(report.reportID)); + }} /> )} diff --git a/src/components/OfflineWithFeedback.tsx b/src/components/OfflineWithFeedback.tsx index 70354c4a4676..28e1d81b30e4 100644 --- a/src/components/OfflineWithFeedback.tsx +++ b/src/components/OfflineWithFeedback.tsx @@ -13,6 +13,7 @@ import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {ReceiptError, ReceiptErrors} from '@src/types/onyx/Transaction'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import CustomStylesForChildrenProvider from './CustomStylesForChildrenProvider'; import MessagesRow from './MessagesRow'; /** @@ -134,7 +135,7 @@ function OfflineWithFeedback({ style={[needsOpacity ? styles.offlineFeedback.pending : {}, contentContainerStyle]} needsOffscreenAlphaCompositing={shouldRenderOffscreen ? needsOpacity && needsOffscreenAlphaCompositing : undefined} > - {children} + {children} )} {shouldShowErrorMessages && hasErrorMessages && ( diff --git a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx index e866f76e1237..da5ce1e43085 100644 --- a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx +++ b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx @@ -110,12 +110,18 @@ function GenericPressable( ref.current?.blur(); Accessibility.moveAccessibilityFocus(nextFocusRef); } - const onPressResult = onPress(event); - return onPressResult; + return onPress(event); }, [shouldUseHapticsOnPress, onPress, nextFocusRef, ref, isDisabled], ); + const voidOnPressHandler = useCallback( + (...args: Parameters) => { + onPressHandler(...args); + }, + [onPressHandler], + ); + const onKeyboardShortcutPressHandler = useCallback( (event?: GestureResponderEvent | KeyboardEvent) => { onPressHandler(event); @@ -159,8 +165,8 @@ function GenericPressable( aria-disabled={isDisabled} aria-keyshortcuts={keyboardShortcut && `${keyboardShortcut.modifiers.join('')}+${keyboardShortcut.shortcutKey}`} // ios-only form of inputs - onMagicTap={!isDisabled ? onPressHandler : undefined} - onAccessibilityTap={!isDisabled ? onPressHandler : undefined} + onMagicTap={!isDisabled ? voidOnPressHandler : undefined} + onAccessibilityTap={!isDisabled ? voidOnPressHandler : undefined} accessible={accessible} // eslint-disable-next-line react/jsx-props-no-spreading {...rest} diff --git a/src/components/PromotedActionsBar.tsx b/src/components/PromotedActionsBar.tsx index b98ab7fcbc32..b3bfe34df542 100644 --- a/src/components/PromotedActionsBar.tsx +++ b/src/components/PromotedActionsBar.tsx @@ -5,7 +5,12 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import * as HeaderUtils from '@libs/HeaderUtils'; import * as Localize from '@libs/Localize'; +import Navigation from '@libs/Navigation/Navigation'; +import * as ReportUtils from '@libs/ReportUtils'; import * as ReportActions from '@userActions/Report'; +import * as Session from '@userActions/Session'; +import CONST from '@src/CONST'; +import type {ReportAction} from '@src/types/onyx'; import type OnyxReport from '@src/types/onyx/Report'; import Button from './Button'; import type {ThreeDotsMenuItem} from './HeaderWithBackButton/types'; @@ -15,21 +20,34 @@ type PromotedAction = { key: string; } & ThreeDotsMenuItem; -type PromotedActionsType = Record<'pin' | 'share', (report: OnyxReport) => PromotedAction> & { +type BasePromotedActions = typeof CONST.PROMOTED_ACTIONS.PIN | typeof CONST.PROMOTED_ACTIONS.SHARE | typeof CONST.PROMOTED_ACTIONS.JOIN; + +type PromotedActionsType = Record PromotedAction> & { message: (params: {accountID?: number; login?: string}) => PromotedAction; +} & { + hold: (params: {isTextHold: boolean; reportAction: ReportAction | undefined}) => PromotedAction; }; const PromotedActions = { pin: (report) => ({ - key: 'pin', + key: CONST.PROMOTED_ACTIONS.PIN, ...HeaderUtils.getPinMenuItem(report), }), share: (report) => ({ - key: 'share', + key: CONST.PROMOTED_ACTIONS.SHARE, ...HeaderUtils.getShareMenuItem(report), }), + join: (report) => ({ + key: CONST.PROMOTED_ACTIONS.JOIN, + icon: Expensicons.ChatBubbles, + text: Localize.translateLocal('common.join'), + onSelected: Session.checkIfActionIsAllowed(() => { + Navigation.dismissModal(); + ReportActions.joinRoom(report); + }), + }), message: ({accountID, login}) => ({ - key: 'message', + key: CONST.PROMOTED_ACTIONS.MESSAGE, icon: Expensicons.CommentBubbles, text: Localize.translateLocal('common.message'), onSelected: () => { @@ -43,6 +61,15 @@ const PromotedActions = { } }, }), + hold: ({isTextHold, reportAction}) => ({ + key: CONST.PROMOTED_ACTIONS.HOLD, + icon: Expensicons.Stopwatch, + text: Localize.translateLocal(`iou.${isTextHold ? 'hold' : 'unhold'}`), + onSelected: () => { + Navigation.dismissModal(); + ReportUtils.changeMoneyRequestHoldStatus(reportAction); + }, + }), } satisfies PromotedActionsType; type PromotedActionsBarProps = { @@ -61,10 +88,6 @@ function PromotedActionsBar({promotedActions, containerStyle}: PromotedActionsBa return null; } - if (promotedActions.length === 0) { - return null; - } - return ( {promotedActions.map(({key, onSelected, ...props}) => ( diff --git a/src/components/ReportActionItem/MoneyRequestAction.tsx b/src/components/ReportActionItem/MoneyRequestAction.tsx index b8f02f83d1cd..15f9cee3705c 100644 --- a/src/components/ReportActionItem/MoneyRequestAction.tsx +++ b/src/components/ReportActionItem/MoneyRequestAction.tsx @@ -59,6 +59,9 @@ type MoneyRequestActionProps = MoneyRequestActionOnyxProps & { /** Styles to be assigned to Container */ style?: StyleProp; + + /** Whether context menu should be shown on press */ + shouldDisplayContextMenu?: boolean; }; function MoneyRequestAction({ @@ -75,11 +78,11 @@ function MoneyRequestAction({ isHovered = false, style, isWhisper = false, + shouldDisplayContextMenu = true, }: MoneyRequestActionProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const {isOffline} = useNetwork(); - const isSplitBillAction = ReportActionsUtils.isSplitBillAction(action); const isTrackExpenseAction = ReportActionsUtils.isTrackExpenseAction(action); @@ -132,6 +135,7 @@ function MoneyRequestAction({ containerStyles={[styles.cursorPointer, isHovered ? styles.reportPreviewBoxHoverBorder : undefined, style]} isHovered={isHovered} isWhisper={isWhisper} + shouldDisplayContextMenu={shouldDisplayContextMenu} /> ); } diff --git a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx index 952e66cb1154..05df4acac5a6 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestPreview/MoneyRequestPreviewContent.tsx @@ -1,8 +1,10 @@ +import {useRoute} from '@react-navigation/native'; import lodashSortBy from 'lodash/sortBy'; import truncate from 'lodash/truncate'; import React, {useMemo} from 'react'; import {View} from 'react-native'; import type {GestureResponderEvent} from 'react-native'; +import Button from '@components/Button'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import {ReceiptScan} from '@components/Icon/Expensicons'; @@ -35,7 +37,10 @@ import ViolationsUtils from '@libs/Violations/ViolationsUtils'; import variables from '@styles/variables'; import * as PaymentMethods from '@userActions/PaymentMethods'; import * as Report from '@userActions/Report'; +import * as Transaction from '@userActions/Transaction'; import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import SCREENS from '@src/SCREENS'; import type {OriginalMessageIOU} from '@src/types/onyx/OriginalMessage'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; @@ -60,12 +65,14 @@ function MoneyRequestPreviewContent({ isHovered = false, isWhisper = false, transactionViolations, + shouldDisplayContextMenu = true, }: MoneyRequestPreviewProps) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); const {windowWidth} = useWindowDimensions(); + const route = useRoute(); const {shouldUseNarrowLayout} = useResponsiveLayout(); const sessionAccountID = session?.accountID; @@ -111,12 +118,23 @@ function MoneyRequestPreviewContent({ const isCardTransaction = TransactionUtils.isCardTransaction(transaction); const isSettled = ReportUtils.isSettled(iouReport?.reportID); const isDeleted = action?.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; + const isReviewDuplicateTransactionPage = route.name === SCREENS.TRANSACTION_DUPLICATE.REVIEW; + const isFullySettled = isSettled && !isSettlementOrApprovalPartial; const isFullyApproved = ReportUtils.isReportApproved(iouReport) && !isSettlementOrApprovalPartial; const shouldShowRBR = hasNoticeTypeViolations || hasViolations || hasFieldErrors || (!isFullySettled && !isFullyApproved && isOnHold); const showCashOrCard = isCardTransaction ? translate('iou.card') : translate('iou.cash'); const shouldShowHoldMessage = !(isSettled && !isSettlementOrApprovalPartial) && isOnHold; + // Get transaction violations for given transaction id from onyx, find duplicated transactions violations and get duplicates + const duplicates = useMemo( + () => + transactionViolations?.[`${ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS}${transaction?.transactionID}`]?.find( + (violation) => violation.name === CONST.VIOLATIONS.DUPLICATED_TRANSACTION, + )?.data?.duplicates ?? [], + [transaction?.transactionID, transactionViolations], + ); + /* Show the merchant for IOUs and expenses only if: - the merchant is not empty, is custom, or is not related to scanning smartscan; @@ -145,6 +163,9 @@ function MoneyRequestPreviewContent({ }; const showContextMenu = (event: GestureResponderEvent) => { + if (!shouldDisplayContextMenu) { + return; + } showContextMenuForReport(event, contextMenuAnchor, reportID, action, checkIfContextMenuActive); }; @@ -382,6 +403,17 @@ function MoneyRequestPreviewContent({ ]} > {childContainer} + {isReviewDuplicateTransactionPage && ( +