diff --git a/.gitignore b/.gitignore index 8265d5fd272b..94c646a04246 100644 --- a/.gitignore +++ b/.gitignore @@ -94,3 +94,4 @@ storybook-static # E2E test reports tests/e2e/results/ +.reassure diff --git a/android/app/build.gradle b/android/app/build.gradle index b0fa64f57a50..9227a6b382b9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -106,8 +106,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001032002 - versionName "1.3.20-2" + versionCode 1001032200 + versionName "1.3.22-0" } splits { diff --git a/assets/images/flag.svg b/assets/images/flag.svg new file mode 100644 index 000000000000..9b6737459fbd --- /dev/null +++ b/assets/images/flag.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/assets/images/flag_level_01.svg b/assets/images/flag_level_01.svg new file mode 100644 index 000000000000..a4259deb0d2c --- /dev/null +++ b/assets/images/flag_level_01.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/assets/images/flag_level_02.svg b/assets/images/flag_level_02.svg new file mode 100644 index 000000000000..9d7010dbb7f9 --- /dev/null +++ b/assets/images/flag_level_02.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/assets/images/flag_level_03.svg b/assets/images/flag_level_03.svg new file mode 100644 index 000000000000..14fc80792cc2 --- /dev/null +++ b/assets/images/flag_level_03.svg @@ -0,0 +1,13 @@ + + + + + + + diff --git a/dangerfile.js b/dangerfile.js new file mode 100644 index 000000000000..1fa05fde711f --- /dev/null +++ b/dangerfile.js @@ -0,0 +1,7 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import path from 'path'; +import {dangerReassure} from 'reassure'; + +dangerReassure({ + inputFilePath: path.join(__dirname, './.reassure/output.md'), +}); diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index a67bdda052dd..323e7336b19f 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.3.20 + 1.3.22 CFBundleSignature ???? CFBundleURLTypes @@ -30,7 +30,7 @@ CFBundleVersion - 1.3.20.2 + 1.3.22.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 86d52d04cc68..28a5b85a6a97 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.3.20 + 1.3.22 CFBundleSignature ???? CFBundleVersion - 1.3.20.2 + 1.3.22.0 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 055d696ec5d8..65bf60c3bd89 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -16,7 +16,7 @@ PODS: - Airship/Core - Airship/PreferenceCenter (16.11.3): - Airship/Core - - AirshipFrameworkProxy (2.0.5): + - AirshipFrameworkProxy (2.0.8): - Airship (= 16.11.3) - Airship/MessageCenter (= 16.11.3) - Airship/PreferenceCenter (= 16.11.3) @@ -495,8 +495,8 @@ PODS: - React-jsinspector (0.71.2-alpha.3) - React-logger (0.71.2-alpha.3): - glog - - react-native-airship (15.2.3): - - AirshipFrameworkProxy (= 2.0.5) + - react-native-airship (15.2.6): + - AirshipFrameworkProxy (= 2.0.8) - React-Core - react-native-blob-util (0.17.3): - React-Core @@ -1018,8 +1018,8 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Airship: c70eed50e429f97f5adb285423c7291fb7a032ae - AirshipFrameworkProxy: 2eefb77bb77b5120b0f48814b0d44439aa3ad415 - boost: 57d2868c099736d80fcd648bf211b4431e51a558 + AirshipFrameworkProxy: 7bc4130c668c6c98e2d4c60fe4c9eb61a999be99 + boost: a7c83b31436843459a1961bfd74b96033dc77234 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: ff54429f0110d3c722630a98096ba689c39f6d5f @@ -1062,7 +1062,7 @@ SPEC CHECKSUMS: Permission-LocationWhenInUse: 3ba99e45c852763f730eabecec2870c2382b7bd4 Plaid: 7d340abeadb46c7aa1a91f896c5b22395a31fcf2 PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef - RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 + RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda RCTRequired: e9e7b8b45aa9bedb2fdad71740adf07a7265b9be RCTTypeSafety: 9ae0e9206625e995f0df4d5b9ddc94411929fb30 React: a71c8e1380f07e01de721ccd52bcf9c03e81867d @@ -1076,7 +1076,7 @@ SPEC CHECKSUMS: React-jsiexecutor: 6f986feb67cf66edff7f98090ca797a67d0a44fb React-jsinspector: 31517b1de3fadf93ad8558840a8974c7a7160bd3 React-logger: b90aa6ed0dbc30717dc72d843af3cf4550297b22 - react-native-airship: 25045092934bf6eabf483e803af0a6e31826b8b9 + react-native-airship: 5d19f4ba303481cf4101ff9dee9249ef6a8a6b64 react-native-blob-util: 99f4d79189252f597fe0d810c57a3733b1b1dea6 react-native-cameraroll: 8ffb0af7a5e5de225fd667610e2979fc1f0c2151 react-native-config: 7cd105e71d903104e8919261480858940a6b9c0e diff --git a/package-lock.json b/package-lock.json index f67e98694149..80dd7c471541 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.3.20-2", + "version": "1.3.22-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.3.20-2", + "version": "1.3.22-0", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -35,13 +35,13 @@ "@react-navigation/native": "6.0.13", "@react-navigation/stack": "6.3.1", "@react-ng/bounds-observer": "^0.2.1", - "@ua/react-native-airship": "^15.2.3", + "@ua/react-native-airship": "^15.2.6", "awesome-phonenumber": "^5.4.0", "babel-plugin-transform-remove-console": "^6.9.4", "babel-polyfill": "^6.26.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#68abe48ad71a98604fdbf5e8e960023ed5807ec2", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#c898563fe851d9a4d594fa9afbdd1ddab5971636", "fbjs": "^3.0.2", "html-entities": "^1.3.1", "htmlparser2": "^7.2.0", @@ -142,6 +142,7 @@ "concurrently": "^5.3.0", "copy-webpack-plugin": "^6.4.1", "css-loader": "^6.7.2", + "danger": "^11.2.6", "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", "electron": "22.3.7", @@ -171,6 +172,7 @@ "react-native-performance-flipper-reporter": "^2.0.0", "react-native-svg-transformer": "^1.0.0", "react-test-renderer": "18.1.0", + "reassure": "^0.9.0", "setimmediate": "^1.0.5", "shellcheck": "^1.1.0", "style-loader": "^2.0.0", @@ -2043,10 +2045,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.18.9", - "license": "MIT", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", + "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", "dependencies": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" }, "engines": { "node": ">=6.9.0" @@ -2131,6 +2134,252 @@ "integrity": "sha512-iZf+UWfL+DogJVpd/xMQyP6X6McYd6ArdYoPMiv/zlOTzeXXfQbYxBNJJBF6tThvsjLMbA8tLjkCdm9RWMFCCw==", "dev": true }, + "node_modules/@callstack/reassure-cli": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@callstack/reassure-cli/-/reassure-cli-0.9.0.tgz", + "integrity": "sha512-auoxqyilxkT5mDdEPJqRRY+ZGlrihJjFQpopcFd/15ng76OPVka3L48RMEY2wXkFXLaOOs6enNGb596jYPuEtQ==", + "dev": true, + "dependencies": { + "@callstack/reassure-compare": "0.5.0", + "@callstack/reassure-logger": "0.3.0", + "chalk": "4.1.2", + "simple-git": "^3.16.0", + "yargs": "^17.6.2" + }, + "bin": { + "reassure": "lib/commonjs/bin.js" + } + }, + "node_modules/@callstack/reassure-cli/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/@callstack/reassure-cli/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/@callstack/reassure-cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@callstack/reassure-cli/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/@callstack/reassure-cli/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/@callstack/reassure-cli/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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@callstack/reassure-cli/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==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@callstack/reassure-cli/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@callstack/reassure-cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@callstack/reassure-cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@callstack/reassure-compare": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@callstack/reassure-compare/-/reassure-compare-0.5.0.tgz", + "integrity": "sha512-3sBeJ/+Hxjdb01KVb8LszO1kcJ8TXcrVnerUj+LYn2dkBOohAMqGYaOvCeoWsVEHJ+MIOzmvAGBJQRu69RoJdQ==", + "dev": true, + "dependencies": { + "@callstack/reassure-logger": "0.3.0", + "markdown-builder": "^0.9.0", + "markdown-table": "^2.0.0", + "zod": "^3.20.2" + } + }, + "node_modules/@callstack/reassure-danger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@callstack/reassure-danger/-/reassure-danger-0.1.1.tgz", + "integrity": "sha512-lfza+qBdvVYtP7WvMTT+LfjBfuYsXZ4RxuBldsL8wJArGeCl3OZwUg+9bTo8v6kk/nY8memk5HxrCwWDSO24UA==", + "dev": true + }, + "node_modules/@callstack/reassure-logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@callstack/reassure-logger/-/reassure-logger-0.3.0.tgz", + "integrity": "sha512-JX5o+8qkIbIRL+cQn9XlQYdv9p/3L6J70zZX6NYi9j0VrSS9PZIRfo8ujMdLSqUNV6HZN1ay59RzuncLjVu0aQ==", + "dev": true, + "dependencies": { + "chalk": "4.1.2" + } + }, + "node_modules/@callstack/reassure-logger/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/@callstack/reassure-logger/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/@callstack/reassure-logger/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/@callstack/reassure-logger/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/@callstack/reassure-logger/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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@callstack/reassure-logger/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==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@callstack/reassure-measure": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@callstack/reassure-measure/-/reassure-measure-0.5.0.tgz", + "integrity": "sha512-KwlmNYcspBOp7FIw6XOz5O9mnKB4cWCCyM6vG4nFUPHSWQ6yVdRkawVvoPIV5qJ2hw7zCzdtqRrLWQSTF4eKlg==", + "dev": true, + "dependencies": { + "@callstack/reassure-logger": "0.3.0", + "mathjs": "^11.5.0" + }, + "peerDependencies": { + "react": "*" + } + }, "node_modules/@cnakazawa/watch": { "version": "1.0.4", "dev": true, @@ -2571,6 +2820,70 @@ "dev": true, "license": "MIT" }, + "node_modules/@gitbeaker/core": { + "version": "21.7.0", + "resolved": "https://registry.npmjs.org/@gitbeaker/core/-/core-21.7.0.tgz", + "integrity": "sha512-cw72rE7tA27wc6JJe1WqeAj9v/6w0S7XJcEji+bRNjTlUfE1zgfW0Gf1mbGUi7F37SOABGCosQLfg9Qe63aIqA==", + "dev": true, + "dependencies": { + "@gitbeaker/requester-utils": "^21.7.0", + "form-data": "^3.0.0", + "li": "^1.3.0", + "xcase": "^2.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@gitbeaker/node": { + "version": "21.7.0", + "resolved": "https://registry.npmjs.org/@gitbeaker/node/-/node-21.7.0.tgz", + "integrity": "sha512-OdM3VcTKYYqboOsnbiPcO0XimXXpYK4gTjARBZ6BWc+1LQXKmqo+OH6oUbyxOoaFu9hHECafIt3WZU3NM4sZTg==", + "deprecated": "Please use its successor @gitbeaker/rest", + "dev": true, + "dependencies": { + "@gitbeaker/core": "^21.7.0", + "@gitbeaker/requester-utils": "^21.7.0", + "form-data": "^3.0.0", + "got": "^11.1.4", + "xcase": "^2.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@gitbeaker/requester-utils": { + "version": "21.7.0", + "resolved": "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-21.7.0.tgz", + "integrity": "sha512-eLTaVXlBnh8Qimj6QuMMA06mu/mLcJm3dy8nqhhn/Vm/D25sPrvpGwmbfFyvzj6QujPqtHvFfsCHtyZddL01qA==", + "dev": true, + "dependencies": { + "form-data": "^3.0.0", + "query-string": "^6.12.1", + "xcase": "^2.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@gitbeaker/requester-utils/node_modules/query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "dev": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@gorhom/portal": { "version": "1.0.14", "license": "MIT", @@ -4230,6 +4543,21 @@ "react-native": "*" } }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "dev": true + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "dev": true, @@ -4585,6 +4913,15 @@ "@octokit/core": ">=4" } }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, "node_modules/@octokit/plugin-rest-endpoint-methods": { "version": "5.16.2", "dev": true, @@ -4667,6 +5004,101 @@ "@octokit/openapi-types": "^13.1.0" } }, + "node_modules/@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "dev": true, + "dependencies": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dev": true, + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dev": true, + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.40.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dev": true, + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dev": true, + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, "node_modules/@octokit/types": { "version": "6.41.0", "dev": true, @@ -15634,9 +16066,9 @@ } }, "node_modules/@ua/react-native-airship": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@ua/react-native-airship/-/react-native-airship-15.2.3.tgz", - "integrity": "sha512-94fgHJcxc4qUy9OmBqt6VuuWggoeCMNIosz3/qwiUNsUVoE1deWcOEG9vULmXcTKX+O9Wal/mKsuPGiFCALTDQ==", + "version": "15.2.6", + "resolved": "https://registry.npmjs.org/@ua/react-native-airship/-/react-native-airship-15.2.6.tgz", + "integrity": "sha512-dVlBPPYXD/4SEshv/X7mmt3xF8WfnNqiSNzCyqJSLAZ1aJuPpP9Z5WemCYsa2iv6goRZvtJSE4P79QKlfoTwXw==", "engines": { "node": ">= 16.0.0" }, @@ -16755,6 +17187,24 @@ "version": "1.0.1", "license": "MIT" }, + "node_modules/async-retry": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", + "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", + "dev": true, + "dependencies": { + "retry": "0.12.0" + } + }, + "node_modules/async-retry/node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/asynckit": { "version": "0.4.0", "dev": true, @@ -18337,6 +18787,12 @@ "node": ">=0.4.0" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, "node_modules/buffer-fill": { "version": "1.0.0", "dev": true, @@ -19378,6 +19834,19 @@ "node": ">=0.10.0" } }, + "node_modules/complex.js": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz", + "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, "node_modules/component-emitter": { "version": "1.3.0", "license": "MIT" @@ -20542,6 +21011,92 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/danger": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/danger/-/danger-11.2.6.tgz", + "integrity": "sha512-EEeuDmUcxPGJ166q7Zzz1WEiV+e0qbPopaX4sXxds8U5doGMdw/8oOUOVye7JiHIBuss3KvQWt4YHZeD3jSCfw==", + "dev": true, + "dependencies": { + "@gitbeaker/node": "^21.3.0", + "@octokit/rest": "^18.12.0", + "async-retry": "1.2.3", + "chalk": "^2.3.0", + "commander": "^2.18.0", + "core-js": "^3.8.2", + "debug": "^4.1.1", + "fast-json-patch": "^3.0.0-1", + "get-stdin": "^6.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "hyperlinker": "^1.0.0", + "json5": "^2.1.0", + "jsonpointer": "^5.0.0", + "jsonwebtoken": "^9.0.0", + "lodash.find": "^4.6.0", + "lodash.includes": "^4.3.0", + "lodash.isobject": "^3.0.2", + "lodash.keys": "^4.0.8", + "lodash.mapvalues": "^4.6.0", + "lodash.memoize": "^4.1.2", + "memfs-or-file-map-to-github-branch": "^1.2.1", + "micromatch": "^4.0.4", + "node-cleanup": "^2.1.2", + "node-fetch": "^2.6.7", + "override-require": "^1.1.1", + "p-limit": "^2.1.0", + "parse-diff": "^0.7.0", + "parse-git-config": "^2.0.3", + "parse-github-url": "^1.0.2", + "parse-link-header": "^2.0.0", + "pinpoint": "^1.1.0", + "prettyjson": "^1.2.1", + "readline-sync": "^1.4.9", + "regenerator-runtime": "^0.13.9", + "require-from-string": "^2.0.2", + "supports-hyperlinks": "^1.0.1" + }, + "bin": { + "danger": "distribution/commands/danger.js", + "danger-ci": "distribution/commands/danger-ci.js", + "danger-init": "distribution/commands/danger-init.js", + "danger-js": "distribution/commands/danger.js", + "danger-local": "distribution/commands/danger-local.js", + "danger-pr": "distribution/commands/danger-pr.js", + "danger-process": "distribution/commands/danger-process.js", + "danger-reset-status": "distribution/commands/danger-reset-status.js", + "danger-runner": "distribution/commands/danger-runner.js" + }, + "engines": { + "node": ">=14.13.1" + } + }, + "node_modules/danger/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/danger/node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "dev": true + }, + "node_modules/danger/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/data-urls": { "version": "3.0.2", "dev": true, @@ -21254,6 +21809,15 @@ "stream-shift": "^1.0.0" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "license": "MIT" @@ -21920,6 +22484,12 @@ "version": "1.0.3", "license": "MIT" }, + "node_modules/escape-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==", + "dev": true + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "license": "MIT", @@ -23402,6 +23972,18 @@ "version": "2.0.0", "license": "MIT" }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/expect": { "version": "29.4.1", "license": "MIT", @@ -23520,8 +24102,8 @@ }, "node_modules/expensify-common": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#68abe48ad71a98604fdbf5e8e960023ed5807ec2", - "integrity": "sha512-OhM2d7W++k0RVscwBpl0cvKXp3aZmflVawQ9Ebh2RBTdy98VZUwq2iZyCDISGNyETthqqsRq8vxy2lFQZZ19RA==", + "resolved": "git+ssh://git@github.com/Expensify/expensify-common.git#c898563fe851d9a4d594fa9afbdd1ddab5971636", + "integrity": "sha512-WjxHYpqebNsPKJC+SBhgsYNSib+8LptZv/BKt8hc67psJjO9JdrTpAHuoZ0n1lCTQ2DhpDERjqTsQbpUqWbgIg==", "license": "MIT", "dependencies": { "classnames": "2.3.1", @@ -24512,6 +25094,19 @@ "node": ">= 0.6" } }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, "node_modules/fragment-cache": { "version": "0.2.1", "license": "MIT", @@ -24542,6 +25137,15 @@ "readable-stream": "^2.0.0" } }, + "node_modules/fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fs-extra": { "version": "9.1.0", "license": "MIT", @@ -24728,6 +25332,41 @@ "node": ">=6" } }, + "node_modules/git-config-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz", + "integrity": "sha512-KcJ2dlrrP5DbBnYIZ2nlikALfRhKzNSX0stvv3ImJ+fvC4hXKoV+U+74SV0upg+jlQZbrtQzc0bu6/Zh+7aQbg==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "fs-exists-sync": "^0.1.0", + "homedir-polyfill": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/git-config-path/node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/git-config-path/node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/github-slugger": { "version": "1.4.0", "dev": true, @@ -25296,6 +25935,18 @@ "react-is": "^16.7.0" } }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/hosted-git-info": { "version": "4.1.0", "dev": true, @@ -25566,6 +26217,299 @@ "node": ">=10.17.0" } }, + "node_modules/husky": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", + "integrity": "sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "cosmiconfig": "^5.0.7", + "execa": "^1.0.0", + "find-up": "^3.0.0", + "get-stdin": "^6.0.0", + "is-ci": "^2.0.0", + "pkg-dir": "^3.0.0", + "please-upgrade-node": "^3.1.1", + "read-pkg": "^4.0.1", + "run-node": "^1.0.0", + "slash": "^2.0.0" + }, + "bin": { + "husky-upgrade": "lib/upgrader/bin.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/husky/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/husky/node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/husky/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/husky/node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/husky/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/husky/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/husky/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "dev": true, + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/husky/node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/husky/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/husky/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/husky/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/husky/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/husky/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/husky/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/husky/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/husky/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/husky/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/husky/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/husky/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/husky/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/husky/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/husky/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/hyperlinker": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", + "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/hyphenate-style-name": { "version": "1.0.4", "license": "BSD-3-Clause" @@ -25786,6 +26730,12 @@ "version": "2.0.4", "license": "ISC" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "node_modules/inline-style-parser": { "version": "0.1.1", "dev": true, @@ -26748,6 +27698,12 @@ "node": ">=8" } }, + "node_modules/javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", + "dev": true + }, "node_modules/jest": { "version": "29.4.1", "license": "MIT", @@ -29883,6 +30839,31 @@ "version": "0.0.0", "license": "Public Domain" }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "dev": true, + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.3", "dev": true, @@ -29903,6 +30884,27 @@ "node": ">=8" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/keyv": { "version": "4.5.2", "dev": true, @@ -30027,6 +31029,12 @@ "node": ">= 0.8.0" } }, + "node_modules/li": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/li/-/li-1.3.0.tgz", + "integrity": "sha512-z34TU6GlMram52Tss5mt1m//ifRIpKH5Dqm7yUVOdHI+BQCs9qGPHFaCUTIzsWX7edN30aa2WrPwR7IO10FHaw==", + "dev": true + }, "node_modules/lie": { "version": "3.1.1", "license": "MIT", @@ -30138,10 +31146,46 @@ "version": "4.0.8", "license": "MIT" }, + "node_modules/lodash.find": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==", + "dev": true + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, "node_modules/lodash.isequal": { "version": "4.5.0", "license": "MIT" }, + "node_modules/lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", + "dev": true + }, + "node_modules/lodash.keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.2.0.tgz", + "integrity": "sha512-J79MkJcp7Df5mizHiVNpjoHXLi4HLjh9VLS/M7lQSGoQ+0oQ+lWEigREkqKyizPB1IawvQLLKY8mzEcm1tkyxQ==", + "dev": true + }, + "node_modules/lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "dev": true, @@ -30596,6 +31640,15 @@ "node": ">=0.10.0" } }, + "node_modules/markdown-builder": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/markdown-builder/-/markdown-builder-0.9.0.tgz", + "integrity": "sha512-UovCyEEzMeKE7l88fbOk9SIJkOG7KXkg+TdudN8rvOtCtBO5uu1X27HSnM7LS/xH+vaShJLGpkBcYYcojWNx/g==", + "dev": true, + "dependencies": { + "husky": "^1.0.0-rc.14" + } + }, "node_modules/markdown-escapes": { "version": "1.0.4", "dev": true, @@ -30605,6 +31658,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/markdown-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", + "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", + "dev": true, + "dependencies": { + "repeat-string": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/matcher": { "version": "3.0.0", "dev": true, @@ -30616,6 +31682,29 @@ "node": ">=10" } }, + "node_modules/mathjs": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-11.8.0.tgz", + "integrity": "sha512-I7r8HCoqUGyEiHQdeOCF2m2k9N+tcOHO3cZQ3tyJkMMBQMFqMR7dMQEboBMJAiFW2Um3PEItGPwcOc4P6KRqwg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0", + "complex.js": "^2.1.1", + "decimal.js": "^10.4.3", + "escape-latex": "^1.2.0", + "fraction.js": "^4.2.0", + "javascript-natural-sort": "^0.7.1", + "seedrandom": "^3.0.5", + "tiny-emitter": "^2.1.0", + "typed-function": "^4.1.0" + }, + "bin": { + "mathjs": "bin/cli.js" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/md5.js": { "version": "1.3.5", "license": "MIT", @@ -30728,6 +31817,15 @@ "node": ">= 4.0.0" } }, + "node_modules/memfs-or-file-map-to-github-branch": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/memfs-or-file-map-to-github-branch/-/memfs-or-file-map-to-github-branch-1.2.1.tgz", + "integrity": "sha512-I/hQzJ2a/pCGR8fkSQ9l5Yx+FQ4e7X6blNHyWBm2ojeFLT3GVzGkTj7xnyWpdclrr7Nq4dmx3xrvu70m3ypzAQ==", + "dev": true, + "dependencies": { + "@octokit/rest": "^16.43.0 || ^17.11.0 || ^18.12.0" + } + }, "node_modules/memoizerific": { "version": "1.11.3", "dev": true, @@ -32424,6 +33522,12 @@ "license": "MIT", "optional": true }, + "node_modules/node-cleanup": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", + "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", + "dev": true + }, "node_modules/node-dir": { "version": "0.1.17", "license": "MIT", @@ -33163,6 +34267,12 @@ "node": ">=0.10.0" } }, + "node_modules/override-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/override-require/-/override-require-1.1.1.tgz", + "integrity": "sha512-eoJ9YWxFcXbrn2U8FKT6RV+/Kj7fiGAB1VvHzbYKt8xM5ZuKZgCGvnHzDxmreEjcBH28ejg5MiOH4iyY1mQnkg==", + "dev": true + }, "node_modules/p-all": { "version": "2.1.0", "dev": true, @@ -33353,6 +34463,12 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/parse-diff": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.7.1.tgz", + "integrity": "sha512-1j3l8IKcy4yRK2W4o9EYvJLSzpAVwz4DXqCewYyx2vEwk2gcf3DBPqc8Fj4XV3K33OYJ08A8fWwyu/ykD/HUSg==", + "dev": true + }, "node_modules/parse-entities": { "version": "2.0.0", "dev": true, @@ -33370,6 +34486,32 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/parse-git-config": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-2.0.3.tgz", + "integrity": "sha512-Js7ueMZOVSZ3tP8C7E3KZiHv6QQl7lnJ+OkbxoaFazzSa2KyEHqApfGbU3XboUgUnq4ZuUmskUpYKTNx01fm5A==", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "git-config-path": "^1.0.1", + "ini": "^1.3.5" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true, + "bin": { + "parse-github-url": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/parse-json": { "version": "5.2.0", "license": "MIT", @@ -33386,6 +34528,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-link-header": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-link-header/-/parse-link-header-2.0.0.tgz", + "integrity": "sha512-xjU87V0VyHZybn2RrCX5TIFGxTVZE6zqqZWMPlIKiSKuWh/X5WZdt+w1Ki1nXB+8L/KtL+nZ4iq+sfI6MrhhMw==", + "dev": true, + "dependencies": { + "xtend": "~4.0.1" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/parse5": { "version": "6.0.1", "dev": true, @@ -33764,6 +34924,12 @@ "node": ">=0.10.0" } }, + "node_modules/pinpoint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pinpoint/-/pinpoint-1.1.0.tgz", + "integrity": "sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg==", + "dev": true + }, "node_modules/pirates": { "version": "4.0.5", "license": "MIT", @@ -33841,6 +35007,15 @@ "node": ">=6" } }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "dependencies": { + "semver-compare": "^1.0.0" + } + }, "node_modules/plist": { "version": "3.0.6", "license": "MIT", @@ -34137,6 +35312,28 @@ "node": ">= 0.8" } }, + "node_modules/prettyjson": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.5.tgz", + "integrity": "sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw==", + "dev": true, + "dependencies": { + "colors": "1.4.0", + "minimist": "^1.2.0" + }, + "bin": { + "prettyjson": "bin/prettyjson" + } + }, + "node_modules/prettyjson/node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/process": { "version": "0.11.10", "license": "MIT", @@ -36223,6 +37420,26 @@ "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" }, + "node_modules/readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/reassure": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/reassure/-/reassure-0.9.0.tgz", + "integrity": "sha512-FIf0GPchyPGItsrW5Wwff/NWVrfOcCUuJJSs4Nur6iRdQt8yvmCpcba4UyemdZ1KaFTIW1gKbAV3u2tuA7zmtQ==", + "dev": true, + "dependencies": { + "@callstack/reassure-cli": "0.9.0", + "@callstack/reassure-danger": "0.1.1", + "@callstack/reassure-measure": "0.5.0" + } + }, "node_modules/recast": { "version": "0.20.5", "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", @@ -36282,8 +37499,9 @@ } }, "node_modules/regenerator-runtime": { - "version": "0.13.9", - "license": "MIT" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "node_modules/regenerator-transform": { "version": "0.15.0", @@ -36822,6 +38040,18 @@ "node": ">=0.12.0" } }, + "node_modules/run-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", + "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", + "dev": true, + "bin": { + "run-node": "run-node" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "dev": true, @@ -37614,6 +38844,21 @@ "version": "3.0.7", "license": "ISC" }, + "node_modules/simple-git": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.19.0.tgz", + "integrity": "sha512-hyH2p9Ptxjf/xPuL7HfXbpYt9gKhC1yWDh3KYIAYJJePAKV7AEjLN4xhp7lozOdNiaJ9jlVvAbBymVlcS2jRiA==", + "dev": true, + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.3.4" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, "node_modules/simple-plist": { "version": "1.3.1", "license": "MIT", @@ -38707,6 +39952,28 @@ "node": ">=4" } }, + "node_modules/supports-hyperlinks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", + "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", + "dev": true, + "dependencies": { + "has-flag": "^2.0.0", + "supports-color": "^5.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "license": "MIT", @@ -39527,6 +40794,15 @@ "node": ">= 0.6" } }, + "node_modules/typed-function": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.0.tgz", + "integrity": "sha512-DGwUl6cioBW5gw2L+6SMupGwH/kZOqivy17E4nsh1JI9fKF87orMmlQx3KISQPmg3sfnOUGlwVkroosvgddrlg==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/typedarray": { "version": "0.0.6", "dev": true, @@ -41500,6 +42776,12 @@ "default-browser-id": "^1.0.4" } }, + "node_modules/xcase": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xcase/-/xcase-2.0.1.tgz", + "integrity": "sha512-UmFXIPU+9Eg3E9m/728Bii0lAIuoc+6nbrNUKaRPJOFp91ih44qqGlWtxMB6kXFrRD6po+86ksHM5XHCfk6iPw==", + "dev": true + }, "node_modules/xcode": { "version": "3.0.1", "license": "Apache-2.0", @@ -41739,6 +43021,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/zwitch": { "version": "1.0.5", "dev": true, @@ -42851,9 +44142,11 @@ } }, "@babel/runtime": { - "version": "7.18.9", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", + "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", "requires": { - "regenerator-runtime": "^0.13.4" + "regenerator-runtime": "^0.13.11" } }, "@babel/runtime-corejs3": { @@ -42920,6 +44213,196 @@ "integrity": "sha512-iZf+UWfL+DogJVpd/xMQyP6X6McYd6ArdYoPMiv/zlOTzeXXfQbYxBNJJBF6tThvsjLMbA8tLjkCdm9RWMFCCw==", "dev": true }, + "@callstack/reassure-cli": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@callstack/reassure-cli/-/reassure-cli-0.9.0.tgz", + "integrity": "sha512-auoxqyilxkT5mDdEPJqRRY+ZGlrihJjFQpopcFd/15ng76OPVka3L48RMEY2wXkFXLaOOs6enNGb596jYPuEtQ==", + "dev": true, + "requires": { + "@callstack/reassure-compare": "0.5.0", + "@callstack/reassure-logger": "0.3.0", + "chalk": "4.1.2", + "simple-git": "^3.16.0", + "yargs": "^17.6.2" + }, + "dependencies": { + "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, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + }, + "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, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } + } + }, + "@callstack/reassure-compare": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@callstack/reassure-compare/-/reassure-compare-0.5.0.tgz", + "integrity": "sha512-3sBeJ/+Hxjdb01KVb8LszO1kcJ8TXcrVnerUj+LYn2dkBOohAMqGYaOvCeoWsVEHJ+MIOzmvAGBJQRu69RoJdQ==", + "dev": true, + "requires": { + "@callstack/reassure-logger": "0.3.0", + "markdown-builder": "^0.9.0", + "markdown-table": "^2.0.0", + "zod": "^3.20.2" + } + }, + "@callstack/reassure-danger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@callstack/reassure-danger/-/reassure-danger-0.1.1.tgz", + "integrity": "sha512-lfza+qBdvVYtP7WvMTT+LfjBfuYsXZ4RxuBldsL8wJArGeCl3OZwUg+9bTo8v6kk/nY8memk5HxrCwWDSO24UA==", + "dev": true + }, + "@callstack/reassure-logger": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@callstack/reassure-logger/-/reassure-logger-0.3.0.tgz", + "integrity": "sha512-JX5o+8qkIbIRL+cQn9XlQYdv9p/3L6J70zZX6NYi9j0VrSS9PZIRfo8ujMdLSqUNV6HZN1ay59RzuncLjVu0aQ==", + "dev": true, + "requires": { + "chalk": "4.1.2" + }, + "dependencies": { + "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, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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, + "requires": { + "color-name": "~1.1.4" + } + }, + "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 + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "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==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@callstack/reassure-measure": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@callstack/reassure-measure/-/reassure-measure-0.5.0.tgz", + "integrity": "sha512-KwlmNYcspBOp7FIw6XOz5O9mnKB4cWCCyM6vG4nFUPHSWQ6yVdRkawVvoPIV5qJ2hw7zCzdtqRrLWQSTF4eKlg==", + "dev": true, + "requires": { + "@callstack/reassure-logger": "0.3.0", + "mathjs": "^11.5.0" + } + }, "@cnakazawa/watch": { "version": "1.0.4", "dev": true, @@ -43248,6 +44731,56 @@ "version": "1.1.3", "dev": true }, + "@gitbeaker/core": { + "version": "21.7.0", + "resolved": "https://registry.npmjs.org/@gitbeaker/core/-/core-21.7.0.tgz", + "integrity": "sha512-cw72rE7tA27wc6JJe1WqeAj9v/6w0S7XJcEji+bRNjTlUfE1zgfW0Gf1mbGUi7F37SOABGCosQLfg9Qe63aIqA==", + "dev": true, + "requires": { + "@gitbeaker/requester-utils": "^21.7.0", + "form-data": "^3.0.0", + "li": "^1.3.0", + "xcase": "^2.0.1" + } + }, + "@gitbeaker/node": { + "version": "21.7.0", + "resolved": "https://registry.npmjs.org/@gitbeaker/node/-/node-21.7.0.tgz", + "integrity": "sha512-OdM3VcTKYYqboOsnbiPcO0XimXXpYK4gTjARBZ6BWc+1LQXKmqo+OH6oUbyxOoaFu9hHECafIt3WZU3NM4sZTg==", + "dev": true, + "requires": { + "@gitbeaker/core": "^21.7.0", + "@gitbeaker/requester-utils": "^21.7.0", + "form-data": "^3.0.0", + "got": "^11.1.4", + "xcase": "^2.0.1" + } + }, + "@gitbeaker/requester-utils": { + "version": "21.7.0", + "resolved": "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-21.7.0.tgz", + "integrity": "sha512-eLTaVXlBnh8Qimj6QuMMA06mu/mLcJm3dy8nqhhn/Vm/D25sPrvpGwmbfFyvzj6QujPqtHvFfsCHtyZddL01qA==", + "dev": true, + "requires": { + "form-data": "^3.0.0", + "query-string": "^6.12.1", + "xcase": "^2.0.1" + }, + "dependencies": { + "query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + } + } + }, "@gorhom/portal": { "version": "1.0.14", "requires": { @@ -44339,6 +45872,21 @@ "version": "2.3.1", "requires": {} }, + "@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "dev": true, + "requires": { + "debug": "^4.1.1" + } + }, + "@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "dev": true + }, "@leichtgewicht/ip-codec": { "version": "2.0.4", "dev": true @@ -44590,6 +46138,13 @@ "@octokit/types": "^6.41.0" } }, + "@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "requires": {} + }, "@octokit/plugin-rest-endpoint-methods": { "version": "5.16.2", "dev": true, @@ -44653,6 +46208,100 @@ } } }, + "@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "dev": true, + "requires": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + }, + "dependencies": { + "@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dev": true, + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dev": true, + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "dev": true, + "requires": { + "@octokit/types": "^6.40.0" + } + }, + "@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dev": true, + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dev": true, + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + } + } + }, "@octokit/types": { "version": "6.41.0", "dev": true, @@ -52105,9 +53754,9 @@ } }, "@ua/react-native-airship": { - "version": "15.2.3", - "resolved": "https://registry.npmjs.org/@ua/react-native-airship/-/react-native-airship-15.2.3.tgz", - "integrity": "sha512-94fgHJcxc4qUy9OmBqt6VuuWggoeCMNIosz3/qwiUNsUVoE1deWcOEG9vULmXcTKX+O9Wal/mKsuPGiFCALTDQ==", + "version": "15.2.6", + "resolved": "https://registry.npmjs.org/@ua/react-native-airship/-/react-native-airship-15.2.6.tgz", + "integrity": "sha512-dVlBPPYXD/4SEshv/X7mmt3xF8WfnNqiSNzCyqJSLAZ1aJuPpP9Z5WemCYsa2iv6goRZvtJSE4P79QKlfoTwXw==", "requires": {} }, "@vercel/ncc": { @@ -52899,6 +54548,23 @@ "async-limiter": { "version": "1.0.1" }, + "async-retry": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", + "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", + "dev": true, + "requires": { + "retry": "0.12.0" + }, + "dependencies": { + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true + } + } + }, "asynckit": { "version": "0.4.0", "dev": true @@ -53991,6 +55657,12 @@ "version": "1.0.0", "dev": true }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true + }, "buffer-fill": { "version": "1.0.0", "dev": true @@ -54662,6 +56334,12 @@ "version": "0.1.2", "dev": true }, + "complex.js": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz", + "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==", + "dev": true + }, "component-emitter": { "version": "1.3.0" }, @@ -55443,6 +57121,74 @@ "version": "1.0.8", "dev": true }, + "danger": { + "version": "11.2.6", + "resolved": "https://registry.npmjs.org/danger/-/danger-11.2.6.tgz", + "integrity": "sha512-EEeuDmUcxPGJ166q7Zzz1WEiV+e0qbPopaX4sXxds8U5doGMdw/8oOUOVye7JiHIBuss3KvQWt4YHZeD3jSCfw==", + "dev": true, + "requires": { + "@gitbeaker/node": "^21.3.0", + "@octokit/rest": "^18.12.0", + "async-retry": "1.2.3", + "chalk": "^2.3.0", + "commander": "^2.18.0", + "core-js": "^3.8.2", + "debug": "^4.1.1", + "fast-json-patch": "^3.0.0-1", + "get-stdin": "^6.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "hyperlinker": "^1.0.0", + "json5": "^2.1.0", + "jsonpointer": "^5.0.0", + "jsonwebtoken": "^9.0.0", + "lodash.find": "^4.6.0", + "lodash.includes": "^4.3.0", + "lodash.isobject": "^3.0.2", + "lodash.keys": "^4.0.8", + "lodash.mapvalues": "^4.6.0", + "lodash.memoize": "^4.1.2", + "memfs-or-file-map-to-github-branch": "^1.2.1", + "micromatch": "^4.0.4", + "node-cleanup": "^2.1.2", + "node-fetch": "^2.6.7", + "override-require": "^1.1.1", + "p-limit": "^2.1.0", + "parse-diff": "^0.7.0", + "parse-git-config": "^2.0.3", + "parse-github-url": "^1.0.2", + "parse-link-header": "^2.0.0", + "pinpoint": "^1.1.0", + "prettyjson": "^1.2.1", + "readline-sync": "^1.4.9", + "regenerator-runtime": "^0.13.9", + "require-from-string": "^2.0.2", + "supports-hyperlinks": "^1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, "data-urls": { "version": "3.0.2", "dev": true, @@ -55917,6 +57663,15 @@ "stream-shift": "^1.0.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1" }, @@ -56367,6 +58122,12 @@ "escape-html": { "version": "1.0.3" }, + "escape-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==", + "dev": true + }, "escape-string-regexp": { "version": "4.0.0" }, @@ -57326,6 +59087,15 @@ } } }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "expect": { "version": "29.4.1", "requires": { @@ -57401,9 +59171,9 @@ } }, "expensify-common": { - "version": "git+ssh://git@github.com/Expensify/expensify-common.git#68abe48ad71a98604fdbf5e8e960023ed5807ec2", - "integrity": "sha512-OhM2d7W++k0RVscwBpl0cvKXp3aZmflVawQ9Ebh2RBTdy98VZUwq2iZyCDISGNyETthqqsRq8vxy2lFQZZ19RA==", - "from": "expensify-common@git+ssh://git@github.com/Expensify/expensify-common.git#68abe48ad71a98604fdbf5e8e960023ed5807ec2", + "version": "git+ssh://git@github.com/Expensify/expensify-common.git#c898563fe851d9a4d594fa9afbdd1ddab5971636", + "integrity": "sha512-WjxHYpqebNsPKJC+SBhgsYNSib+8LptZv/BKt8hc67psJjO9JdrTpAHuoZ0n1lCTQ2DhpDERjqTsQbpUqWbgIg==", + "from": "expensify-common@git+ssh://git@github.com/Expensify/expensify-common.git#c898563fe851d9a4d594fa9afbdd1ddab5971636", "requires": { "classnames": "2.3.1", "clipboard": "2.0.4", @@ -58066,6 +59836,12 @@ "version": "0.2.0", "dev": true }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true + }, "fragment-cache": { "version": "0.2.1", "requires": { @@ -58086,6 +59862,12 @@ "readable-stream": "^2.0.0" } }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", + "dev": true + }, "fs-extra": { "version": "9.1.0", "requires": { @@ -58196,6 +59978,34 @@ "getenv": { "version": "1.0.0" }, + "git-config-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz", + "integrity": "sha512-KcJ2dlrrP5DbBnYIZ2nlikALfRhKzNSX0stvv3ImJ+fvC4hXKoV+U+74SV0upg+jlQZbrtQzc0bu6/Zh+7aQbg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "fs-exists-sync": "^0.1.0", + "homedir-polyfill": "^1.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true + } + } + }, "github-slugger": { "version": "1.4.0", "dev": true @@ -58569,6 +60379,15 @@ "react-is": "^16.7.0" } }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, "hosted-git-info": { "version": "4.1.0", "dev": true, @@ -58736,6 +60555,225 @@ "human-signals": { "version": "2.1.0" }, + "husky": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-1.3.1.tgz", + "integrity": "sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.7", + "execa": "^1.0.0", + "find-up": "^3.0.0", + "get-stdin": "^6.0.0", + "is-ci": "^2.0.0", + "pkg-dir": "^3.0.0", + "please-upgrade-node": "^3.1.1", + "read-pkg": "^4.0.1", + "run-node": "^1.0.0", + "slash": "^2.0.0" + }, + "dependencies": { + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + } + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "hyperlinker": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", + "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==", + "dev": true + }, "hyphenate-style-name": { "version": "1.0.4" }, @@ -58857,6 +60895,12 @@ "inherits": { "version": "2.0.4" }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, "inline-style-parser": { "version": "0.1.1", "dev": true @@ -59401,6 +61445,12 @@ } } }, + "javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", + "dev": true + }, "jest": { "version": "29.4.1", "requires": { @@ -61480,6 +63530,24 @@ "jsonify": { "version": "0.0.0" }, + "jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true + }, + "jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "dev": true, + "requires": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + } + }, "jsx-ast-utils": { "version": "3.3.3", "dev": true, @@ -61492,6 +63560,27 @@ "version": "3.1.0", "dev": true }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dev": true, + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "keyv": { "version": "4.5.2", "dev": true, @@ -61575,6 +63664,12 @@ "type-check": "~0.4.0" } }, + "li": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/li/-/li-1.3.0.tgz", + "integrity": "sha512-z34TU6GlMram52Tss5mt1m//ifRIpKH5Dqm7yUVOdHI+BQCs9qGPHFaCUTIzsWX7edN30aa2WrPwR7IO10FHaw==", + "dev": true + }, "lie": { "version": "3.1.1", "requires": { @@ -61651,9 +63746,45 @@ "lodash.debounce": { "version": "4.0.8" }, + "lodash.find": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==", + "dev": true + }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true + }, "lodash.isequal": { "version": "4.5.0" }, + "lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", + "dev": true + }, + "lodash.keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.2.0.tgz", + "integrity": "sha512-J79MkJcp7Df5mizHiVNpjoHXLi4HLjh9VLS/M7lQSGoQ+0oQ+lWEigREkqKyizPB1IawvQLLKY8mzEcm1tkyxQ==", + "dev": true + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, "lodash.merge": { "version": "4.6.2", "dev": true @@ -61973,10 +64104,28 @@ "object-visit": "^1.0.0" } }, + "markdown-builder": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/markdown-builder/-/markdown-builder-0.9.0.tgz", + "integrity": "sha512-UovCyEEzMeKE7l88fbOk9SIJkOG7KXkg+TdudN8rvOtCtBO5uu1X27HSnM7LS/xH+vaShJLGpkBcYYcojWNx/g==", + "dev": true, + "requires": { + "husky": "^1.0.0-rc.14" + } + }, "markdown-escapes": { "version": "1.0.4", "dev": true }, + "markdown-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", + "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", + "dev": true, + "requires": { + "repeat-string": "^1.0.0" + } + }, "matcher": { "version": "3.0.0", "dev": true, @@ -61984,6 +64133,23 @@ "escape-string-regexp": "^4.0.0" } }, + "mathjs": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-11.8.0.tgz", + "integrity": "sha512-I7r8HCoqUGyEiHQdeOCF2m2k9N+tcOHO3cZQ3tyJkMMBQMFqMR7dMQEboBMJAiFW2Um3PEItGPwcOc4P6KRqwg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.21.0", + "complex.js": "^2.1.1", + "decimal.js": "^10.4.3", + "escape-latex": "^1.2.0", + "fraction.js": "^4.2.0", + "javascript-natural-sort": "^0.7.1", + "seedrandom": "^3.0.5", + "tiny-emitter": "^2.1.0", + "typed-function": "^4.1.0" + } + }, "md5.js": { "version": "1.3.5", "requires": { @@ -62056,6 +64222,15 @@ "fs-monkey": "^1.0.3" } }, + "memfs-or-file-map-to-github-branch": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/memfs-or-file-map-to-github-branch/-/memfs-or-file-map-to-github-branch-1.2.1.tgz", + "integrity": "sha512-I/hQzJ2a/pCGR8fkSQ9l5Yx+FQ4e7X6blNHyWBm2ojeFLT3GVzGkTj7xnyWpdclrr7Nq4dmx3xrvu70m3ypzAQ==", + "dev": true, + "requires": { + "@octokit/rest": "^16.43.0 || ^17.11.0 || ^18.12.0" + } + }, "memoizerific": { "version": "1.11.3", "dev": true, @@ -63246,6 +65421,12 @@ "dev": true, "optional": true }, + "node-cleanup": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", + "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", + "dev": true + }, "node-dir": { "version": "0.1.17", "requires": { @@ -63739,6 +65920,12 @@ "os-tmpdir": { "version": "1.0.2" }, + "override-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/override-require/-/override-require-1.1.1.tgz", + "integrity": "sha512-eoJ9YWxFcXbrn2U8FKT6RV+/Kj7fiGAB1VvHzbYKt8xM5ZuKZgCGvnHzDxmreEjcBH28ejg5MiOH4iyY1mQnkg==", + "dev": true + }, "p-all": { "version": "2.1.0", "dev": true, @@ -63857,6 +66044,12 @@ "safe-buffer": "^5.1.1" } }, + "parse-diff": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.7.1.tgz", + "integrity": "sha512-1j3l8IKcy4yRK2W4o9EYvJLSzpAVwz4DXqCewYyx2vEwk2gcf3DBPqc8Fj4XV3K33OYJ08A8fWwyu/ykD/HUSg==", + "dev": true + }, "parse-entities": { "version": "2.0.0", "dev": true, @@ -63869,6 +66062,23 @@ "is-hexadecimal": "^1.0.0" } }, + "parse-git-config": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-2.0.3.tgz", + "integrity": "sha512-Js7ueMZOVSZ3tP8C7E3KZiHv6QQl7lnJ+OkbxoaFazzSa2KyEHqApfGbU3XboUgUnq4ZuUmskUpYKTNx01fm5A==", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "git-config-path": "^1.0.1", + "ini": "^1.3.5" + } + }, + "parse-github-url": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", + "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", + "dev": true + }, "parse-json": { "version": "5.2.0", "requires": { @@ -63878,6 +66088,21 @@ "lines-and-columns": "^1.1.6" } }, + "parse-link-header": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-link-header/-/parse-link-header-2.0.0.tgz", + "integrity": "sha512-xjU87V0VyHZybn2RrCX5TIFGxTVZE6zqqZWMPlIKiSKuWh/X5WZdt+w1Ki1nXB+8L/KtL+nZ4iq+sfI6MrhhMw==", + "dev": true, + "requires": { + "xtend": "~4.0.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true + }, "parse5": { "version": "6.0.1", "dev": true @@ -64125,6 +66350,12 @@ "pinkie": "^2.0.0" } }, + "pinpoint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pinpoint/-/pinpoint-1.1.0.tgz", + "integrity": "sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg==", + "dev": true + }, "pirates": { "version": "4.0.5" }, @@ -64173,6 +66404,15 @@ } } }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, "plist": { "version": "3.0.6", "requires": { @@ -64364,6 +66604,24 @@ "version": "1.0.3", "dev": true }, + "prettyjson": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.5.tgz", + "integrity": "sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw==", + "dev": true, + "requires": { + "colors": "1.4.0", + "minimist": "^1.2.0" + }, + "dependencies": { + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true + } + } + }, "process": { "version": "0.11.10" }, @@ -65752,6 +68010,23 @@ "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==" }, + "readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "dev": true + }, + "reassure": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/reassure/-/reassure-0.9.0.tgz", + "integrity": "sha512-FIf0GPchyPGItsrW5Wwff/NWVrfOcCUuJJSs4Nur6iRdQt8yvmCpcba4UyemdZ1KaFTIW1gKbAV3u2tuA7zmtQ==", + "dev": true, + "requires": { + "@callstack/reassure-cli": "0.9.0", + "@callstack/reassure-danger": "0.1.1", + "@callstack/reassure-measure": "0.5.0" + } + }, "recast": { "version": "0.20.5", "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", @@ -65794,7 +68069,9 @@ } }, "regenerator-runtime": { - "version": "0.13.9" + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, "regenerator-transform": { "version": "0.15.0", @@ -66142,6 +68419,12 @@ "version": "2.4.1", "dev": true }, + "run-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", + "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", + "dev": true + }, "run-parallel": { "version": "1.2.0", "dev": true, @@ -66697,6 +68980,17 @@ "signal-exit": { "version": "3.0.7" }, + "simple-git": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.19.0.tgz", + "integrity": "sha512-hyH2p9Ptxjf/xPuL7HfXbpYt9gKhC1yWDh3KYIAYJJePAKV7AEjLN4xhp7lozOdNiaJ9jlVvAbBymVlcS2jRiA==", + "dev": true, + "requires": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.3.4" + } + }, "simple-plist": { "version": "1.3.1", "requires": { @@ -67447,6 +69741,24 @@ "has-flag": "^3.0.0" } }, + "supports-hyperlinks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", + "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", + "dev": true, + "requires": { + "has-flag": "^2.0.0", + "supports-color": "^5.0.0" + }, + "dependencies": { + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", + "dev": true + } + } + }, "supports-preserve-symlinks-flag": { "version": "1.0.0" }, @@ -67974,6 +70286,12 @@ "mime-types": "~2.1.24" } }, + "typed-function": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.0.tgz", + "integrity": "sha512-DGwUl6cioBW5gw2L+6SMupGwH/kZOqivy17E4nsh1JI9fKF87orMmlQx3KISQPmg3sfnOUGlwVkroosvgddrlg==", + "dev": true + }, "typedarray": { "version": "0.0.6", "dev": true @@ -69236,6 +71554,12 @@ "default-browser-id": "^1.0.4" } }, + "xcase": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xcase/-/xcase-2.0.1.tgz", + "integrity": "sha512-UmFXIPU+9Eg3E9m/728Bii0lAIuoc+6nbrNUKaRPJOFp91ih44qqGlWtxMB6kXFrRD6po+86ksHM5XHCfk6iPw==", + "dev": true + }, "xcode": { "version": "3.0.1", "requires": { @@ -69389,6 +71713,12 @@ "yocto-queue": { "version": "0.1.0" }, + "zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "dev": true + }, "zwitch": { "version": "1.0.5", "dev": true diff --git a/package.json b/package.json index a8b1e5b9e22f..8cea35e7b955 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.3.20-2", + "version": "1.3.22-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.", @@ -70,13 +70,13 @@ "@react-navigation/native": "6.0.13", "@react-navigation/stack": "6.3.1", "@react-ng/bounds-observer": "^0.2.1", - "@ua/react-native-airship": "^15.2.3", + "@ua/react-native-airship": "^15.2.6", "awesome-phonenumber": "^5.4.0", "babel-plugin-transform-remove-console": "^6.9.4", "babel-polyfill": "^6.26.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#68abe48ad71a98604fdbf5e8e960023ed5807ec2", + "expensify-common": "git+ssh://git@github.com/Expensify/expensify-common.git#c898563fe851d9a4d594fa9afbdd1ddab5971636", "fbjs": "^3.0.2", "html-entities": "^1.3.1", "htmlparser2": "^7.2.0", @@ -177,6 +177,7 @@ "concurrently": "^5.3.0", "copy-webpack-plugin": "^6.4.1", "css-loader": "^6.7.2", + "danger": "^11.2.6", "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", "electron": "22.3.7", @@ -206,6 +207,7 @@ "react-native-performance-flipper-reporter": "^2.0.0", "react-native-svg-transformer": "^1.0.0", "react-test-renderer": "18.1.0", + "reassure": "^0.9.0", "setimmediate": "^1.0.5", "shellcheck": "^1.1.0", "style-loader": "^2.0.0", diff --git a/src/CONST.js b/src/CONST.js index 182548b4d99e..4557c66a42cc 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -799,6 +799,8 @@ const CONST = { }, ATTACHMENT_MESSAGE_TEXT: '[Attachment]', + // This is a placeholder for attachment which is uploading + ATTACHMENT_UPLOADING_MESSAGE_HTML: 'Uploading attachment...', ATTACHMENT_SOURCE_ATTRIBUTE: 'data-expensify-source', ATTACHMENT_PREVIEW_ATTRIBUTE: 'src', ATTACHMENT_ORIGINAL_FILENAME_ATTRIBUTE: 'data-name', @@ -2432,8 +2434,14 @@ const CONST = { MODERATION: { MODERATOR_DECISION_PENDING: 'pending', MODERATOR_DECISION_PENDING_HIDE: 'pendingHide', + MODERATOR_DECISION_APPROVED: 'approved', + MODERATOR_DECISION_HIDDEN: 'hidden', FLAG_SEVERITY_SPAM: 'spam', FLAG_SEVERITY_INCONSIDERATE: 'inconsiderate', + FLAG_SEVERITY_INTIMIDATION: 'intimidation', + FLAG_SEVERITY_BULLYING: 'bullying', + FLAG_SEVERITY_HARASSMENT: 'harassment', + FLAG_SEVERITY_ASSAULT: 'assault', }, }; diff --git a/src/Expensify.js b/src/Expensify.js index ff61485bc8f2..e7c830ff2029 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -92,9 +92,15 @@ function Expensify(props) { const [isNavigationReady, setIsNavigationReady] = useState(false); const [isOnyxMigrated, setIsOnyxMigrated] = useState(false); const [isSplashHidden, setIsSplashHidden] = useState(false); + const [hasAttemptedToOpenPublicRoom, setAttemptedToOpenPublicRoom] = useState(false); + + useEffect(() => { + if (props.isCheckingPublicRoom) return; + setAttemptedToOpenPublicRoom(true); + }, [props.isCheckingPublicRoom]); const isAuthenticated = useMemo(() => Boolean(lodashGet(props.session, 'authToken', null)), [props.session]); - const shouldInit = isNavigationReady && (!isAuthenticated || props.isSidebarLoaded) && !props.isCheckingPublicRoom; + const shouldInit = isNavigationReady && (!isAuthenticated || props.isSidebarLoaded) && hasAttemptedToOpenPublicRoom; const shouldHideSplash = shouldInit && !isSplashHidden; const initializeClient = () => { @@ -197,7 +203,7 @@ function Expensify(props) { )} - {!props.isCheckingPublicRoom && ( + {hasAttemptedToOpenPublicRoom && ( `flag/${reportID}/${reportActionID}`, SEARCH: 'search', SET_PASSWORD_WITH_VALIDATE_CODE: 'setpassword/:accountID/:validateCode', DETAILS: 'details', diff --git a/src/components/AttachmentCarousel/index.js b/src/components/AttachmentCarousel/index.js index 56f592bc5865..6ae3214cd32a 100644 --- a/src/components/AttachmentCarousel/index.js +++ b/src/components/AttachmentCarousel/index.js @@ -3,6 +3,7 @@ import {View, FlatList, PixelRatio} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; +import {Parser as HtmlParser} from 'htmlparser2'; import * as Expensicons from '../Icon/Expensicons'; import styles from '../../styles/styles'; import themeColors from '../../styles/themes/default'; @@ -10,7 +11,6 @@ import CarouselActions from './CarouselActions'; import Button from '../Button'; import * as ReportActionsUtils from '../../libs/ReportActionsUtils'; import AttachmentView from '../AttachmentView'; -import addEncryptedAuthTokenToURL from '../../libs/addEncryptedAuthTokenToURL'; import * as DeviceCapabilities from '../../libs/DeviceCapabilities'; import CONST from '../../CONST'; import ONYXKEYS from '../../ONYXKEYS'; @@ -62,28 +62,13 @@ class AttachmentCarousel extends React.Component { this.updateZoomState = this.updateZoomState.bind(this); this.toggleArrowsVisibility = this.toggleArrowsVisibility.bind(this); - this.state = this.makeInitialState(); + this.state = this.createInitialState(); } componentDidMount() { this.autoHideArrow(); } - /** - * Helps to navigate between next/previous attachments - * @param {Object} attachmentItem - * @returns {Object} - */ - getAttachment(attachmentItem) { - const source = _.get(attachmentItem, 'source', ''); - const file = _.get(attachmentItem, 'file', {name: ''}); - - return { - source, - file, - }; - } - /** * Calculate items layout information to optimize scrolling performance * @param {*} data @@ -159,39 +144,39 @@ class AttachmentCarousel extends React.Component { } /** - * Map report actions to attachment items and sets the initial carousel state + * Constructs the initial component state from report actions * @returns {{page: Number, attachments: Array, shouldShowArrow: Boolean, containerWidth: Number, isZoomed: Boolean}} */ - makeInitialState() { - let page = 0; - const actions = ReportActionsUtils.getSortedReportActions(_.values(this.props.reportActions), true); - - /** - * Looping to filter out attachments and retrieve the src URL and name of attachments. - */ + createInitialState() { + const actions = ReportActionsUtils.getSortedReportActions(_.values(this.props.reportActions)); const attachments = []; - _.forEach(actions, ({originalMessage, message}) => { - // Check for attachment which hasn't been deleted - if (!originalMessage || !originalMessage.html || _.some(message, (m) => m.isEdited)) { - return; - } - const matches = [...originalMessage.html.matchAll(CONST.REGEX.ATTACHMENT_DATA)]; - - // matchAll captured both source url and name of the attachment - if (matches.length === 2) { - const [originalSource, name] = _.map(matches, (m) => m[2]); - - // Update the image URL so the images can be accessed depending on the config environment. - // Eg: while using Ngrok the image path is from an Ngrok URL and not an Expensify URL. - const source = tryResolveUrlFromApiRoot(originalSource); - if (source === this.props.source) { - page = attachments.length; + + const htmlParser = new HtmlParser({ + onopentag: (name, attribs) => { + if (name !== 'img' || !attribs.src) { + return; } - attachments.push({source, file: {name}}); - } + const expensifySource = attribs[CONST.ATTACHMENT_SOURCE_ATTRIBUTE]; + + // By iterating actions in chronological order and prepending each attachment + // we ensure correct order of attachments even across actions with multiple attachments. + attachments.unshift({ + source: tryResolveUrlFromApiRoot(expensifySource || attribs.src), + isAuthTokenRequired: Boolean(expensifySource), + file: {name: attribs[CONST.ATTACHMENT_ORIGINAL_FILENAME_ATTRIBUTE] || attribs.src.split('/').pop()}, + }); + }, }); + _.forEach(actions, (action) => htmlParser.write(_.get(action, ['message', 0, 'html']))); + htmlParser.end(); + + const page = _.findIndex(attachments, (a) => a.source === this.props.source); + if (page === -1) { + throw new Error('Attachment not found'); + } + return { page, attachments, @@ -220,7 +205,7 @@ class AttachmentCarousel extends React.Component { /** * Updates the page state when the user navigates between attachments - * @param {Array<{item: *, index: Number}>} viewableItems + * @param {Array<{item: {source, file}, index: Number}>} viewableItems */ updatePage({viewableItems}) { // Since we can have only one item in view at a time, we can use the first item in the array @@ -231,8 +216,7 @@ class AttachmentCarousel extends React.Component { } const page = entry.index; - const {source, file} = this.getAttachment(entry.item); - this.props.onNavigate({source: addEncryptedAuthTokenToURL(source), file}); + this.props.onNavigate(entry.item); this.setState({page, isZoomed: false}); } @@ -258,26 +242,17 @@ class AttachmentCarousel extends React.Component { /** * Defines how a single attachment should be rendered - * @param {{ source: String, file: { name: String } }} item + * @param {{ isAuthTokenRequired: Boolean, source: String, file: { name: String } }} item * @returns {JSX.Element} */ renderItem({item}) { - const authSource = addEncryptedAuthTokenToURL(item.source); - if (!this.canUseTouchScreen) { - return ( - - ); - } - return ( ); } diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js index 642004913303..24a6ecfb3152 100755 --- a/src/components/AttachmentModal.js +++ b/src/components/AttachmentModal.js @@ -22,6 +22,7 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize'; import ConfirmModal from './ConfirmModal'; import HeaderGap from './HeaderGap'; import SafeAreaConsumer from './SafeAreaConsumer'; +import addEncryptedAuthTokenToURL from '../libs/addEncryptedAuthTokenToURL'; /** * Modal render prop component that exposes modal launching triggers that can be used @@ -84,6 +85,7 @@ class AttachmentModal extends PureComponent { isModalOpen: false, shouldLoadAttachment: false, isAttachmentInvalid: false, + isAuthTokenRequired: props.isAuthTokenRequired, attachmentInvalidReasonTitle: null, attachmentInvalidReason: null, source: props.source, @@ -100,17 +102,17 @@ class AttachmentModal extends PureComponent { this.submitAndClose = this.submitAndClose.bind(this); this.closeConfirmModal = this.closeConfirmModal.bind(this); this.onNavigate = this.onNavigate.bind(this); + this.downloadAttachment = this.downloadAttachment.bind(this); this.validateAndDisplayFileToUpload = this.validateAndDisplayFileToUpload.bind(this); this.updateConfirmButtonVisibility = this.updateConfirmButtonVisibility.bind(this); } /** - * Helps to navigate between next/previous attachments - * by setting sourceURL and file in state - * @param {Object} attachmentData + * Keeps the attachment source in sync with the attachment displayed currently in the carousel. + * @param {{ source: String, isAuthTokenRequired: Boolean, file: { name: string } }} attachment */ - onNavigate(attachmentData) { - this.setState(attachmentData); + onNavigate(attachment) { + this.setState(attachment); } /** @@ -126,11 +128,15 @@ class AttachmentModal extends PureComponent { } /** - * @param {String} sourceURL + * Download the currently viewed attachment. */ - downloadAttachment(sourceURL) { - const originalFileName = lodashGet(this.state, 'file.name') || this.props.originalFileName; - fileDownload(sourceURL, originalFileName); + downloadAttachment() { + let sourceURL = this.state.source; + if (this.state.isAuthTokenRequired) { + sourceURL = addEncryptedAuthTokenToURL(sourceURL); + } + + fileDownload(sourceURL, this.state.file.name); // At ios, if the keyboard is open while opening the attachment, then after downloading // the attachment keyboard will show up. So, to fix it we need to dismiss the keyboard. @@ -274,7 +280,7 @@ class AttachmentModal extends PureComponent { title={this.props.headerTitle || this.props.translate('common.attachment')} shouldShowBorderBottom shouldShowDownloadButton={this.props.allowDownload} - onDownloadButtonPress={() => this.downloadAttachment(this.state.source)} + onDownloadButtonPress={this.downloadAttachment} onCloseButtonPress={() => this.setState({isModalOpen: false})} /> @@ -291,7 +297,7 @@ class AttachmentModal extends PureComponent { diff --git a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js index 6a3e766175a4..b5758680619a 100644 --- a/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js +++ b/src/components/AutoCompleteSuggestions/BaseAutoCompleteSuggestions.js @@ -44,6 +44,7 @@ const BaseAutoCompleteSuggestions = (props) => { ); const rowHeight = measureHeightOfSuggestionRows(props.suggestions.length, props.isSuggestionPickerLarge); + const innerHeight = CONST.AUTO_COMPLETE_SUGGESTER.ITEM_HEIGHT * props.suggestions.length; return ( { renderItem={renderSuggestionMenuItem} keyExtractor={props.keyExtractor} removeClippedSubviews={false} - style={{height: rowHeight}} + showsVerticalScrollIndicator={innerHeight > rowHeight} + style={{flex: 1}} /> ); diff --git a/src/components/CheckboxWithLabel.js b/src/components/CheckboxWithLabel.js index 298f1252d48a..a11af52f6887 100644 --- a/src/components/CheckboxWithLabel.js +++ b/src/components/CheckboxWithLabel.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, {useState, useEffect} from 'react'; import PropTypes from 'prop-types'; import {View} from 'react-native'; import _ from 'underscore'; @@ -9,6 +9,11 @@ import FormHelpMessage from './FormHelpMessage'; import variables from '../styles/variables'; import PressableWithFeedback from './Pressable/PressableWithFeedback'; +/** + * Returns an error if the required props are not provided + * @param {Object} props + * @returns {Error|null} + */ const requiredPropsCheck = (props) => { if (!props.label && !props.LabelComponent) { return new Error('One of "label" or "LabelComponent" must be provided'); @@ -73,55 +78,55 @@ const defaultProps = { forwardedRef: () => {}, }; -class CheckboxWithLabel extends React.Component { - constructor(props) { - super(props); - - // We need to pick the first value that is strictly a boolean - // https://github.com/Expensify/App/issues/16885#issuecomment-1520846065 - this.isChecked = _.find([props.value, props.defaultValue, props.isChecked], (value) => _.isBoolean(value)); - - this.LabelComponent = props.LabelComponent; - - this.toggleCheckbox = this.toggleCheckbox.bind(this); - } - - toggleCheckbox() { - this.props.onInputChange(!this.isChecked); - this.isChecked = !this.isChecked; - } - - render() { - return ( - - - - - {this.props.label && {this.props.label}} - {this.LabelComponent && } - - - +const CheckboxWithLabel = (props) => { + // We need to pick the first value that is strictly a boolean + // https://github.com/Expensify/App/issues/16885#issuecomment-1520846065 + const [isChecked, setIsChecked] = useState(_.find([props.value, props.defaultValue, props.isChecked], (value) => _.isBoolean(value))); + + const toggleCheckbox = () => { + const newState = !isChecked; + props.onInputChange(newState); + setIsChecked(newState); + }; + + useEffect(() => { + setIsChecked(props.isChecked); + }, [props.isChecked]); + + const LabelComponent = props.LabelComponent; + + return ( + + + + + {props.label && {props.label}} + {LabelComponent && } + - ); - } -} + + + ); +}; CheckboxWithLabel.propTypes = propTypes; CheckboxWithLabel.defaultProps = defaultProps; +CheckboxWithLabel.displayName = 'CheckboxWithLabel'; export default React.forwardRef((props, ref) => ( { + setIsSkinToneListVisible((prev) => !prev); + }, []); /** * Pass the skinTone to props and hide the picker * @param {object} skinToneEmoji */ - updateSelectedSkinTone(skinToneEmoji) { - this.setState((prev) => ({isSkinToneListVisible: !prev.isSkinToneListVisible, highlightedIndex: skinToneEmoji.skinTone})); - this.props.updatePreferredSkinTone(skinToneEmoji.skinTone); + function updateSelectedSkinTone(skinToneEmoji) { + toggleIsSkinToneListVisible(); + setHighlightedIndex(skinToneEmoji.skinTone); + props.updatePreferredSkinTone(skinToneEmoji.skinTone); } - render() { - const selectedEmoji = getSkinToneEmojiFromIndex(this.props.preferredSkinTone); - return ( - - {!this.state.isSkinToneListVisible && ( - this.setState((prev) => ({isSkinToneListVisible: !prev.isSkinToneListVisible}))} - style={[styles.flex1, styles.flexRow, styles.alignSelfCenter, styles.justifyContentStart, styles.alignItemsCenter]} - > - - {selectedEmoji.code} - - {this.props.translate('emojiPicker.skinTonePickerLabel')} - - )} - {this.state.isSkinToneListVisible && ( - - {_.map(Emojis.skinTones, (skinToneEmoji) => ( - this.updateSelectedSkinTone(skinToneEmoji)} - onHoverIn={() => this.setState({highlightedIndex: skinToneEmoji.skinTone})} - onHoverOut={() => this.setState({highlightedIndex: selectedEmoji.skinTone})} - key={skinToneEmoji.code} - emoji={skinToneEmoji.code} - isHighlighted={skinToneEmoji.skinTone === this.state.highlightedIndex || skinToneEmoji.skinTone === selectedEmoji.skinTone} - /> - ))} + const currentSkinTone = getSkinToneEmojiFromIndex(props.preferredSkinTone); + return ( + + {!isSkinToneListVisible && ( + + + {currentSkinTone.code} - )} - - ); - } + {props.translate('emojiPicker.skinTonePickerLabel')} + + )} + {isSkinToneListVisible && ( + + {_.map(Emojis.skinTones, (skinToneEmoji) => ( + updateSelectedSkinTone(skinToneEmoji)} + onHoverIn={() => setHighlightedIndex(skinToneEmoji.skinTone)} + onHoverOut={() => setHighlightedIndex(null)} + key={skinToneEmoji.code} + emoji={skinToneEmoji.code} + isHighlighted={skinToneEmoji.skinTone === highlightedIndex || skinToneEmoji.skinTone === currentSkinTone.skinTone} + /> + ))} + + )} + + ); } EmojiSkinToneList.propTypes = propTypes; +EmojiSkinToneList.displayName = 'EmojiSkinToneList'; export default withLocalize(EmojiSkinToneList); diff --git a/src/components/Form.js b/src/components/Form.js index 5bcf97cf3547..578081ad0678 100644 --- a/src/components/Form.js +++ b/src/components/Form.js @@ -1,5 +1,5 @@ +import React, {useState, useEffect, useCallback, useRef} from 'react'; import lodashGet from 'lodash/get'; -import React from 'react'; import {Keyboard, ScrollView, StyleSheet} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; @@ -87,120 +87,99 @@ const defaultProps = { style: [], }; -class Form extends React.Component { - constructor(props) { - super(props); - - this.state = { - errors: {}, - inputValues: { - ...props.draftValues, - }, - }; - - this.formRef = React.createRef(null); - this.formContentRef = React.createRef(null); - this.inputRefs = {}; - this.touchedInputs = {}; - - this.setTouchedInput = this.setTouchedInput.bind(this); - this.validate = this.validate.bind(this); - this.submit = this.submit.bind(this); - } - - componentDidUpdate(prevProps) { - if (prevProps.preferredLocale === this.props.preferredLocale) { - return; - } +const Form = (props) => { + const [errors, setErrors] = useState({}); + const [inputValues, setInputValues] = useState({...props.draftValues}); + const formRef = useRef(null); + const formContentRef = useRef(null); + const inputRefs = useRef({}); + const touchedInputs = useRef({}); - // Update the error messages if the language changes - this.validate(this.state.inputValues); - } + const {validate, translate, onSubmit, children} = props; - getErrorMessage() { - const latestErrorMessage = ErrorUtils.getLatestErrorMessage(this.props.formState); - return this.props.formState.error || (typeof latestErrorMessage === 'string' ? latestErrorMessage : ''); - } + /** + * @param {Object} values - An object containing the value of each inputID, e.g. {inputID1: value1, inputID2: value2} + * @returns {Object} - An object containing the errors for each inputID, e.g. {inputID1: error1, inputID2: error2} + */ + const onValidate = useCallback( + (values) => { + const trimmedStringValues = {}; + _.each(values, (inputValue, inputID) => { + if (_.isString(inputValue)) { + trimmedStringValues[inputID] = inputValue.trim(); + } else { + trimmedStringValues[inputID] = inputValue; + } + }); - getFirstErroredInput() { - const hasStateErrors = !_.isEmpty(this.state.errors); - const hasErrorFields = !_.isEmpty(this.props.formState.errorFields); + FormActions.setErrors(props.formID, null); + FormActions.setErrorFields(props.formID, null); - if (!hasStateErrors && !hasErrorFields) { - return; - } + // Run any validations passed as a prop + const validationErrors = validate(trimmedStringValues); + + // Validate the input for html tags. It should supercede any other error + _.each(trimmedStringValues, (inputValue, inputID) => { + // Return early if there is no value OR the value is not a string OR there are no HTML characters + if (!inputValue || !_.isString(inputValue) || inputValue.search(CONST.VALIDATE_FOR_HTML_TAG_REGEX) === -1) { + return; + } + + // Add a validation error here because it is a string value that contains HTML characters + validationErrors[inputID] = translate('common.error.invalidCharacter'); + }); + + if (!_.isObject(validationErrors)) { + throw new Error('Validate callback must return an empty object or an object with shape {inputID: error}'); + } + + const touchedInputErrors = _.pick(validationErrors, (inputValue, inputID) => Boolean(touchedInputs.current[inputID])); + + if (!_.isEqual(errors, touchedInputErrors)) { + setErrors(touchedInputErrors); + } + + return touchedInputErrors; + }, + [errors, touchedInputs, props.formID, validate, translate], + ); - return _.first(_.keys(hasStateErrors ? this.state.erorrs : this.props.formState.errorFields)); - } + useEffect(() => { + onValidate(inputValues); + }, [onValidate, inputValues]); + + const getErrorMessage = useCallback(() => { + const latestErrorMessage = ErrorUtils.getLatestErrorMessage(props.formState); + return props.formState.error || (typeof latestErrorMessage === 'string' ? latestErrorMessage : ''); + }, [props.formState]); /** * @param {String} inputID - The inputID of the input being touched */ - setTouchedInput(inputID) { - this.touchedInputs[inputID] = true; - } + const setTouchedInput = useCallback( + (inputID) => { + touchedInputs.current[inputID] = true; + }, + [touchedInputs], + ); - submit() { + const submit = useCallback(() => { // Return early if the form is already submitting to avoid duplicate submission - if (this.props.formState.isLoading) { + if (props.formState.isLoading) { return; } // Touches all form inputs so we can validate the entire form - _.each(this.inputRefs, (inputRef, inputID) => (this.touchedInputs[inputID] = true)); + _.each(inputRefs.current, (inputRef, inputID) => (touchedInputs.current[inputID] = true)); // Validate form and return early if any errors are found - if (!_.isEmpty(this.validate(this.state.inputValues))) { + if (!_.isEmpty(onValidate(inputValues))) { return; } // Call submit handler - this.props.onSubmit(this.state.inputValues); - } - - /** - * @param {Object} values - An object containing the value of each inputID, e.g. {inputID1: value1, inputID2: value2} - * @returns {Object} - An object containing the errors for each inputID, e.g. {inputID1: error1, inputID2: error2} - */ - validate(values) { - const trimmedStringValues = {}; - _.each(values, (inputValue, inputID) => { - if (_.isString(inputValue)) { - trimmedStringValues[inputID] = inputValue.trim(); - } else { - trimmedStringValues[inputID] = inputValue; - } - }); - - FormActions.setErrors(this.props.formID, null); - FormActions.setErrorFields(this.props.formID, null); - - // Run any validations passed as a prop - const validationErrors = this.props.validate(trimmedStringValues); - - // Validate the input for html tags. It should supercede any other error - _.each(trimmedStringValues, (inputValue, inputID) => { - // Return early if there is no value OR the value is not a string OR there are no HTML characters - if (!inputValue || !_.isString(inputValue) || inputValue.search(CONST.VALIDATE_FOR_HTML_TAG_REGEX) === -1) { - return; - } - - // Add a validation error here because it is a string value that contains HTML characters - validationErrors[inputID] = this.props.translate('common.error.invalidCharacter'); - }); - - if (!_.isObject(validationErrors)) { - throw new Error('Validate callback must return an empty object or an object with shape {inputID: error}'); - } - - const errors = _.pick(validationErrors, (inputValue, inputID) => Boolean(this.touchedInputs[inputID])); - - if (!_.isEqual(errors, this.state.errors)) { - this.setState({errors}); - } - - return errors; - } + onSubmit(inputValues); + }, [props.formState, onSubmit, inputRefs, inputValues, onValidate, touchedInputs]); /** * Loops over Form's children and automatically supplies Form props to them @@ -208,154 +187,152 @@ class Form extends React.Component { * @param {Array | Function | Node} children - An array containing all Form children * @returns {React.Component} */ - childrenWrapperWithProps(children) { - return React.Children.map(children, (child) => { - // Just render the child if it is not a valid React element, e.g. text within a component - if (!React.isValidElement(child)) { - return child; - } + const childrenWrapperWithProps = useCallback( + (childNodes) => + React.Children.map(childNodes, (child) => { + // Just render the child if it is not a valid React element, e.g. text within a component + if (!React.isValidElement(child)) { + return child; + } - // Depth first traversal of the render tree as the input element is likely to be the last node - if (child.props.children) { - return React.cloneElement(child, { - children: this.childrenWrapperWithProps(child.props.children), - }); - } + // Depth first traversal of the render tree as the input element is likely to be the last node + if (child.props.children) { + return React.cloneElement(child, { + children: childrenWrapperWithProps(child.props.children), + }); + } + + // Look for any inputs nested in a custom component, e.g AddressForm or IdentityForm + if (_.isFunction(child.type)) { + const childNode = new child.type(child.props); - // Look for any inputs nested in a custom component, e.g AddressForm or IdentityForm - if (_.isFunction(child.type)) { - const childNode = new child.type(child.props); + // If the custom component has a render method, use it to get the nested children + const nestedChildren = _.isFunction(childNode.render) ? childNode.render() : childNode; - // If the custom component has a render method, use it to get the nested children - const nestedChildren = _.isFunction(childNode.render) ? childNode.render() : childNode; + // Render the custom component if it's a valid React element + // If the custom component has nested children, Loop over them and supply From props + if (React.isValidElement(nestedChildren) || lodashGet(nestedChildren, 'props.children')) { + return childrenWrapperWithProps(nestedChildren); + } - // Render the custom component if it's a valid React element - // If the custom component has nested children, Loop over them and supply From props - if (React.isValidElement(nestedChildren) || lodashGet(nestedChildren, 'props.children')) { - return this.childrenWrapperWithProps(nestedChildren); + // Just render the child if it's custom component not a valid React element, or if it hasn't children + return child; } - // Just render the child if it's custom component not a valid React element, or if it hasn't children - return child; - } + // We check if the child has the inputID prop. + // We don't want to pass form props to non form components, e.g. View, Text, etc + if (!child.props.inputID) { + return child; + } - // We check if the child has the inputID prop. - // We don't want to pass form props to non form components, e.g. View, Text, etc - if (!child.props.inputID) { - return child; - } + // We clone the child passing down all form props + const inputID = child.props.inputID; + let defaultValue; + + // We need to make sure that checkboxes have correct + // value assigned from the list of draft values + // https://github.com/Expensify/App/issues/16885#issuecomment-1520846065 + if (_.isBoolean(props.draftValues[inputID])) { + defaultValue = props.draftValues[inputID]; + } else { + defaultValue = props.draftValues[inputID] || child.props.defaultValue; + } - // We clone the child passing down all form props - const inputID = child.props.inputID; - let defaultValue; - - // We need to make sure that checkboxes have correct - // value assigned from the list of draft values - // https://github.com/Expensify/App/issues/16885#issuecomment-1520846065 - if (_.isBoolean(this.props.draftValues[inputID])) { - defaultValue = this.props.draftValues[inputID]; - } else { - defaultValue = this.props.draftValues[inputID] || child.props.defaultValue; - } + // We want to initialize the input value if it's undefined + if (_.isUndefined(inputValues[inputID])) { + inputValues[inputID] = defaultValue; + } - // We want to initialize the input value if it's undefined - if (_.isUndefined(this.state.inputValues[inputID])) { - this.state.inputValues[inputID] = defaultValue; - } + // We force the form to set the input value from the defaultValue props if there is a saved valid value + if (child.props.shouldUseDefaultValue) { + inputValues[inputID] = child.props.defaultValue; + } - // We force the form to set the input value from the defaultValue props if there is a saved valid value - if (child.props.shouldUseDefaultValue) { - this.state.inputValues[inputID] = child.props.defaultValue; - } + if (!_.isUndefined(child.props.value)) { + inputValues[inputID] = child.props.value; + } - if (!_.isUndefined(child.props.value)) { - this.state.inputValues[inputID] = child.props.value; - } + const errorFields = lodashGet(props.formState, 'errorFields', {}); + const fieldErrorMessage = + _.chain(errorFields[inputID]) + .keys() + .sortBy() + .reverse() + .map((key) => errorFields[inputID][key]) + .first() + .value() || ''; - const errorFields = lodashGet(this.props.formState, 'errorFields', {}); - const fieldErrorMessage = - _.chain(errorFields[inputID]) - .keys() - .sortBy() - .reverse() - .map((key) => errorFields[inputID][key]) - .first() - .value() || ''; - - return React.cloneElement(child, { - ref: (node) => { - this.inputRefs[inputID] = node; - - const {ref} = child; - if (_.isFunction(ref)) { - ref(node); - } - }, - value: this.state.inputValues[inputID], - errorText: this.state.errors[inputID] || fieldErrorMessage, - onBlur: (event) => { - // We delay the validation in order to prevent Checkbox loss of focus when - // the user are focusing a TextInput and proceeds to toggle a CheckBox in - // web and mobile web platforms. - setTimeout(() => { - this.setTouchedInput(inputID); - this.validate(this.state.inputValues); - }, 200); - - if (_.isFunction(child.props.onBlur)) { - child.props.onBlur(event); - } - }, - onTouched: () => { - this.setTouchedInput(inputID); - }, - onInputChange: (value, key) => { - const inputKey = key || inputID; - this.setState( - (prevState) => ({ - inputValues: { - ...prevState.inputValues, + return React.cloneElement(child, { + ref: (node) => { + inputRefs.current[inputID] = node; + + const {ref} = child; + if (_.isFunction(ref)) { + ref(node); + } + }, + value: inputValues[inputID], + errorText: errors[inputID] || fieldErrorMessage, + onBlur: (event) => { + // We delay the validation in order to prevent Checkbox loss of focus when + // the user are focusing a TextInput and proceeds to toggle a CheckBox in + // web and mobile web platforms. + setTimeout(() => { + setTouchedInput(inputID); + onValidate(inputValues); + }, 200); + + if (_.isFunction(child.props.onBlur)) { + child.props.onBlur(event); + } + }, + onTouched: () => { + setTouchedInput(inputID); + }, + onInputChange: (value, key) => { + const inputKey = key || inputID; + setInputValues((prevState) => { + const newState = { + ...prevState, [inputKey]: value, - }, - }), - () => this.validate(this.state.inputValues), - ); - - if (child.props.shouldSaveDraft) { - FormActions.setDraftValues(this.props.formID, {[inputKey]: value}); - } - - if (child.props.onValueChange) { - child.props.onValueChange(value); - } - }, - }); - }); - } + }; + onValidate(newState); + return newState; + }); + + if (child.props.shouldSaveDraft) { + FormActions.setDraftValues(props.formID, {[inputKey]: value}); + } + + if (child.props.onValueChange) { + child.props.onValueChange(value); + } + }, + }); + }), + [errors, inputRefs, inputValues, onValidate, props.draftValues, props.formID, props.formState, setTouchedInput], + ); - render() { - const scrollViewContent = (safeAreaPaddingBottomStyle) => ( + const scrollViewContent = useCallback( + (safeAreaPaddingBottomStyle) => ( - {this.childrenWrapperWithProps(_.isFunction(this.props.children) ? this.props.children({inputValues: this.state.inputValues}) : this.props.children)} - {this.props.isSubmitButtonVisible && ( + {childrenWrapperWithProps(_.isFunction(children) ? children({inputValues}) : children)} + {props.isSubmitButtonVisible && ( 0 || Boolean(this.getErrorMessage()) || !_.isEmpty(this.props.formState.errorFields)} - isLoading={this.props.formState.isLoading} - message={_.isEmpty(this.props.formState.errorFields) ? this.getErrorMessage() : null} - onSubmit={this.submit} - footerContent={this.props.footerContent} + buttonText={props.submitButtonText} + isAlertVisible={_.size(errors) > 0 || Boolean(getErrorMessage()) || !_.isEmpty(props.formState.errorFields)} + isLoading={props.formState.isLoading} + message={_.isEmpty(props.formState.errorFields) ? getErrorMessage() : null} + onSubmit={submit} + footerContent={props.footerContent} onFixTheErrorsLinkPressed={() => { - const errors = !_.isEmpty(this.state.errors) ? this.state.errors : this.props.formState.errorFields; - const focusKey = _.find(_.keys(this.inputRefs), (key) => _.keys(errors).includes(key)); - const focusInput = this.inputRefs[focusKey]; - - const formRef = this.formRef.current; - const formContentRef = this.formContentRef.current; + const errorFields = !_.isEmpty(errors) ? errors : props.formState.errorFields; + const focusKey = _.find(_.keys(inputRefs.current), (key) => _.keys(errorFields).includes(key)); + const focusInput = inputRefs.current[focusKey]; // Start with dismissing the keyboard, so when we focus a non-text input, the keyboard is hidden Keyboard.dismiss(); @@ -364,7 +341,7 @@ class Form extends React.Component { if (focusInput.measureLayout && typeof focusInput.measureLayout === 'function') { // We measure relative to the content root, not the scroll view, as that gives // consistent results across mobile and web - focusInput.measureLayout(formContentRef, (x, y) => formRef.scrollTo({y: y - 10, animated: false})); + focusInput.measureLayout(formContentRef.current, (x, y) => formRef.current.scrollTo({y: y - 10, animated: false})); } // Focus the input after scrolling, as on the Web it gives a slightly better visual result @@ -373,42 +350,61 @@ class Form extends React.Component { } }} containerStyles={[styles.mh0, styles.mt5, styles.flex1]} - enabledWhenOffline={this.props.enabledWhenOffline} - isSubmitActionDangerous={this.props.isSubmitActionDangerous} + enabledWhenOffline={props.enabledWhenOffline} + isSubmitActionDangerous={props.isSubmitActionDangerous} disablePressOnEnter /> )} - ); - - return ( - - {({safeAreaPaddingBottomStyle}) => - this.props.scrollContextEnabled ? ( - - {scrollViewContent(safeAreaPaddingBottomStyle)} - - ) : ( - - {scrollViewContent(safeAreaPaddingBottomStyle)} - - ) - } - - ); - } -} + ), + [ + childrenWrapperWithProps, + errors, + formContentRef, + formRef, + getErrorMessage, + inputRefs, + inputValues, + submit, + props.style, + children, + props.formState, + props.footerContent, + props.enabledWhenOffline, + props.isSubmitActionDangerous, + props.isSubmitButtonVisible, + props.submitButtonText, + ], + ); + + return ( + + {({safeAreaPaddingBottomStyle}) => + props.scrollContextEnabled ? ( + + {scrollViewContent(safeAreaPaddingBottomStyle)} + + ) : ( + + {scrollViewContent(safeAreaPaddingBottomStyle)} + + ) + } + + ); +}; +Form.displayName = 'Form'; Form.propTypes = propTypes; Form.defaultProps = defaultProps; diff --git a/src/components/Icon/Expensicons.js b/src/components/Icon/Expensicons.js index 70503706f112..db093d2bc4df 100644 --- a/src/components/Icon/Expensicons.js +++ b/src/components/Icon/Expensicons.js @@ -41,6 +41,10 @@ import ExpensifyWordmark from '../../../assets/images/expensify-wordmark.svg'; import Expand from '../../../assets/images/expand.svg'; import Eye from '../../../assets/images/eye.svg'; import EyeDisabled from '../../../assets/images/eye-disabled.svg'; +import Flag from '../../../assets/images/flag.svg'; +import FlagLevelOne from '../../../assets/images/flag_level_01.svg'; +import FlagLevelTwo from '../../../assets/images/flag_level_02.svg'; +import FlagLevelThree from '../../../assets/images/flag_level_03.svg'; import Gallery from '../../../assets/images/gallery.svg'; import Gear from '../../../assets/images/gear.svg'; import Globe from '../../../assets/images/globe.svg'; @@ -162,6 +166,10 @@ export { EyeDisabled, FallbackAvatar, FallbackWorkspaceAvatar, + Flag, + FlagLevelOne, + FlagLevelTwo, + FlagLevelThree, Gallery, Gear, Globe, diff --git a/src/components/ImageView/index.js b/src/components/ImageView/index.js index f1ec25485991..7138f4087ed4 100644 --- a/src/components/ImageView/index.js +++ b/src/components/ImageView/index.js @@ -282,6 +282,7 @@ class ImageView extends PureComponent { > - + {decomposeString(props.value, props.maxLength)[index] || ''} diff --git a/src/components/MenuItem.js b/src/components/MenuItem.js index 66536b796eea..21195a9f4ca2 100644 --- a/src/components/MenuItem.js +++ b/src/components/MenuItem.js @@ -21,6 +21,7 @@ import PressableWithSecondaryInteraction from './PressableWithSecondaryInteracti import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; import * as DeviceCapabilities from '../libs/DeviceCapabilities'; import ControlSelection from '../libs/ControlSelection'; +import variables from '../styles/variables'; const propTypes = { ...menuItemPropTypes, @@ -62,6 +63,9 @@ const defaultProps = { shouldStackHorizontally: false, avatarSize: undefined, shouldBlockSelection: false, + hoverAndPressStyle: [], + furtherDetails: '', + furtherDetailsIcon: undefined, }; const MenuItem = (props) => { @@ -112,6 +116,7 @@ const MenuItem = (props) => { props.style, !props.interactive && styles.cursorDefault, StyleUtils.getButtonBackgroundColorStyle(getButtonState(props.focused || hovered, pressed, props.success, props.disabled, props.interactive), true), + (hovered || pressed) && props.hoverAndPressStyle, ...(_.isArray(props.wrapperStyle) ? props.wrapperStyle : [props.wrapperStyle]), ]} disabled={props.disabled} @@ -187,6 +192,22 @@ const MenuItem = (props) => { {props.description} )} + {Boolean(props.furtherDetails) && ( + + + + {props.furtherDetails} + + + )} diff --git a/src/components/ReportActionItem/IOUPreview.js b/src/components/ReportActionItem/IOUPreview.js index ab706197351a..902c724aa614 100644 --- a/src/components/ReportActionItem/IOUPreview.js +++ b/src/components/ReportActionItem/IOUPreview.js @@ -4,7 +4,6 @@ import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import lodashGet from 'lodash/get'; import _ from 'underscore'; -import Str from 'expensify-common/lib/str'; import compose from '../../libs/compose'; import styles from '../../styles/styles'; import ONYXKEYS from '../../ONYXKEYS'; @@ -141,7 +140,7 @@ const IOUPreview = (props) => { const requestAmount = moneyRequestAction.amount; const requestCurrency = moneyRequestAction.currency; - const requestComment = Str.htmlDecode(moneyRequestAction.comment).trim(); + const requestComment = moneyRequestAction.comment.trim(); const getSettledMessage = () => { switch (lodashGet(props.action, 'originalMessage.paymentType', '')) { diff --git a/src/components/ReportTransaction.js b/src/components/ReportTransaction.js deleted file mode 100644 index 166921cb3845..000000000000 --- a/src/components/ReportTransaction.js +++ /dev/null @@ -1,84 +0,0 @@ -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; -import {View} from 'react-native'; -import styles from '../styles/styles'; -import * as IOU from '../libs/actions/IOU'; -import * as ReportActions from '../libs/actions/ReportActions'; -import reportActionPropTypes from '../pages/home/report/reportActionPropTypes'; -import ReportActionItemSingle from '../pages/home/report/ReportActionItemSingle'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; -import OfflineWithFeedback from './OfflineWithFeedback'; -import Text from './Text'; -import Button from './Button'; - -const propTypes = { - /** The chatReport which the transaction is associated with */ - /* eslint-disable-next-line react/no-unused-prop-types */ - chatReportID: PropTypes.string.isRequired, - - /** ID for the IOU report */ - /* eslint-disable-next-line react/no-unused-prop-types */ - iouReportID: PropTypes.string.isRequired, - - /** The report action which we are displaying */ - action: PropTypes.shape(reportActionPropTypes).isRequired, - - /** Can this transaction be deleted? */ - canBeDeleted: PropTypes.bool, - - /** Indicates whether pressing the delete button should hide the details sidebar */ - shouldCloseOnDelete: PropTypes.bool, - - ...withLocalizePropTypes, -}; - -const defaultProps = { - canBeDeleted: false, - shouldCloseOnDelete: false, -}; - -class ReportTransaction extends Component { - constructor(props) { - super(props); - - this.deleteMoneyRequest = this.deleteMoneyRequest.bind(this); - } - - deleteMoneyRequest() { - IOU.deleteMoneyRequest(this.props.chatReportID, this.props.iouReportID, this.props.action, this.props.shouldCloseOnDelete); - } - - render() { - return ( - ReportActions.clearReportActionErrors(this.props.chatReportID, this.props.action)} - pendingAction={this.props.action.pendingAction} - errors={this.props.action.errors} - errorRowStyles={[styles.ml10, styles.mr2]} - > - - - {this.props.action.message[0].text} - - {this.props.canBeDeleted && ( - - + )} + ) : ( )} + {!props.displayAsGroup && hasBeenFlagged && ( + + )} ); } @@ -331,6 +387,7 @@ function ReportActionItem(props) { wrapperStyles={[styles.chatItem, isWhisper ? styles.pt1 : {}]} shouldShowSubscriptAvatar={props.shouldShowSubscriptAvatar} report={props.report} + hasBeenFlagged={!_.contains([CONST.MODERATION.MODERATOR_DECISION_APPROVED, CONST.MODERATION.MODERATOR_DECISION_PENDING], moderationDecision)} > {content} diff --git a/src/pages/home/report/ReportActionItemMessage.js b/src/pages/home/report/ReportActionItemMessage.js index 6ebf8c10e472..a764eafb84b7 100644 --- a/src/pages/home/report/ReportActionItemMessage.js +++ b/src/pages/home/report/ReportActionItemMessage.js @@ -1,5 +1,5 @@ import React from 'react'; -import {View} from 'react-native'; +import {View, Text} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import lodashGet from 'lodash/get'; @@ -15,28 +15,36 @@ const propTypes = { /** Additional styles to add after local styles. */ style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + /** Whether or not the message is hidden by moderation */ + isHidden: PropTypes.bool, + /** localization props */ ...withLocalizePropTypes, }; const defaultProps = { style: [], + isHidden: false, }; const ReportActionItemMessage = (props) => ( - {_.map(_.compact(props.action.previousMessage || props.action.message), (fragment, index) => ( - - ))} + {!props.isHidden ? ( + _.map(_.compact(props.action.previousMessage || props.action.message), (fragment, index) => ( + + )) + ) : ( + {props.translate('moderation.flaggedContent')} + )} ); diff --git a/src/pages/home/report/ReportActionItemParentAction.js b/src/pages/home/report/ReportActionItemParentAction.js index 991a7c507b16..9ce119494b56 100644 --- a/src/pages/home/report/ReportActionItemParentAction.js +++ b/src/pages/home/report/ReportActionItemParentAction.js @@ -17,6 +17,9 @@ import reportActionPropTypes from './reportActionPropTypes'; import * as ReportActionsUtils from '../../../libs/ReportActionsUtils'; const propTypes = { + /** Flag to show, hide the thread divider line */ + shouldHideThreadDividerLine: PropTypes.bool, + /** The id of the report */ reportID: PropTypes.string.isRequired, @@ -38,6 +41,7 @@ const propTypes = { const defaultProps = { report: {}, parentReportActions: {}, + shouldHideThreadDividerLine: false, }; const ReportActionItemParentAction = (props) => { @@ -67,7 +71,7 @@ const ReportActionItemParentAction = (props) => { /> )} - + {!props.shouldHideThreadDividerLine && } ); }; diff --git a/src/pages/home/report/ReportActionItemSingle.js b/src/pages/home/report/ReportActionItemSingle.js index 3cbe52cd0e38..96fd6be6ad26 100644 --- a/src/pages/home/report/ReportActionItemSingle.js +++ b/src/pages/home/report/ReportActionItemSingle.js @@ -46,6 +46,9 @@ const propTypes = { /** Determines if the avatar is displayed as a subscript (positioned lower than normal) */ shouldShowSubscriptAvatar: PropTypes.bool, + /** If the message has been flagged for moderation */ + hasBeenFlagged: PropTypes.bool, + ...withLocalizePropTypes, }; @@ -54,6 +57,7 @@ const defaultProps = { wrapperStyles: [styles.chatItem], showHeader: true, shouldShowSubscriptAvatar: false, + hasBeenFlagged: false, report: undefined, }; @@ -130,7 +134,7 @@ const ReportActionItemSingle = (props) => { ) : null} - {props.children} + {props.children} ); diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index 75cd18743822..b10134b2ceb7 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -115,8 +115,11 @@ const ReportActionsList = (props) => { // When the new indicator should not be displayed we explicitly set it to null const shouldDisplayNewMarker = reportAction.reportActionID === newMarkerReportActionID; const shouldDisplayParentAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED && ReportUtils.isThread(report); + const shouldHideThreadDividerLine = + shouldDisplayParentAction && sortedReportActions.length > 1 && sortedReportActions[sortedReportActions.length - 2].reportActionID === newMarkerReportActionID; return shouldDisplayParentAction ? ( action.originalMessage && action.originalMessage.type && Number(action.originalMessage.IOUReportID) === Number(this.props.iouReportID), - ); - - const deletedTransactionIDs = _.chain(actionsForIOUReport) - .filter((action) => _.contains([CONST.IOU.REPORT_ACTION_TYPE.CANCEL, CONST.IOU.REPORT_ACTION_TYPE.DECLINE, CONST.IOU.REPORT_ACTION_TYPE.DELETE], action.originalMessage.type)) - .map((deletedAction) => lodashGet(deletedAction, 'originalMessage.IOUTransactionID', '')) - .compact() - .value(); - - return _.chain(actionsForIOUReport) - .filter((action) => action.originalMessage.type === CONST.IOU.REPORT_ACTION_TYPE.CREATE) - .filter((action) => !_.contains(deletedTransactionIDs, action.originalMessage.IOUTransactionID)) - .filter((action) => this.props.userEmail === action.actorEmail) - .map((action) => lodashGet(action, 'originalMessage.IOUTransactionID', '')) - .compact() - .value(); - } - - render() { - const sortedReportActions = ReportActionsUtils.getSortedReportActionsForDisplay(this.props.reportActions); - return ( - - {_.map(sortedReportActions, (reportAction) => { - // iouReportIDs should be strings, but we still have places that send them as ints so we convert them both to Numbers for comparison - if ( - !reportAction.originalMessage || - reportAction.actionName !== CONST.REPORT.ACTIONS.TYPE.IOU || - Number(reportAction.originalMessage.IOUReportID) !== Number(this.props.iouReportID) - ) { - return; - } - - const deletableTransactions = this.getDeletableTransactions(); - const canBeDeleted = _.contains(deletableTransactions, reportAction.originalMessage.IOUTransactionID); - return ( - - ); - })} - - ); - } -} - -IOUTransactions.defaultProps = defaultProps; -IOUTransactions.propTypes = propTypes; -export default withOnyx({ - reportActions: { - key: ({chatReportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${chatReportID}`, - canEvict: false, - }, -})(IOUTransactions); diff --git a/src/pages/signin/ChangeExpensifyLoginLink.js b/src/pages/signin/ChangeExpensifyLoginLink.js index 4e033d947710..0ea56a176af2 100755 --- a/src/pages/signin/ChangeExpensifyLoginLink.js +++ b/src/pages/signin/ChangeExpensifyLoginLink.js @@ -1,5 +1,5 @@ import React from 'react'; -import {TouchableOpacity, View} from 'react-native'; +import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import PropTypes from 'prop-types'; @@ -8,6 +8,7 @@ import styles from '../../styles/styles'; import ONYXKEYS from '../../ONYXKEYS'; import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; import compose from '../../libs/compose'; +import PressableWithFeedback from '../../components/Pressable/PressableWithFeedback'; const propTypes = { /** The credentials of the logged in person */ @@ -31,15 +32,17 @@ const defaultProps = { const ChangeExpensifyLoginLink = (props) => ( {!_.isEmpty(props.credentials.login) && {props.translate('loginForm.notYou', {user: props.formatPhoneNumber(props.credentials.login)})}} - {props.translate('common.goBack')} {'.'} - + ); diff --git a/src/pages/signin/PasswordForm.js b/src/pages/signin/PasswordForm.js index 78eaf0e0a0e9..26ab6eb1423e 100755 --- a/src/pages/signin/PasswordForm.js +++ b/src/pages/signin/PasswordForm.js @@ -1,5 +1,5 @@ import React from 'react'; -import {TouchableOpacity, View} from 'react-native'; +import {View} from 'react-native'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; @@ -23,6 +23,7 @@ import {withNetwork} from '../../components/OnyxProvider'; import networkPropTypes from '../../components/networkPropTypes'; import FormHelpMessage from '../../components/FormHelpMessage'; import Terms from './Terms'; +import PressableWithFeedback from '../../components/Pressable/PressableWithFeedback'; const propTypes = { /* Onyx Props */ @@ -191,12 +192,15 @@ class PasswordForm extends React.Component { hasError={passwordFieldHasError} /> - {this.props.translate('passwordForm.forgot')} - + diff --git a/src/pages/signin/ResendValidationForm.js b/src/pages/signin/ResendValidationForm.js index a5874d2421dc..c17e19099b7f 100755 --- a/src/pages/signin/ResendValidationForm.js +++ b/src/pages/signin/ResendValidationForm.js @@ -1,6 +1,6 @@ import React from 'react'; import _ from 'underscore'; -import {TouchableOpacity, View} from 'react-native'; +import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import PropTypes from 'prop-types'; import Str from 'expensify-common/lib/str'; @@ -17,6 +17,7 @@ import * as UserUtils from '../../libs/UserUtils'; import networkPropTypes from '../../components/networkPropTypes'; import {withNetwork} from '../../components/OnyxProvider'; import DotIndicatorMessage from '../../components/DotIndicatorMessage'; +import PressableWithFeedback from '../../components/Pressable/PressableWithFeedback'; import CONST from '../../CONST'; const propTypes = { @@ -91,9 +92,16 @@ const ResendValidationForm = (props) => { /> )} - redirectToSignIn()}> + redirectToSignIn()} + accessibilityRole="button" + accessibilityLabel={props.translate('common.back')} + // disable hover dim for switch + hoverDimmingValue={1} + pressDimmingValue={0.2} + > {props.translate('common.back')} - +