diff --git a/.eslintignore b/.eslintignore
index cd4efd8e..1f6dfa0a 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1 +1,4 @@
*.d.ts
+dist
+node_modules
+*.config.js
diff --git a/.eslintrc.js b/.eslintrc.js
index 02a609dc..f49834cc 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,11 +1,80 @@
module.exports = {
extends: ['expensify', 'prettier'],
- rules: {
- // Allow JSX to be written in any file ignoring the extension type
- 'react/jsx-filename-extension': 'off'
- },
- plugins: ['jest'],
- env: {
- "jest/globals": true
- }
+ parser: '@typescript-eslint/parser',
+ overrides: [
+ {
+ files: ['*.js', '*.jsx'],
+ settings: {
+ 'import/resolver': {
+ node: {
+ extensions: ['.js', '.jsx', '.ts', '.tsx'],
+ },
+ },
+ },
+ rules: {
+ // Allow JSX to be written in any file ignoring the extension type
+ 'react/jsx-filename-extension': 'off',
+ 'rulesdir/no-api-in-views': 'off',
+ 'rulesdir/no-multiple-api-calls': 'off',
+ 'rulesdir/prefer-import-module-contents': 'off',
+ 'no-constructor-return': 'off',
+ 'import/extensions': [
+ 'error',
+ 'ignorePackages',
+ {
+ js: 'never',
+ jsx: 'never',
+ ts: 'never',
+ tsx: 'never',
+ },
+ ],
+ },
+ },
+ {
+ files: ['*.ts', '*.tsx'],
+ extends: [
+ 'expensify',
+ 'plugin:@typescript-eslint/recommended',
+ 'plugin:@typescript-eslint/stylistic',
+ 'plugin:import/typescript',
+ 'plugin:you-dont-need-lodash-underscore/all',
+ 'prettier',
+ 'plugin:prettier/recommended',
+ ],
+ plugins: ['react', 'import', '@typescript-eslint'],
+ parserOptions: {
+ project: './tsconfig.json',
+ },
+ rules: {
+ 'prefer-regex-literals': 'off',
+ 'rulesdir/prefer-underscore-method': 'off',
+ 'react/jsx-props-no-spreading': 'off',
+ 'react/require-default-props': 'off',
+ 'valid-jsdoc': 'off',
+ 'es/no-optional-chaining': 'off',
+ 'es/no-nullish-coalescing-operators': 'off',
+ 'react/jsx-filename-extension': ['error', {extensions: ['.tsx', '.jsx']}],
+ 'import/no-unresolved': 'error',
+ 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
+ 'no-use-before-define': 'off',
+ '@typescript-eslint/no-use-before-define': 'off',
+ '@typescript-eslint/no-unused-vars': ['error', {argsIgnorePattern: '^_'}],
+ '@typescript-eslint/consistent-type-imports': ['error', {prefer: 'type-imports'}],
+ '@typescript-eslint/consistent-type-exports': ['error', {fixMixedExportsWithInlineTypeSpecifier: false}],
+ '@typescript-eslint/no-non-null-assertion': 'off',
+ '@typescript-eslint/array-type': ['error', {default: 'array-simple'}],
+ '@typescript-eslint/consistent-type-definitions': 'off',
+ 'import/extensions': [
+ 'error',
+ 'ignorePackages',
+ {
+ js: 'never',
+ jsx: 'never',
+ ts: 'never',
+ tsx: 'never',
+ },
+ ],
+ },
+ },
+ ],
};
diff --git a/.github/OSBotify-private-key.asc.gpg b/.github/OSBotify-private-key.asc.gpg
new file mode 100644
index 00000000..c19d5c97
Binary files /dev/null and b/.github/OSBotify-private-key.asc.gpg differ
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 71bab56f..a24f8b13 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -27,3 +27,12 @@ jobs:
- run: npm run lint
env:
CI: true
+
+ - name: Verify there's no Prettier diff
+ run: |
+ npm run prettier -- --loglevel silent
+ if ! git diff --name-only --exit-code; then
+ # shellcheck disable=SC2016
+ echo 'Error: Prettier diff detected! Please run `npm run prettier` and commit the changes.'
+ exit 1
+ fi
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 00000000..baa8fded
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,77 @@
+name: Publish package to npmjs
+
+# This workflow runs when code is pushed to `main` (i.e: when a pull request is merged)
+on:
+ push:
+ branches: [main]
+
+# Ensure that only once instance of this workflow executes at a time.
+# If multiple PRs are merged in quick succession, there will only ever be one publish workflow running and one pending.
+concurrency: ${{ github.workflow }}
+
+jobs:
+ version:
+ runs-on: ubuntu-latest
+
+ # OSBotify will update the version on `main`, so this check is important to prevent an infinite loop
+ if: ${{ github.actor != 'OSBotify' }}
+
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ ref: main
+ # The OS_BOTIFY_COMMIT_TOKEN is a personal access token tied to osbotify, which allows him to push to protected branches
+ token: ${{ secrets.OS_BOTIFY_COMMIT_TOKEN }}
+
+ - name: Decrypt & Import OSBotify GPG key
+ run: |
+ cd .github
+ gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output OSBotify-private-key.asc OSBotify-private-key.asc.gpg
+ gpg --import OSBotify-private-key.asc
+ env:
+ LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }}
+
+ - name: Set up git for OSBotify
+ run: |
+ git config --global user.signingkey 367811D53E34168C
+ git config --global commit.gpgsign true
+ git config --global user.name OSBotify
+ git config --global user.email infra+osbotify@expensify.com
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ registry-url: 'https://registry.npmjs.org'
+
+ - name: Install npm packages
+ run: npm ci
+
+ - name: Update npm version
+ run: npm version patch
+
+ - name: Set new version in GitHub ENV
+ run: echo "NEW_VERSION=$(jq '.version' package.json)" >> $GITHUB_ENV
+
+ - name: Push branch and publish tags
+ run: git push origin main && git push --tags
+
+ - name: Build package
+ run: npm run build
+
+ - name: Publish to npm
+ run: npm publish
+ env:
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+
+ - name: Get merged pull request
+ id: getMergedPullRequest
+ run: |
+ read -r number < <(gh pr list --search ${{ github.sha }} --state merged --json 'number' | jq -r '.[0] | [.number] | join(" ")')
+ echo "number=$number" >> "$GITHUB_OUTPUT"
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+
+ - name: Comment on merged pull request
+ run: gh pr comment ${{ steps.getMergedPullRequest.outputs.number }} --body "🚀Published to npm in v${{ env.NEW_VERSION }}"
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml
new file mode 100644
index 00000000..09d4a38f
--- /dev/null
+++ b/.github/workflows/typecheck.yml
@@ -0,0 +1,24 @@
+name: TypeScript Checks
+
+on:
+ pull_request:
+ types: [opened, synchronize]
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Node
+ uses: actions/setup-node@v4
+ with:
+ cache: npm
+ cache-dependency-path: package-lock.json
+
+ - run: npm ci
+
+ - name: Type check with TypeScript
+ run: npm run typecheck
+ env:
+ CI: true
diff --git a/.gitignore b/.gitignore
index 608a5535..78c6fc53 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,10 @@ npm-debug.log
package.json-e
.DS_Store
*.swp
+dist
+
+# Decrypted private key we do not want to commit
+.github/OSBotify-private-key.asc
+
+# Published package
+*.tgz
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 00000000..62d44807
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+20.13.0
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 00000000..d54e0bdf
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,4 @@
+dist
+package.json
+package-lock.json
+*.html
diff --git a/README.md b/README.md
index 11baaf0b..55801113 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,16 @@
# `expensify-common`
-This is a collection of JS libraries and components which are used across various Expensify projects. These libraries are provided as-is, and the repos which use them will need to do their own bundling, minifying, and uglifying.
+This is a collection of JS/TS libraries and components which are used across various Expensify projects. These libraries are provided as-is, and the repos which use them will need to do their own bundling, minifying, and uglifying.
# Installation
-1. Clone this repo to a directory of your choosing
-2. Run `npm install` to install all the dependencies
+`expensify-common` is published to [`npm`](https://www.npmjs.com/package/expensify-common)
+
+```shell
+npm install expensify-common
+```
# Development
* Write all code as ES6.
-* Always lint your code with `npm run grunt watch`
-* Make sure you're using http://editorconfig.org/
+* Always lint your code with `npm run lint`
## Testing your code while you are developing
The best way to test your code while you are developing changes is via `npm link`.
@@ -28,7 +30,7 @@ Alternatively, you can edit files directly in a project's `node_modules` then ap
1. They will review and accept your changes, merge them, then deploy a new version
# Deploying a Change (Expensify Only)
-Once the PR has been merged, update the `package.json` commit hash in any repos with a dependency on the code being changed in expensify-common, don't forget to run a `npm install` so `package-lock.json` is also updated. Be sure to check the repos below to confirm whether or not they are affected by your changes!
+Once the PR has been merged, install the new version of the package with `npm install expensify-common@x.x.x` command. Be sure to check the repos below to confirm whether or not they are affected by your changes!
- Expensify/Web-Expensify
- Expensify/Web-Secure
- Expensify/Mobile-Expensify
diff --git a/babel.config.js b/babel.config.js
index d7c97f55..f792e8e1 100644
--- a/babel.config.js
+++ b/babel.config.js
@@ -1,12 +1,3 @@
module.exports = {
- presets: [
- [
- '@babel/preset-env',
- {
- targets: {
- node: 'current',
- },
- },
- ],
- ],
+ presets: [['@babel/preset-env', {targets: {node: 'current'}}], '@babel/preset-typescript'],
};
diff --git a/lib/API.jsx b/lib/API.jsx
index 6a6d0482..41cdafa2 100644
--- a/lib/API.jsx
+++ b/lib/API.jsx
@@ -150,6 +150,7 @@ export default function API(network, args) {
* @param {String} commandName The name of the API command
*/
function requireParameters(parameterNames, parameters, commandName) {
+ // eslint-disable-next-line rulesdir/prefer-early-return
parameterNames.forEach((parameterName) => {
if (!_(parameters).has(parameterName) || parameters[parameterName] === null || parameters[parameterName] === undefined) {
const parametersCopy = _.clone(parameters);
@@ -823,7 +824,7 @@ export default function API(network, args) {
*
* @returns {APIDeferred}
*/
- createAdminIssuedVirtualCard: function (parameters) {
+ createAdminIssuedVirtualCard(parameters) {
const commandName = 'Card_CreateAdminIssuedVirtualCard';
requireParameters(['cardTitle', 'assigneeEmail', 'cardLimit', 'cardLimitType', 'domainName'], parameters, commandName);
return performPOSTRequest(commandName, parameters);
@@ -842,7 +843,7 @@ export default function API(network, args) {
*
* @returns {APIDeferred}
*/
- editAdminIssuedVirtualCard: function (parameters) {
+ editAdminIssuedVirtualCard(parameters) {
const commandName = 'Card_EditAdminIssuedVirtualCard';
requireParameters(['domainName', 'cardID', 'cardTitle', 'assigneeEmail', 'cardLimit', 'cardLimitType'], parameters, commandName);
return performPOSTRequest(commandName, parameters);
diff --git a/lib/CONST.d.ts b/lib/CONST.d.ts
deleted file mode 100644
index 77974b46..00000000
--- a/lib/CONST.d.ts
+++ /dev/null
@@ -1,852 +0,0 @@
-/**
- * URL of our CloudFront Instance
- */
-export declare const g_cloudFront: 'https://d2k5nsl2zxldvw.cloudfront.net';
-/**
- * URL of our image CDN
- */
-export declare const g_cloudFrontImg: 'https://d2k5nsl2zxldvw.cloudfront.net/images/';
-export declare const CONST: {
- readonly CORPAY_DIRECT_REIMBURSEMENT_CURRENCIES: readonly ['USD', 'GBP', 'EUR', 'AUD', 'CAD'];
- /**
- * Default max ACH limit. It can be overwritten by a private NVP
- */
- readonly ACH_DEFAULT_MAX_AMOUNT_LIMIT: 2000000;
- /**
- * IRS remimbursement rate for mileage
- * WARNING ! UPDATE THE PHP CONSTANT VERSION WHEN UPDATING THIS ONE
- */
- readonly MILEAGE_IRS_RATE: 0.545 | 0.58;
- readonly COUNTRY: {
- readonly US: 'US';
- readonly AU: 'AU';
- readonly UK: 'UK';
- readonly NZ: 'NZ';
- };
- readonly CURRENCIES: {
- readonly US: 'USD';
- readonly AU: 'AUD';
- readonly UK: 'GBP';
- readonly NZ: 'NZD';
- };
- readonly STATES: {
- readonly AK: {
- readonly stateISO: 'AK';
- readonly stateName: 'Alaska';
- };
- readonly AL: {
- readonly stateISO: 'AL';
- readonly stateName: 'Alabama';
- };
- readonly AR: {
- readonly stateISO: 'AR';
- readonly stateName: 'Arkansas';
- };
- readonly AZ: {
- readonly stateISO: 'AZ';
- readonly stateName: 'Arizona';
- };
- readonly CA: {
- readonly stateISO: 'CA';
- readonly stateName: 'California';
- };
- readonly CO: {
- readonly stateISO: 'CO';
- readonly stateName: 'Colorado';
- };
- readonly CT: {
- readonly stateISO: 'CT';
- readonly stateName: 'Connecticut';
- };
- readonly DE: {
- readonly stateISO: 'DE';
- readonly stateName: 'Delaware';
- };
- readonly FL: {
- readonly stateISO: 'FL';
- readonly stateName: 'Florida';
- };
- readonly GA: {
- readonly stateISO: 'GA';
- readonly stateName: 'Georgia';
- };
- readonly HI: {
- readonly stateISO: 'HI';
- readonly stateName: 'Hawaii';
- };
- readonly IA: {
- readonly stateISO: 'IA';
- readonly stateName: 'Iowa';
- };
- readonly ID: {
- readonly stateISO: 'ID';
- readonly stateName: 'Idaho';
- };
- readonly IL: {
- readonly stateISO: 'IL';
- readonly stateName: 'Illinois';
- };
- readonly IN: {
- readonly stateISO: 'IN';
- readonly stateName: 'Indiana';
- };
- readonly KS: {
- readonly stateISO: 'KS';
- readonly stateName: 'Kansas';
- };
- readonly KY: {
- readonly stateISO: 'KY';
- readonly stateName: 'Kentucky';
- };
- readonly LA: {
- readonly stateISO: 'LA';
- readonly stateName: 'Louisiana';
- };
- readonly MA: {
- readonly stateISO: 'MA';
- readonly stateName: 'Massachusetts';
- };
- readonly MD: {
- readonly stateISO: 'MD';
- readonly stateName: 'Maryland';
- };
- readonly ME: {
- readonly stateISO: 'ME';
- readonly stateName: 'Maine';
- };
- readonly MI: {
- readonly stateISO: 'MI';
- readonly stateName: 'Michigan';
- };
- readonly MN: {
- readonly stateISO: 'MN';
- readonly stateName: 'Minnesota';
- };
- readonly MO: {
- readonly stateISO: 'MO';
- readonly stateName: 'Missouri';
- };
- readonly MS: {
- readonly stateISO: 'MS';
- readonly stateName: 'Mississippi';
- };
- readonly MT: {
- readonly stateISO: 'MT';
- readonly stateName: 'Montana';
- };
- readonly NC: {
- readonly stateISO: 'NC';
- readonly stateName: 'North Carolina';
- };
- readonly ND: {
- readonly stateISO: 'ND';
- readonly stateName: 'North Dakota';
- };
- readonly NE: {
- readonly stateISO: 'NE';
- readonly stateName: 'Nebraska';
- };
- readonly NH: {
- readonly stateISO: 'NH';
- readonly stateName: 'New Hampshire';
- };
- readonly NJ: {
- readonly stateISO: 'NJ';
- readonly stateName: 'New Jersey';
- };
- readonly NM: {
- readonly stateISO: 'NM';
- readonly stateName: 'New Mexico';
- };
- readonly NV: {
- readonly stateISO: 'NV';
- readonly stateName: 'Nevada';
- };
- readonly NY: {
- readonly stateISO: 'NY';
- readonly stateName: 'New York';
- };
- readonly OH: {
- readonly stateISO: 'OH';
- readonly stateName: 'Ohio';
- };
- readonly OK: {
- readonly stateISO: 'OK';
- readonly stateName: 'Oklahoma';
- };
- readonly OR: {
- readonly stateISO: 'OR';
- readonly stateName: 'Oregon';
- };
- readonly PA: {
- readonly stateISO: 'PA';
- readonly stateName: 'Pennsylvania';
- };
- readonly PR: {
- readonly stateISO: 'PR';
- readonly stateName: 'Puerto Rico';
- };
- readonly RI: {
- readonly stateISO: 'RI';
- readonly stateName: 'Rhode Island';
- };
- readonly SC: {
- readonly stateISO: 'SC';
- readonly stateName: 'South Carolina';
- };
- readonly SD: {
- readonly stateISO: 'SD';
- readonly stateName: 'South Dakota';
- };
- readonly TN: {
- readonly stateISO: 'TN';
- readonly stateName: 'Tennessee';
- };
- readonly TX: {
- readonly stateISO: 'TX';
- readonly stateName: 'Texas';
- };
- readonly UT: {
- readonly stateISO: 'UT';
- readonly stateName: 'Utah';
- };
- readonly VA: {
- readonly stateISO: 'VA';
- readonly stateName: 'Virginia';
- };
- readonly VT: {
- readonly stateISO: 'VT';
- readonly stateName: 'Vermont';
- };
- readonly WA: {
- readonly stateISO: 'WA';
- readonly stateName: 'Washington';
- };
- readonly WI: {
- readonly stateISO: 'WI';
- readonly stateName: 'Wisconsin';
- };
- readonly WV: {
- readonly stateISO: 'WV';
- readonly stateName: 'West Virginia';
- };
- readonly WY: {
- readonly stateISO: 'WY';
- readonly stateName: 'Wyoming';
- };
- readonly DC: {
- readonly stateISO: 'DC';
- readonly stateName: 'District Of Columbia';
- };
- };
- /**
- * Store all the regular expression we are using for matching stuff
- */
- readonly REG_EXP: {
- /**
- * Regular expression to check that a domain is valid
- */
- readonly DOMAIN: RegExp;
- /**
- * Regex matching an text containing an email
- */
- readonly EMAIL_PART: "([\\w\\-\\+\\'#]+(?:\\.[\\w\\-\\'\\+]+)*@(?:[\\w\\-]+\\.)+[a-z]{2,})";
- /**
- * Regex matching a text containing general phone number
- */
- readonly GENERAL_PHONE_PART: RegExp;
- /**
- * Regex matching a text containing an E.164 format phone number
- */
- readonly PHONE_PART: '\\+[1-9]\\d{1,14}';
- /**
- * Regular expression to check that a basic name is valid
- */
- readonly FREE_NAME: RegExp;
- /**
- * Regular expression to check that a card is masked
- */
- readonly MASKED_CARD: RegExp;
- /**
- * Regular expression to check that an email is valid
- */
- readonly EMAIL: RegExp;
- /**
- * Regular expression to extract an email from a text
- */
- readonly EXTRACT_EMAIL: RegExp;
- /**
- * Regular expression to search for valid email addresses in a string
- */
- readonly EMAIL_SEARCH: RegExp;
- /**
- * Regular expression to detect if something is a hyperlink
- *
- * Adapted from: https://gist.github.com/dperini/729294
- */
- readonly HYPERLINK: RegExp;
- /**
- * Regex to match valid emails during markdown transformations
- */
- readonly MARKDOWN_EMAIL: "([a-zA-Z0-9.!#$%&'+/=?^`{|}-][a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]*@[a-zA-Z0-9-]+?(\\.[a-zA-Z]+)+)";
- /**
- * Regex matching an text containing an Emoji
- */
- readonly EMOJIS: RegExp;
- /**
- * Regex matching an text containing an Emoji that can be a single emoji or made up by some different emojis
- *
- * @type RegExp
- */
- readonly EMOJI_RULE: RegExp;
- };
- readonly REPORT: {
- /**
- * Limit when we decided to turn off print to pdf and use only the native feature
- */
- readonly LIMIT_PRINT_PDF: 250;
- readonly ACH_LIMIT: 2000000;
- readonly ACH_DEFAULT_DAYS: 4;
- /**
- * This is the string that a user can enter in a formula to refer to the report title field
- */
- readonly TITLE_FORMULA: '{report:title}';
- /**
- * The max time a comment can be made after another to be considered the same comment, in seconds
- */
- readonly MAX_AGE_SAME_COMMENT: 300;
- readonly SMARTREPORT_AGENT_EMAIL: 'smartreports@expensify.com';
- };
- /**
- * Root URLs
- */
- readonly URL: {
- readonly FORUM_ROOT: 'https://community.expensify.com/';
- readonly RECEIPTS: {
- readonly DEVELOPMENT: 'https://www.expensify.com.dev/receipts/';
- readonly STAGING: 'https://staging.expensify.com/receipts/';
- readonly PRODUCTION: 'https://www.expensify.com/receipts/';
- };
- readonly CLOUDFRONT: 'https://d2k5nsl2zxldvw.cloudfront.net';
- readonly CLOUDFRONT_IMG: 'https://d2k5nsl2zxldvw.cloudfront.net/images/';
- readonly CLOUDFRONT_FILES: 'https://d2k5nsl2zxldvw.cloudfront.net/files/';
- readonly EXPENSIFY_SYNC_MANAGER: 'quickbooksdesktop/Expensify_QuickBooksDesktop_Setup_2300802.exe';
- readonly USEDOT_ROOT: 'https://use.expensify.com/';
- readonly ITUNES_SUBSCRIPTION: 'https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/manageSubscriptions';
- };
- readonly DATE: {
- readonly FORMAT_STRING: 'yyyy-MM-dd';
- readonly FORMAT_STRING_PRETTY: 'MMM d, yyyy';
- /**
- * Expensify date format string for moment js
- * usage: moment().format( CONST.DATE.MOMENT_FORMAT_STRING )
- */
- readonly MOMENT_FORMAT_STRING: 'YYYY-MM-DD';
- /**
- * This is a typical format of the date plus the time
- */
- readonly MOMENT_DATE_TIME: 'YYYY-MM-DD HH:mm';
- /**
- * Pretty format used for report history items
- *
- * @example Jun 19, 2019 12:38 PM
- */
- readonly MOMENT_DATE_TIME_PRETTY: 'MMM DD YYYY h:mma';
- /**
- * Date-time format, including timezone information, eg "2015-10-14T19:44:35+07:00"
- */
- readonly MOMENT_DATE_TIME_TIMEZONE: 'YYYY-MM-DDTHH:mm:ssZ';
- /**
- * Moment formatting option for a date of this format "Jul 2, 2014"
- */
- readonly MOMENT_US_DATE: 'MMM D, YYYY';
- /**
- * Moment formatting option for a date of this format "July 2, 2014"
- * ie, full month name
- */
- readonly MOMENT_US_DATE_LONG: 'MMMM D, YYYY';
- /**
- * Moment formatting option for full month name and year as in "July 2015"
- */
- readonly MOMENT_US_MONTH_YEAR_LONG: 'MMMM YYYY';
- /**
- * Difference between the local time and UTC time in ms
- */
- readonly TIMEZONE_OFFSET_MS: number;
- readonly SHORT_MONTH_SHORT_DAY: 'MMM d';
- readonly LONG_YEAR_MONTH_DAY_24_TIME: 'yyyy-MM-dd HH:mm:ss';
- readonly SHORT_MONTH_DAY_LOCAL_TIME: 'MMM D [at] LT';
- readonly SHORT_MONTH_DAY_YEAR_LOCAL_TIME: 'MMM D, YYYY [at] LT';
- };
- /**
- * Message used by the Func.die() exception
- */
- readonly FUNC_DIE_MESSAGE: 'Aborting JavaScript execution';
- /**
- * Default for how long the email delivery failure NVP should be valid (in seconds)
- * Currently 14 days (14 * 24 * 60 * 60)
- *
- * WARNING ! UPDATE THE PHP CONSTANT VERSION WHEN UPDATING THIS ONE
- */
- readonly EMAIL_DELIVERY_FAILURE_VALIDITY: 1209600;
- /**
- * Bill Processing-related constants
- */
- readonly BILL_PROCESSING_PARTNER_NAME: 'expensify.cash';
- readonly BILL_PROCESSING_EMAIL_DOMAIN: 'expensify.cash';
- /**
- * Bank Import Logic Constants
- */
- readonly BANK_IMPORT: {
- readonly BANK_STATUS_BROKEN: 2;
- };
- /**
- * Bank Account Logic Constants
- */
- readonly BANK_ACCOUNT: {
- readonly VERIFICATION_MAX_ATTEMPTS: 7;
- };
- /**
- * Emails that the user shouldn't be interacting with from the front-end interface
- * Trying to add these emails as a delegate, onto a policy, or as an approver is considered invalid
- * Any changes here should be reflected in the PHP constant in web-expensify,
- * which is located in _constant.php and also named EXPENSIFY_EMAILS.
- * And should also be reflected in the constant in expensify/app,
- * which is located in src/CONST.js and also named EXPENSIFY_EMAILS.
- */
- readonly EXPENSIFY_EMAILS: readonly [
- 'concierge@expensify.com',
- 'help@expensify.com',
- 'receipts@expensify.com',
- 'chronos@expensify.com',
- 'qa@expensify.com',
- 'contributors@expensify.com',
- 'firstresponders@expensify.com',
- 'qa+travisreceipts@expensify.com',
- 'bills@expensify.com',
- 'studentambassadors@expensify.com',
- 'accounting@expensify.com',
- 'payroll@expensify.com',
- 'svfg@expensify.com',
- 'integrationtestingcreds@expensify.com',
- 'admin@expensify.com',
- 'notifications@expensify.com',
- ];
- /**
- * Emails that the user shouldn't submit reports to nor share reports with
- * Any changes here should be reflected in the PHP constant,
- * which is located in _constant.php and also named INVALID_APPROVER_AND_SHAREE_EMAILS
- */
- readonly INVALID_APPROVER_AND_SHAREE_EMAILS: readonly [
- 'concierge@expensify.com',
- 'help@expensify.com',
- 'receipts@expensify.com',
- 'chronos@expensify.com',
- 'qa@expensify.com',
- 'contributors@expensify.com',
- 'firstresponders@expensify.com',
- 'qa+travisreceipts@expensify.com',
- 'bills@expensify.com',
- 'admin@expensify.com',
- 'notifications@expensify.com',
- ];
- /**
- * Smart scan-related constants
- */
- readonly SMART_SCAN: {
- readonly COST: 20;
- readonly FREE_NUMBER: 25;
- };
- readonly SMS: {
- readonly DOMAIN: 'expensify.sms';
- readonly E164_REGEX: RegExp;
- };
- readonly PASSWORD_COMPLEXITY_REGEX_STRING: '^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{8,}$';
- readonly INTEGRATIONS: {
- /**
- * Constants that specify how to map (import) Integrations data to Expensify
- * Parallel to IntegrationEntityMappingTypeEnum in the IS
- */
- readonly DATA_MAPPING: {
- readonly NONE: 'NONE';
- readonly TAG: 'TAG';
- readonly REPORT_FIELD: 'REPORT_FIELD';
- readonly DEFAULT: 'DEFAULT';
- };
- readonly EXPORT_DATE: {
- readonly LAST_EXPENSE: 'LAST_EXPENSE';
- readonly REPORT_EXPORTED: 'REPORT_EXPORTED';
- readonly REPORT_SUBMITTED: 'REPORT_SUBMITTED';
- };
- readonly XERO_HQ_CONNECTION_NAME: 'xerohq';
- readonly EXPENSIFY_SYNC_MANAGER_VERSION: '23.0.802.0';
- };
- readonly INTEGRATION_TYPES: {
- readonly ACCOUNTING: 'accounting';
- readonly HR: 'hr';
- };
- readonly DIRECT_INTEGRATIONS: {
- readonly zenefits: {
- readonly value: 'zenefits';
- readonly text: 'Zenefits';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/zenefit.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/zenefit_gray.svg';
- readonly alert_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/zenefit_alert.svg';
- readonly types: readonly ['hr'];
- readonly isCorporateOnly: false;
- };
- readonly gusto: {
- readonly value: 'gusto';
- readonly text: 'Gusto';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/gusto.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/gusto_gray.svg';
- readonly alert_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/gusto_alert.svg';
- readonly types: readonly ['hr'];
- readonly isCorporateOnly: false;
- };
- readonly quickbooksOnline: {
- readonly value: 'quickbooksOnline';
- readonly text: 'QuickBooks Online';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/quickbooks.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/quickbooks_gray.svg';
- readonly alert_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/quickbooks_alert.svg';
- readonly types: readonly ['hr', 'accounting'];
- readonly isCorporateOnly: false;
- };
- readonly xero: {
- readonly value: 'xero';
- readonly text: 'Xero';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/xero.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/xero_gray.svg';
- readonly alert_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/xero_alert.svg';
- readonly types: readonly ['accounting'];
- readonly isCorporateOnly: false;
- };
- readonly netsuite: {
- readonly value: 'netsuite';
- readonly text: 'NetSuite';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/netsuite.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/netsuite_gray.svg';
- readonly alert_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/netsuite_alert.svg';
- readonly types: readonly ['hr', 'accounting'];
- readonly isCorporateOnly: true;
- };
- readonly quickbooksDesktop: {
- readonly value: 'qbd';
- readonly text: 'QuickBooks Desktop';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/quickbooks.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/quickbooks_gray.svg';
- readonly alert_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/quickbooks_alert.svg';
- readonly types: readonly ['accounting'];
- readonly isCorporateOnly: false;
- };
- readonly intacct: {
- readonly value: 'intacct';
- readonly text: 'Sage Intacct';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/sage.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/sage_gray.svg';
- readonly alert_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/sage_alert.svg';
- readonly types: readonly ['hr', 'accounting'];
- readonly isCorporateOnly: true;
- };
- readonly financialforce: {
- readonly value: 'financialforce';
- readonly text: 'Certinia';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/certinia.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/certinia_gray.svg';
- readonly alert_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/certinia_alert.svg';
- readonly types: readonly ['accounting'];
- readonly isCorporateOnly: true;
- };
- };
- readonly INDIRECT_INTEGRATIONS: {
- readonly microsoft_dynamics: {
- readonly value: 'microsoft_dynamics';
- readonly text: 'Microsoft Dynamics';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/microsoft_dynamics.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/microsoft_dynamics_gray.svg';
- readonly types: readonly ['accounting'];
- readonly isCorporateOnly: true;
- };
- readonly oracle: {
- readonly value: 'oracle';
- readonly text: 'Oracle';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/oracle.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/oracle_gray.svg';
- readonly types: readonly ['hr', 'accounting'];
- readonly isCorporateOnly: true;
- };
- readonly sage: {
- readonly value: 'sage';
- readonly text: 'Sage';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/sage.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/sage_gray.svg';
- readonly types: readonly ['accounting'];
- readonly isCorporateOnly: true;
- };
- readonly sap: {
- readonly value: 'sap';
- readonly text: 'SAP';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/sap.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/sap_gray.svg';
- readonly types: readonly ['accounting'];
- readonly isCorporateOnly: true;
- };
- readonly myob: {
- readonly value: 'myob';
- readonly text: 'MYOB';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/myob.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/myob_gray.svg';
- readonly types: readonly ['accounting'];
- readonly isCorporateOnly: true;
- };
- readonly workday: {
- readonly value: 'workday';
- readonly text: 'Workday';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/workday.svg';
- readonly gray_image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/workday_gray.svg';
- readonly types: readonly ['hr'];
- readonly isCorporateOnly: true;
- };
- readonly adp: {
- readonly value: 'adp';
- readonly text: 'ADP';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/export-icons/adp.svg';
- readonly types: readonly ['hr'];
- readonly isCorporateOnly: true;
- };
- readonly generic_indirect_connection: {
- readonly value: 'generic_indirect_connection';
- readonly text: 'Other';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/accounting-other--blue.svg';
- readonly types: readonly ['hr', 'accounting'];
- };
- };
- readonly DEFAULT_IS_TEMPLATES: {
- readonly default: {
- readonly value: 'default_template';
- readonly text: 'Basic Export';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/accounting-other--blue.svg';
- };
- readonly tag: {
- readonly value: 'tag_template';
- readonly text: 'Tag Export';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/accounting-other--blue.svg';
- };
- readonly category: {
- readonly value: 'category_template';
- readonly text: 'Category Export';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/accounting-other--blue.svg';
- };
- readonly detailed: {
- readonly value: 'detailed_export';
- readonly text: 'All Data - Expense Level Export';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/accounting-other--blue.svg';
- };
- readonly report: {
- readonly value: 'report_level_export';
- readonly text: 'All Data - Report Level Export';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/accounting-other--blue.svg';
- };
- readonly tax: {
- readonly value: 'multiple_tax_export';
- readonly text: 'Canadian Multiple Tax Export';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/accounting-other--blue.svg';
- };
- readonly perdiem: {
- readonly value: 'per_diem_export';
- readonly text: 'Per Diem Export';
- readonly image: 'https://d2k5nsl2zxldvw.cloudfront.net/images/icons/accounting-other--blue.svg';
- };
- };
- readonly NVP: {
- readonly DISMISSED_VIOLATIONS: 'dismissedViolations';
- };
- readonly FILESIZE: {
- readonly BYTES_IN_MEGABYTE: 1000000;
- readonly MAX: 10000000;
- };
- readonly PARTNER_NAMES: {
- readonly IPHONE: 'iphone';
- readonly ANDROID: 'android';
- readonly CHAT: 'chat-expensify-com';
- };
- readonly LOGIN_TYPES: {
- readonly WEB: 'login';
- readonly MOBILE: 'device';
- };
- readonly EXPENSIFY_CARD: {
- readonly FEED_NAME: 'Expensify Card';
- readonly FRAUD_STATES: {
- readonly NONE: 0;
- readonly DOMAIN_CARDS_REIMBURSEMENTS_INVESTIGATION: 1;
- readonly DOMAIN_CARDS_RAPID_INCREASE_INVESTIGATION: 2;
- readonly DOMAIN_CARDS_RAPID_INCREASE_CLEARED: 3;
- readonly DOMAIN_CARDS_RAPID_INCREASE_CONFIRMED: 4;
- readonly INDIVIDUAL_CARD_RAPID_INCREASE_INVESTIGATION: 5;
- readonly INDIVIDUAL_CARD_RAPID_INCREASE_CLEARED: 6;
- readonly INDIVIDUAL_CARD_RAPID_INCREASE_CONFIRMED: 7;
- readonly SUSPICIOUS_PAN_ENTRY: 8;
- readonly SUSPICIOUS_PAN_ENTRY_CLEARED: 9;
- readonly SUSPICIOUS_PAN_ENTRY_CONFIRMED: 10;
- };
- };
- readonly TRAVEL_BOOKING: {
- readonly OPTIONS: {
- readonly shortFlightFare: {
- readonly economy: 'Economy';
- readonly premiumEconomy: 'Premium Economy';
- readonly business: 'Business';
- readonly first: 'First';
- };
- readonly longFlightFare: {
- readonly economy: 'Economy';
- readonly premiumEconomy: 'Premium Economy';
- readonly business: 'Business';
- readonly first: 'First';
- };
- readonly hotelStar: {
- readonly oneStar: '1';
- readonly twoStars: '2';
- readonly threeStars: '3';
- readonly fourStars: '4';
- readonly fiveStars: '5';
- };
- };
- readonly DEFAULT_OPTIONS: {
- readonly shortFlightFare: 'economy';
- readonly longFlightFare: 'economy';
- readonly hotelStar: 'fourStars';
- };
- };
- readonly EXPENSIFY_DOMAINS: readonly ['expensify.com', 'expensifail.com', 'expensicorp.com'];
- readonly SUBSCRIPTION_CHANGE_REASONS: {
- readonly TOO_LIMITED: {
- readonly id: 'tooLimited';
- readonly label: 'Functionality needs improvement';
- readonly prompt: 'What software are you migrating to and what led to this decision?';
- };
- readonly TOO_EXPENSIVE: {
- readonly id: 'tooExpensive';
- readonly label: 'Too expensive';
- readonly prompt: 'What software are you migrating to and what led to this decision?';
- };
- readonly INADEQUATE_SUPPORT: {
- readonly id: 'inadequateSupport';
- readonly label: 'Inadequate customer support';
- readonly prompt: 'What software are you migrating to and what led to this decision?';
- };
- readonly BUSINESS_CLOSING: {
- readonly id: 'businessClosing';
- readonly label: 'Company closing, downsizing, or acquired';
- readonly prompt: 'What software are you migrating to and what led to this decision?';
- };
- };
-};
-/**
- * UI Constants
- */
-export declare const UI: {
- readonly ICON: {
- readonly DELETE: 'trashcan';
- readonly CAR: 'car';
- readonly CASH: 'cash';
- readonly MANAGED_CARD: 'corporate-card';
- readonly CARD: 'credit-card';
- readonly CLOCK: 'time';
- readonly PER_DIEM: 'per-diem';
- readonly PENDING_CARD: 'card-transaction-pending';
- readonly CSV_UPLOAD: 'csv-upload';
- readonly PENDING_CREDIT_CARD: 'credit-card-pending';
- };
- readonly spinnerDIV: '
';
- readonly spinnerSmallDIV: '';
- readonly spinnerLargeDIV: '';
- readonly spinnerClass: 'view_spinner';
- readonly SPINNER: 'spinner';
- readonly imageURLPrefix: 'https://d2k5nsl2zxldvw.cloudfront.net/images/';
- readonly ACTIVE: 'active';
- readonly ERROR: 'error';
- readonly HIDDEN: 'hidden';
- readonly INVISIBLE: 'invisible';
- readonly DEPRECIATED: 'depreciated';
- readonly DISABLED: 'disabled';
- readonly REQUIRED: 'required';
- readonly SELECT_DEFAULT: '###';
- readonly SELECTED: 'selected';
- readonly QR_CODE: 'js_qrCode';
- readonly DIALOG_Z_INDEX: 4000;
-};
-export declare const PUBLIC_DOMAINS: readonly [
- 'accountant.com',
- 'afis.ch',
- 'aol.com',
- 'artlover.com',
- 'asia.com',
- 'att.net',
- 'bellsouth.net',
- 'bills.expensify.com',
- 'btinternet.com',
- 'cheerful.com',
- 'chromeexpensify.com',
- 'comcast.net',
- 'consultant.com',
- 'contractor.com',
- 'cox.net',
- 'cpa.com',
- 'cryptohistoryprice.com',
- 'dr.com',
- 'email.com',
- 'engineer.com',
- 'europe.com',
- 'evernote.user',
- 'execs.com',
- 'expensify.cash',
- 'expensify.sms',
- 'gmail.com',
- 'gmail.con',
- 'googlemail.com',
- 'hey.com',
- 'hotmail.co.uk',
- 'hotmail.com',
- 'hotmail.fr',
- 'hotmail.it',
- 'icloud.com',
- 'iname.com',
- 'jeeviess.com',
- 'live.com',
- 'mac.com',
- 'mail.com',
- 'mail.ru',
- 'mailfence.com',
- 'me.com',
- 'msn.com',
- 'musician.org',
- 'myself.com',
- 'outlook.com',
- 'pm.me',
- 'post.com',
- 'privaterelay.appleid.com',
- 'proton.me',
- 'protonmail.ch',
- 'protonmail.com',
- 'qq.com',
- 'rigl.ch',
- 'sasktel.net',
- 'sbcglobal.net',
- 'spacehotline.com',
- 'tafmail.com',
- 'techie.com',
- 'usa.com',
- 'verizon.net',
- 'vomoto.com',
- 'wolfandcranebar.tech',
- 'workmail.com',
- 'writeme.com',
- 'yahoo.ca',
- 'yahoo.co.in',
- 'yahoo.co.uk',
- 'yahoo.com',
- 'yahoo.com.br',
- 'ymail.com',
-];
diff --git a/lib/CONST.jsx b/lib/CONST.ts
similarity index 98%
rename from lib/CONST.jsx
rename to lib/CONST.ts
index 7991d1e2..7e112e4a 100644
--- a/lib/CONST.jsx
+++ b/lib/CONST.ts
@@ -8,14 +8,14 @@ const MOMENT_FORMAT_STRING = 'YYYY-MM-DD';
/**
* URL of our CloudFront Instance
*/
-export const g_cloudFront = 'https://d2k5nsl2zxldvw.cloudfront.net';
+const g_cloudFront = 'https://d2k5nsl2zxldvw.cloudfront.net';
/**
* URL of our image CDN
*/
-export const g_cloudFrontImg = `${g_cloudFront}/images/`;
+const g_cloudFrontImg = `${g_cloudFront}/images/`;
-export const CONST = {
+const CONST = {
CORPAY_DIRECT_REIMBURSEMENT_CURRENCIES: ['USD', 'GBP', 'EUR', 'AUD', 'CAD'],
/**
@@ -361,6 +361,7 @@ export const CONST = {
*
* @type RegExp
*/
+ // eslint-disable-next-line no-misleading-character-class
EMOJIS: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu,
/**
@@ -884,12 +885,12 @@ export const CONST = {
prompt: 'What software are you migrating to and what led to this decision?',
},
},
-};
+} as const;
/**
* UI Constants
*/
-export const UI = {
+const UI = {
ICON: {
DELETE: 'trashcan',
CAR: 'car',
@@ -923,10 +924,10 @@ export const UI = {
// Base z-index for dialogs $zindex-dialog in _vars.scss should take it's value from here!
DIALOG_Z_INDEX: 4000,
-};
+} as const;
// List of most frequently used public domains
-export const PUBLIC_DOMAINS = [
+const PUBLIC_DOMAINS = [
'accountant.com',
'afis.ch',
'aol.com',
@@ -998,4 +999,6 @@ export const PUBLIC_DOMAINS = [
'yahoo.com',
'yahoo.com.br',
'ymail.com',
-];
+] as const;
+
+export {g_cloudFront, g_cloudFrontImg, CONST, UI, PUBLIC_DOMAINS};
diff --git a/lib/Cookie.jsx b/lib/Cookie.jsx
index 8dad1345..d2ae6f3c 100644
--- a/lib/Cookie.jsx
+++ b/lib/Cookie.jsx
@@ -58,7 +58,7 @@ function set(name, value, expiredays) {
// Get expiry date, set
const exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
- document.cookie = `${name}=${encodeURIComponent(value)}` + `${expiredays === null ? '' : `;expires=${exdate.toUTCString()}`}`;
+ document.cookie = `${name}=${encodeURIComponent(value)}${expiredays === null ? '' : `;expires=${exdate.toUTCString()}`}`;
}
/**
diff --git a/lib/CredentialsWrapper.jsx b/lib/CredentialsWrapper.jsx
index b6283c07..90fe7759 100644
--- a/lib/CredentialsWrapper.jsx
+++ b/lib/CredentialsWrapper.jsx
@@ -1,6 +1,6 @@
import localForage from 'localforage';
-export const LOGIN_PARTNER_DETAILS = {
+const LOGIN_PARTNER_DETAILS = {
CREDENTIALS_KEY: 'DEVICE_SESSION_CREDENTIALS',
EXPENSIFY_PARTNER_PREFIX: 'expensify.',
PARTNER_NAME: 'chat-expensify-com',
@@ -33,6 +33,7 @@ const CredentialWrapper = {
*/
setCredentials(credentials) {
if (!credentials.partnerUserID || !credentials.partnerUserSecret) {
+ // eslint-disable-next-line prefer-promise-reject-errors
return Promise.reject('Invalid credential pair');
}
@@ -48,3 +49,4 @@ const CredentialWrapper = {
};
export default CredentialWrapper;
+export {LOGIN_PARTNER_DETAILS};
diff --git a/lib/Device.d.ts b/lib/Device.d.ts
deleted file mode 100644
index 6cb8abd3..00000000
--- a/lib/Device.d.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-declare function getOSAndName(): {
- os: string | undefined;
- osVersion: string | undefined;
- deviceName: string | undefined;
- deviceVersion: string | undefined;
-};
-export {getOSAndName};
diff --git a/lib/Device.jsx b/lib/Device.ts
similarity index 65%
rename from lib/Device.jsx
rename to lib/Device.ts
index 43419dba..1100cb45 100644
--- a/lib/Device.jsx
+++ b/lib/Device.ts
@@ -1,6 +1,13 @@
import {UAParser} from 'ua-parser-js';
-function getOSAndName() {
+type DeviceInfo = {
+ os: string | undefined;
+ osVersion: string | undefined;
+ deviceName: string | undefined;
+ deviceVersion: string | undefined;
+};
+
+function getOSAndName(): DeviceInfo {
const parser = new UAParser();
const result = parser.getResult();
return {
diff --git a/lib/ExpenseRule.jsx b/lib/ExpenseRule.jsx
index 5d614932..03c66be3 100644
--- a/lib/ExpenseRule.jsx
+++ b/lib/ExpenseRule.jsx
@@ -21,11 +21,7 @@ export default class ExpenseRule {
* @return {Object}
*/
getApplyWhenByField(field) {
- return (
- _.find(this.applyWhen, (conditions) => {
- return conditions.field === field;
- }) || {}
- );
+ return _.find(this.applyWhen, (conditions) => conditions.field === field) || {};
}
/**
diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js
index 21f7081b..194b6b05 100644
--- a/lib/ExpensiMark.js
+++ b/lib/ExpensiMark.js
@@ -178,7 +178,7 @@ export default class ExpensiMark {
{
name: 'reportMentions',
- regex: /(?$1',
},
diff --git a/lib/Log.jsx b/lib/Log.jsx
index ba0ca1b1..b114979b 100644
--- a/lib/Log.jsx
+++ b/lib/Log.jsx
@@ -1,3 +1,4 @@
+/* eslint-disable no-console */
import _ from 'underscore';
import API from './API';
import Network from './Network';
diff --git a/lib/Logger.d.ts b/lib/Logger.d.ts
deleted file mode 100644
index f2b6995e..00000000
--- a/lib/Logger.d.ts
+++ /dev/null
@@ -1,63 +0,0 @@
-declare type Parameters = string | Record | Array>;
-declare type ServerLoggingCallbackOptions = {api_setCookie: boolean; logPacket: string};
-declare type ServerLoggingCallback = (logger: Logger, options: ServerLoggingCallbackOptions) => Promise<{requestID: string}> | undefined;
-declare type ClientLoggingCallBack = (message: string) => void;
-declare type LogLine = {message: string; parameters: Parameters; onlyFlushWithOthers: boolean; timestamp: Date};
-export default class Logger {
- logLines: LogLine[];
- serverLoggingCallback: ServerLoggingCallback;
- clientLoggingCallback: ClientLoggingCallBack;
- isDebug: boolean;
- constructor({serverLoggingCallback, isDebug, clientLoggingCallback}: {serverLoggingCallback: ServerLoggingCallback; isDebug: boolean; clientLoggingCallback: ClientLoggingCallBack});
- /**
- * Ask the server to write the log message
- */
- logToServer(): void;
- /**
- * Add a message to the list
- * @param message
- * @param parameters The parameters associated with the message
- * @param forceFlushToServer Should we force flushing all logs to server?
- * @param onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
- */
- add(message: string, parameters: Parameters, forceFlushToServer: boolean, onlyFlushWithOthers?: boolean): void;
- /**
- * Caches an informational message locally, to be sent to the server if
- * needed later.
- *
- * @param message The message to log.
- * @param sendNow if true, the message will be sent right away.
- * @param parameters The parameters to send along with the message
- * @param onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
- */
- info(message: string, sendNow?: boolean, parameters?: Parameters, onlyFlushWithOthers?: boolean): void;
- /**
- * Logs an alert.
- *
- * @param message The message to alert.
- * @param parameters The parameters to send along with the message
- * @param includeStackTrace Must be disabled for testing
- */
- alert(message: string, parameters?: Parameters, includeStackTrace?: boolean): void;
- /**
- * Logs a warn.
- *
- * @param message The message to warn.
- * @param parameters The parameters to send along with the message
- */
- warn(message: string, parameters?: Parameters): void;
- /**
- * Logs a hmmm.
- *
- * @param message The message to hmmm.
- * @param parameters The parameters to send along with the message
- */
- hmmm(message: string, parameters?: Parameters): void;
- /**
- * Logs a message in the browser console.
- *
- * @param message The message to log.
- */
- client(message: string): void;
-}
-export {};
diff --git a/lib/Logger.jsx b/lib/Logger.ts
similarity index 51%
rename from lib/Logger.jsx
rename to lib/Logger.ts
index d1e8180b..90d70b9a 100644
--- a/lib/Logger.jsx
+++ b/lib/Logger.ts
@@ -1,8 +1,22 @@
-import _ from 'underscore';
+type Parameters = string | Record | Array> | Error;
+type ServerLoggingCallbackOptions = {api_setCookie: boolean; logPacket: string};
+type ServerLoggingCallback = (logger: Logger, options: ServerLoggingCallbackOptions) => Promise<{requestID: string}> | undefined;
+type ClientLoggingCallBack = (message: string) => void;
+type LogLine = {message: string; parameters: Parameters; onlyFlushWithOthers?: boolean; timestamp: Date};
+type LoggerOptions = {serverLoggingCallback: ServerLoggingCallback; isDebug: boolean; clientLoggingCallback: ClientLoggingCallBack};
const MAX_LOG_LINES_BEFORE_FLUSH = 50;
+
export default class Logger {
- constructor({serverLoggingCallback, isDebug, clientLoggingCallback}) {
+ logLines: LogLine[];
+
+ serverLoggingCallback: ServerLoggingCallback;
+
+ clientLoggingCallback: ClientLoggingCallBack;
+
+ isDebug: boolean;
+
+ constructor({serverLoggingCallback, isDebug, clientLoggingCallback}: LoggerOptions) {
// An array of log lines that limits itself to a certain number of entries (deleting the oldest)
this.logLines = [];
this.serverLoggingCallback = serverLoggingCallback;
@@ -10,26 +24,25 @@ export default class Logger {
this.isDebug = isDebug;
// Public Methods
- return {
- info: this.info.bind(this),
- alert: this.alert.bind(this),
- warn: this.warn.bind(this),
- hmmm: this.hmmm.bind(this),
- client: this.client.bind(this),
- };
+ this.info = this.info.bind(this);
+ this.alert = this.alert.bind(this);
+ this.warn = this.warn.bind(this);
+ this.hmmm = this.hmmm.bind(this);
+ this.client = this.client.bind(this);
}
/**
* Ask the server to write the log message
*/
- logToServer() {
+ logToServer(): void {
// We do not want to call the server with an empty list or if all the lines has onlyFlushWithOthers=true
- if (!this.logLines.length || _.all(this.logLines, (l) => l.onlyFlushWithOthers)) {
+ if (!this.logLines.length || this.logLines?.every((l) => l.onlyFlushWithOthers)) {
return;
}
// We don't care about log setting web cookies so let's define it as false
- const linesToLog = _.map(this.logLines, (l) => {
+ const linesToLog = this.logLines?.map((l) => {
+ // eslint-disable-next-line no-param-reassign
delete l.onlyFlushWithOthers;
return l;
});
@@ -38,6 +51,7 @@ export default class Logger {
if (!promise) {
return;
}
+ // eslint-disable-next-line rulesdir/prefer-early-return
promise.then((response) => {
if (response.requestID) {
this.info('Previous log requestID', false, {requestID: response.requestID}, true);
@@ -47,12 +61,11 @@ export default class Logger {
/**
* Add a message to the list
- * @param {String} message
- * @param {Object|String} parameters The parameters associated with the message
- * @param {Boolean} forceFlushToServer Should we force flushing all logs to server?
- * @param {Boolean} onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
+ * @param parameters The parameters associated with the message
+ * @param forceFlushToServer Should we force flushing all logs to server?
+ * @param onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
*/
- add(message, parameters, forceFlushToServer, onlyFlushWithOthers = false) {
+ add(message: string, parameters: Parameters, forceFlushToServer: boolean, onlyFlushWithOthers = false) {
const length = this.logLines.push({
message,
parameters,
@@ -74,12 +87,12 @@ export default class Logger {
* Caches an informational message locally, to be sent to the server if
* needed later.
*
- * @param {String} message The message to log.
- * @param {Boolean} sendNow if true, the message will be sent right away.
- * @param {Object|String} parameters The parameters to send along with the message
- * @param {Boolean} onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
+ * @param message The message to log.
+ * @param sendNow if true, the message will be sent right away.
+ * @param parameters The parameters to send along with the message
+ * @param onlyFlushWithOthers A request will never be sent to the server if all loglines have this set to true
*/
- info(message, sendNow = false, parameters = '', onlyFlushWithOthers = false) {
+ info(message: string, sendNow = false, parameters: Parameters = '', onlyFlushWithOthers = false) {
const msg = `[info] ${message}`;
this.add(msg, parameters, sendNow, onlyFlushWithOthers);
}
@@ -87,15 +100,15 @@ export default class Logger {
/**
* Logs an alert.
*
- * @param {String} message The message to alert.
- * @param {Object|String} parameters The parameters to send along with the message
- * @param {Boolean} includeStackTrace Must be disabled for testing
+ * @param message The message to alert.
+ * @param parameters The parameters to send along with the message
+ * @param includeStackTrace Must be disabled for testing
*/
- alert(message, parameters = {}, includeStackTrace = true) {
+ alert(message: string, parameters: Parameters = {}, includeStackTrace = true) {
const msg = `[alrt] ${message}`;
const params = parameters;
- if (includeStackTrace) {
+ if (includeStackTrace && typeof params === 'object' && !Array.isArray(params)) {
params.stack = JSON.stringify(new Error().stack);
}
@@ -108,7 +121,7 @@ export default class Logger {
* @param {String} message The message to warn.
* @param {Object|String} parameters The parameters to send along with the message
*/
- warn(message, parameters = '') {
+ warn(message: string, parameters: Parameters = '') {
const msg = `[warn] ${message}`;
this.add(msg, parameters, true);
}
@@ -116,10 +129,10 @@ export default class Logger {
/**
* Logs a hmmm.
*
- * @param {String} message The message to hmmm.
- * @param {Object|String} parameters The parameters to send along with the message
+ * @param message The message to hmmm.
+ * @param parameters The parameters to send along with the message
*/
- hmmm(message, parameters = '') {
+ hmmm(message: string, parameters: Parameters = '') {
const msg = `[hmmm] ${message}`;
this.add(msg, parameters, false);
}
@@ -127,9 +140,9 @@ export default class Logger {
/**
* Logs a message in the browser console.
*
- * @param {String} message The message to log.
+ * @param message The message to log.
*/
- client(message) {
+ client(message: string) {
if (!this.clientLoggingCallback) {
return;
}
diff --git a/lib/Network.jsx b/lib/Network.jsx
index ee388da0..96897136 100644
--- a/lib/Network.jsx
+++ b/lib/Network.jsx
@@ -64,6 +64,7 @@ export default function Network(endpoint) {
if (isNewURLFormat) {
// Remove command from parameters and use it in the URL
const command = parameters.command;
+ // eslint-disable-next-line no-param-reassign
delete parameters.command;
newURL = `${endpoint}${command}`;
}
diff --git a/lib/ReportHistoryStore.jsx b/lib/ReportHistoryStore.jsx
index 6cabca88..c8acae97 100644
--- a/lib/ReportHistoryStore.jsx
+++ b/lib/ReportHistoryStore.jsx
@@ -263,9 +263,6 @@ export default class ReportHistoryStore {
delete this.cache[reportID];
}
- // We'll poll the API for the un-cached history
- const cachedHistory = this.cache[reportID] || [];
-
this.API.Report_GetHistory({
reportID,
})
diff --git a/lib/Templates.jsx b/lib/Templates.jsx
index 5f2c3878..e5e21fe8 100644
--- a/lib/Templates.jsx
+++ b/lib/Templates.jsx
@@ -1,3 +1,4 @@
+/* eslint-disable max-classes-per-file */
import _ from 'underscore';
import $ from 'jquery';
@@ -67,6 +68,7 @@ export default (function () {
get(data = {}) {
// Add the "template" object to the parameter to allow nested templates
const dataToCompile = {...data};
+ // eslint-disable-next-line no-undef
dataToCompile.nestedTemplate = Templates.get;
if (!this.compiled) {
this.compiled = _.template($(`#${this.id}`).html());
@@ -119,22 +121,18 @@ export default (function () {
* @return {String}
*/
get(templatePath, data = {}) {
- try {
- const template = getTemplate(templatePath);
- if (_.isUndefined(template)) {
- throw Error(`Template '${templatePath}' is not defined`);
- }
-
- // Check for the absense of get which means someone is likely using
- // the templating engine wrong and trying to access a template namespace
- if (!{}.propertyIsEnumerable.call(template, 'get')) {
- throw Error(`'${templatePath}' is not a valid template path`);
- }
+ const template = getTemplate(templatePath);
+ if (_.isUndefined(template)) {
+ throw Error(`Template '${templatePath}' is not defined`);
+ }
- return template.get(data);
- } catch (err) {
- throw err;
+ // Check for the absense of get which means someone is likely using
+ // the templating engine wrong and trying to access a template namespace
+ if (!{}.propertyIsEnumerable.call(template, 'get')) {
+ throw Error(`'${templatePath}' is not a valid template path`);
}
+
+ return template.get(data);
},
/**
@@ -151,6 +149,7 @@ export default (function () {
*/
init() {
// Read the DOM to find all the templates, and make them available to the code
+ // eslint-disable-next-line rulesdir/prefer-underscore-method
$('.js_template').each((__, $el) => {
const namespaceElements = $el.id.split('_');
const id = namespaceElements.pop();
diff --git a/lib/components/form/element/onOffSwitch.jsx b/lib/components/form/element/onOffSwitch.jsx
index b3a4da29..72780595 100644
--- a/lib/components/form/element/onOffSwitch.jsx
+++ b/lib/components/form/element/onOffSwitch.jsx
@@ -19,6 +19,7 @@ const propTypes = {
labelOnRight: PropTypes.bool,
// Classes of the label
+ // eslint-disable-next-line react/forbid-prop-types
labelClasses: PropTypes.any,
// True if the switch is on
@@ -176,6 +177,7 @@ class OnOffSwitch extends Component {
descriptionElm = (
);
diff --git a/lib/fastMerge.d.ts b/lib/fastMerge.d.ts
deleted file mode 100644
index 4355619f..00000000
--- a/lib/fastMerge.d.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Merges two objects and removes null values if "shouldRemoveNullObjectValues" is set to true
- *
- * We generally want to remove null values from objects written to disk and cache, because it decreases the amount of data stored in memory and on disk.
- * On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
- * To be consistent with the behaviour for merge, we'll also want to remove null values for "set" operations.
- */
-declare function fastMerge(target: T, source: T, shouldRemoveNullObjectValues: boolean): T;
-
-export default fastMerge;
diff --git a/lib/fastMerge.js b/lib/fastMerge.js
deleted file mode 100644
index 57352cff..00000000
--- a/lib/fastMerge.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import _ from 'underscore';
-
-// Mostly copied from https://medium.com/@lubaka.a/how-to-remove-lodash-performance-improvement-b306669ad0e1
-
-/**
- * @param {mixed} val
- * @returns {boolean}
- */
-function isMergeableObject(val) {
- const nonNullObject = val != null ? typeof val === 'object' : false;
- return nonNullObject && Object.prototype.toString.call(val) !== '[object RegExp]' && Object.prototype.toString.call(val) !== '[object Date]' && !_.isArray(val);
-}
-
-/**
- * @param {Object} target
- * @param {Object} source
- * @param {Boolean} shouldRemoveNullObjectValues
- * @returns {Object}
- */
-function mergeObject(target, source, shouldRemoveNullObjectValues = true) {
- const destination = {};
- if (isMergeableObject(target)) {
- // lodash adds a small overhead so we don't use it here
- const targetKeys = _.keys(target);
- for (let i = 0; i < targetKeys.length; ++i) {
- const key = targetKeys[i];
-
- // If shouldRemoveNullObjectValues is true, we want to remove null values from the merged object
- const isSourceOrTargetNull = target[key] === null || source[key] === null;
- const shouldOmitSourceKey = shouldRemoveNullObjectValues && isSourceOrTargetNull;
-
- if (!shouldOmitSourceKey) {
- destination[key] = target[key];
- }
- }
- }
-
- // lodash adds a small overhead so we don't use it here
- const sourceKeys = _.keys(source);
- for (let i = 0; i < sourceKeys.length; ++i) {
- const key = sourceKeys[i];
-
- // If shouldRemoveNullObjectValues is true, we want to remove null values from the merged object
- const shouldOmitSourceKey = shouldRemoveNullObjectValues && source[key] === null;
-
- // If we pass undefined as the updated value for a key, we want to generally ignore it
- const isSourceKeyUndefined = source[key] === undefined;
-
- if (!isSourceKeyUndefined && !shouldOmitSourceKey) {
- const isSourceKeyMergable = isMergeableObject(source[key]);
-
- if (isSourceKeyMergable && target[key]) {
- if (!shouldRemoveNullObjectValues || isSourceKeyMergable) {
- // eslint-disable-next-line no-use-before-define
- destination[key] = fastMerge(target[key], source[key], shouldRemoveNullObjectValues);
- }
- } else if (!shouldRemoveNullObjectValues || source[key] !== null) {
- destination[key] = source[key];
- }
- }
- }
-
- return destination;
-}
-
-/**
- * Merges two objects and removes null values if "shouldRemoveNullObjectValues" is set to true
- *
- * We generally want to remove null values from objects written to disk and cache, because it decreases the amount of data stored in memory and on disk.
- * On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
- * To be consistent with the behaviour for merge, we'll also want to remove null values for "set" operations.
- *
- * @param {Object|Array} target
- * @param {Object|Array} source
- * @param {Boolean} shouldRemoveNullObjectValues
- * @returns {Object|Array}
- */
-function fastMerge(target, source, shouldRemoveNullObjectValues = true) {
- // We have to ignore arrays and nullish values here,
- // otherwise "mergeObject" will throw an error,
- // because it expects an object as "source"
- if (_.isArray(source) || source === null || source === undefined) {
- return source;
- }
- return mergeObject(target, source, shouldRemoveNullObjectValues);
-}
-
-export default fastMerge;
diff --git a/lib/fastMerge.ts b/lib/fastMerge.ts
new file mode 100644
index 00000000..a7ce03bd
--- /dev/null
+++ b/lib/fastMerge.ts
@@ -0,0 +1,88 @@
+/* eslint-disable @typescript-eslint/prefer-for-of */
+
+// Mostly copied from https://medium.com/@lubaka.a/how-to-remove-lodash-performance-improvement-b306669ad0e1
+
+/**
+ * Checks whether the given value can be merged. It has to be an object, but not an array, RegExp or Date.
+ */
+function isMergeableObject(value: unknown): value is Record {
+ const nonNullObject = value != null ? typeof value === 'object' : false;
+ return nonNullObject && Object.prototype.toString.call(value) !== '[object RegExp]' && Object.prototype.toString.call(value) !== '[object Date]' && !Array.isArray(value);
+}
+
+/**
+ * Merges the source object into the target object.
+ * @param target - The target object.
+ * @param source - The source object.
+ * @param shouldRemoveNestedNulls - If true, null object values will be removed.
+ * @returns - The merged object.
+ */
+function mergeObject>(target: TObject, source: TObject, shouldRemoveNullObjectValues = true): TObject {
+ const destination: Record = {};
+
+ if (isMergeableObject(target)) {
+ // lodash adds a small overhead so we don't use it here
+ const targetKeys = Object.keys(target);
+ for (let i = 0; i < targetKeys.length; ++i) {
+ const key = targetKeys[i];
+ const sourceValue = source?.[key];
+ const targetValue = target?.[key];
+
+ // If shouldRemoveNullObjectValues is true, we want to remove null values from the merged object
+ const isSourceOrTargetNull = targetValue === null || sourceValue === null;
+ const shouldOmitSourceKey = shouldRemoveNullObjectValues && isSourceOrTargetNull;
+
+ if (!shouldOmitSourceKey) {
+ destination[key] = targetValue;
+ }
+ }
+ }
+
+ // lodash adds a small overhead so we don't use it here
+ const sourceKeys = Object.keys(source);
+ for (let i = 0; i < sourceKeys.length; ++i) {
+ const key = sourceKeys[i];
+ const sourceValue = source?.[key];
+ const targetValue = target?.[key];
+
+ // If shouldRemoveNullObjectValues is true, we want to remove null values from the merged object
+ const shouldOmitSourceKey = shouldRemoveNullObjectValues && sourceValue === null;
+
+ // If we pass undefined as the updated value for a key, we want to generally ignore it
+ const isSourceKeyUndefined = sourceValue === undefined;
+
+ if (!isSourceKeyUndefined && !shouldOmitSourceKey) {
+ const isSourceKeyMergable = isMergeableObject(sourceValue);
+
+ if (isSourceKeyMergable && targetValue) {
+ if (!shouldRemoveNullObjectValues || isSourceKeyMergable) {
+ // eslint-disable-next-line no-use-before-define
+ destination[key] = fastMerge(targetValue as TObject, sourceValue, shouldRemoveNullObjectValues);
+ }
+ } else if (!shouldRemoveNullObjectValues || sourceValue !== null) {
+ destination[key] = sourceValue;
+ }
+ }
+ }
+
+ return destination as TObject;
+}
+
+/**
+ * Merges two objects and removes null values if "shouldRemoveNullObjectValues" is set to true
+ *
+ * We generally want to remove null values from objects written to disk and cache, because it decreases the amount of data stored in memory and on disk.
+ * On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
+ * To be consistent with the behaviour for merge, we'll also want to remove null values for "set" operations.
+ */
+function fastMerge(target: TObject, source: TObject, shouldRemoveNullObjectValues = true): TObject {
+ // We have to ignore arrays and nullish values here,
+ // otherwise "mergeObject" will throw an error,
+ // because it expects an object as "source"
+ if (Array.isArray(source) || source === null || source === undefined) {
+ return source;
+ }
+ return mergeObject(target as Record, source as Record, shouldRemoveNullObjectValues) as TObject;
+}
+
+export default fastMerge;
diff --git a/lib/index.ts b/lib/index.ts
new file mode 100644
index 00000000..72d34ee4
--- /dev/null
+++ b/lib/index.ts
@@ -0,0 +1,21 @@
+// eslint-disable-next-line rulesdir/no-api-in-views
+export {default as API} from './API';
+export {default as APIDeferred} from './APIDeferred';
+export {default as BrowserDetect} from './BrowserDetect';
+export {g_cloudFront, g_cloudFrontImg, CONST, UI, PUBLIC_DOMAINS} from './CONST';
+
+export {default as Cookie} from './Cookie';
+export {default as CredentialsWrapper, LOGIN_PARTNER_DETAILS} from './CredentialsWrapper';
+export * as Device from './Device';
+export {default as ExpensiMark} from './ExpensiMark';
+export {default as Logger} from './Logger';
+export {default as Network} from './Network';
+export {default as Num} from './Num';
+export {default as PageEvent} from './PageEvent';
+export {default as PubSub} from './PubSub';
+export {default as ReportHistoryStore} from './ReportHistoryStore';
+export {default as Templates} from './Templates';
+export {default as Url} from './Url';
+export {default as fastMerge} from './fastMerge';
+export {default as Str} from './str';
+export {default as TLD_REGEX} from './tlds';
diff --git a/package-lock.json b/package-lock.json
index 0076e0ef..8c8c3f38 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,16 +1,17 @@
{
"name": "expensify-common",
- "version": "1.0.0",
+ "version": "2.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "expensify-common",
- "version": "1.0.0",
+ "version": "2.0.0",
"license": "MIT",
"dependencies": {
"classnames": "2.5.0",
"clipboard": "2.0.11",
+ "eslint-plugin-you-dont-need-lodash-underscore": "^6.14.0",
"html-entities": "^2.5.2",
"jquery": "3.6.0",
"localforage": "^1.10.0",
@@ -25,20 +26,28 @@
},
"devDependencies": {
"@babel/preset-env": "^7.24.4",
+ "@babel/preset-typescript": "^7.24.1",
"@lwc/eslint-plugin-lwc": "^1.8.0",
+ "@types/jest": "^29.5.12",
+ "@types/react-dom": "^18.3.0",
+ "@types/ua-parser-js": "^0.7.39",
+ "@typescript-eslint/eslint-plugin": "^7.9.0",
+ "@typescript-eslint/parser": "^7.9.0",
"babel-jest": "^29.0.0",
"babelify": "10.0.0",
- "eslint": "^7.15.0",
+ "eslint": "^8.57.0",
"eslint-config-expensify": "^2.0.48",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-jest": "^24.7.0",
+ "eslint-plugin-prettier": "^5.1.3",
"grunt": "1.6.1",
"grunt-chokidar": "1.0.2",
"grunt-eslint": "25.0.0",
"jest": "^29.0.0",
"jest-environment-jsdom": "^29.7.0",
"jit-grunt": "^0.10.0",
- "prettier": "^3.2.5"
+ "prettier": "^3.2.5",
+ "typescript": "^5.4.5"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -243,19 +252,19 @@
"dev": true
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.24.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz",
- "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==",
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz",
+ "integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
- "@babel/helper-member-expression-to-functions": "^7.23.0",
+ "@babel/helper-member-expression-to-functions": "^7.24.5",
"@babel/helper-optimise-call-expression": "^7.22.5",
"@babel/helper-replace-supers": "^7.24.1",
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
- "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-split-export-declaration": "^7.24.5",
"semver": "^6.3.1"
},
"engines": {
@@ -351,12 +360,12 @@
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.23.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz",
- "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==",
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz",
+ "integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.23.0"
+ "@babel/types": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
@@ -406,9 +415,9 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.24.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz",
- "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==",
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz",
+ "integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==",
"dev": true,
"engines": {
"node": ">=6.9.0"
@@ -473,30 +482,30 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
- "version": "7.22.6",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
- "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz",
+ "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==",
"dev": true,
"dependencies": {
- "@babel/types": "^7.22.5"
+ "@babel/types": "^7.24.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
- "version": "7.23.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
- "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz",
+ "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
- "version": "7.22.20",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
- "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz",
+ "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==",
"dev": true,
"engines": {
"node": ">=6.9.0"
@@ -771,12 +780,12 @@
}
},
"node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.23.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz",
- "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==",
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz",
+ "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
+ "@babel/helper-plugin-utils": "^7.24.0"
},
"engines": {
"node": ">=6.9.0"
@@ -888,12 +897,12 @@
}
},
"node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.23.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz",
- "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==",
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz",
+ "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==",
"dev": true,
"dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
+ "@babel/helper-plugin-utils": "^7.24.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1626,6 +1635,24 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.5.tgz",
+ "integrity": "sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.22.5",
+ "@babel/helper-create-class-features-plugin": "^7.24.5",
+ "@babel/helper-plugin-utils": "^7.24.5",
+ "@babel/plugin-syntax-typescript": "^7.24.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-transform-unicode-escapes": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz",
@@ -1807,6 +1834,25 @@
"@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
}
},
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz",
+ "integrity": "sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.24.0",
+ "@babel/helper-validator-option": "^7.23.5",
+ "@babel/plugin-syntax-jsx": "^7.24.1",
+ "@babel/plugin-transform-modules-commonjs": "^7.24.1",
+ "@babel/plugin-transform-typescript": "^7.24.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/regjsgen": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz",
@@ -1861,13 +1907,13 @@
}
},
"node_modules/@babel/types": {
- "version": "7.24.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz",
- "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==",
+ "version": "7.24.5",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz",
+ "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==",
"dev": true,
"dependencies": {
- "@babel/helper-string-parser": "^7.23.4",
- "@babel/helper-validator-identifier": "^7.22.20",
+ "@babel/helper-string-parser": "^7.24.1",
+ "@babel/helper-validator-identifier": "^7.24.5",
"to-fast-properties": "^2.0.0"
},
"engines": {
@@ -1951,18 +1997,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/@eslint/eslintrc/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/@eslint/js": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.0.0.tgz",
@@ -2808,18 +2842,6 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/@lwc/eslint-plugin-lwc/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
"version": "5.1.1-v1",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
@@ -2865,6 +2887,18 @@
"node": ">= 8"
}
},
+ "node_modules/@pkgr/core": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+ "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
+ }
+ },
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@@ -2972,6 +3006,16 @@
"@types/istanbul-lib-report": "*"
}
},
+ "node_modules/@types/jest": {
+ "version": "29.5.12",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz",
+ "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
"node_modules/@types/jsdom": {
"version": "20.0.1",
"resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-20.0.1.tgz",
@@ -3004,6 +3048,31 @@
"undici-types": "~5.26.4"
}
},
+ "node_modules/@types/prop-types": {
+ "version": "15.7.12",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
+ "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
+ "dev": true
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.2",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.2.tgz",
+ "integrity": "sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==",
+ "dev": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.0",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz",
+ "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
@@ -3016,6 +3085,12 @@
"integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
"dev": true
},
+ "node_modules/@types/ua-parser-js": {
+ "version": "0.7.39",
+ "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.39.tgz",
+ "integrity": "sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg==",
+ "dev": true
+ },
"node_modules/@types/yargs": {
"version": "17.0.32",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz",
@@ -3031,6 +3106,107 @@
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
"dev": true
},
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz",
+ "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "7.9.0",
+ "@typescript-eslint/type-utils": "7.9.0",
+ "@typescript-eslint/utils": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.3.1",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^7.0.0",
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz",
+ "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz",
+ "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz",
+ "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
"node_modules/@typescript-eslint/experimental-utils": {
"version": "4.16.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.16.1.tgz",
@@ -3055,52 +3231,81 @@
"eslint": "*"
}
},
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "4.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz",
- "integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==",
+ "node_modules/@typescript-eslint/parser": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz",
+ "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "4.16.1",
- "@typescript-eslint/visitor-keys": "4.16.1"
+ "@typescript-eslint/scope-manager": "7.9.0",
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/typescript-estree": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0",
+ "debug": "^4.3.4"
},
"engines": {
- "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ "node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
}
},
- "node_modules/@typescript-eslint/types": {
- "version": "4.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz",
- "integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==",
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz",
+ "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==",
"dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0"
+ },
"engines": {
- "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ "node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "4.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz",
- "integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==",
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz",
+ "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz",
+ "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "4.16.1",
- "@typescript-eslint/visitor-keys": "4.16.1",
- "debug": "^4.1.1",
- "globby": "^11.0.1",
- "is-glob": "^4.0.1",
- "semver": "^7.3.2",
- "tsutils": "^3.17.1"
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
@@ -3112,65 +3317,435 @@
}
}
},
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "4.16.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz",
- "integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==",
+ "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz",
+ "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "4.16.1",
- "eslint-visitor-keys": "^2.0.0"
+ "@typescript-eslint/types": "7.9.0",
+ "eslint-visitor-keys": "^3.4.3"
},
"engines": {
- "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ "node": "^18.18.0 || >=20.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
- "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
- "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+ "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
- "engines": {
- "node": ">=10"
+ "dependencies": {
+ "balanced-match": "^1.0.0"
}
},
- "node_modules/abab": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
- "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
- "deprecated": "Use your platform's native atob() and btoa() methods instead",
- "dev": true
- },
- "node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
- "dev": true
- },
- "node_modules/acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "node_modules/@typescript-eslint/parser/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
"engines": {
- "node": ">=0.4.0"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/acorn-globals": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
- "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
+ "node_modules/@typescript-eslint/parser/node_modules/minimatch": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+ "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
"dev": true,
"dependencies": {
- "acorn": "^8.1.0",
- "acorn-walk": "^8.0.2"
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "4.16.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.16.1.tgz",
+ "integrity": "sha512-6IlZv9JaurqV0jkEg923cV49aAn8V6+1H1DRfhRcvZUrptQ+UtSKHb5kwTayzOYTJJ/RsYZdcvhOEKiBLyc0Cw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "4.16.1",
+ "@typescript-eslint/visitor-keys": "4.16.1"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz",
+ "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "7.9.0",
+ "@typescript-eslint/utils": "7.9.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz",
+ "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz",
+ "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz",
+ "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils/node_modules/minimatch": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+ "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "4.16.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.16.1.tgz",
+ "integrity": "sha512-nnKqBwMgRlhzmJQF8tnFDZWfunXmJyuXj55xc8Kbfup4PbkzdoDXZvzN8//EiKR27J6vUSU8j4t37yUuYPiLqA==",
+ "dev": true,
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "4.16.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.16.1.tgz",
+ "integrity": "sha512-m8I/DKHa8YbeHt31T+UGd/l8Kwr0XCTCZL3H4HMvvLCT7HU9V7yYdinTOv1gf/zfqNeDcCgaFH2BMsS8x6NvJg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "4.16.1",
+ "@typescript-eslint/visitor-keys": "4.16.1",
+ "debug": "^4.1.1",
+ "globby": "^11.0.1",
+ "is-glob": "^4.0.1",
+ "semver": "^7.3.2",
+ "tsutils": "^3.17.1"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz",
+ "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "7.9.0",
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/typescript-estree": "7.9.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.56.0"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz",
+ "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz",
+ "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz",
+ "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "@typescript-eslint/visitor-keys": "7.9.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": {
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz",
+ "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "7.9.0",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || >=20.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/utils/node_modules/minimatch": {
+ "version": "9.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
+ "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "4.16.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.16.1.tgz",
+ "integrity": "sha512-s/aIP1XcMkEqCNcPQtl60ogUYjSM8FU2mq1O7y5cFf3Xcob1z1iXWNB6cC43Op+NGRTFgGolri6s8z/efA9i1w==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "4.16.1",
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz",
+ "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true
+ },
+ "node_modules/abab": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz",
+ "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
+ "deprecated": "Use your platform's native atob() and btoa() methods instead",
+ "dev": true
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "dev": true
+ },
+ "node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-globals": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-7.0.1.tgz",
+ "integrity": "sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.1.0",
+ "acorn-walk": "^8.0.2"
}
},
"node_modules/acorn-globals/node_modules/acorn": {
@@ -3527,15 +4102,6 @@
"integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
"dev": true
},
- "node_modules/astral-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
- "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/async": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz",
@@ -4336,6 +4902,12 @@
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
"dev": true
},
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true
+ },
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
@@ -4890,54 +5462,55 @@
}
},
"node_modules/eslint": {
- "version": "7.15.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.15.0.tgz",
- "integrity": "sha512-Vr64xFDT8w30wFll643e7cGrIkPEU50yIiI36OdSIDoSGguIeaLzBo0vpGvzo9RECUqq7htURfwEtKqwytkqzA==",
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz",
+ "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==",
"dev": true,
"dependencies": {
- "@babel/code-frame": "^7.0.0",
- "@eslint/eslintrc": "^0.2.2",
- "ajv": "^6.10.0",
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.0",
+ "@humanwhocodes/config-array": "^0.11.14",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
- "debug": "^4.0.1",
+ "debug": "^4.3.2",
"doctrine": "^3.0.0",
- "enquirer": "^2.3.5",
- "eslint-scope": "^5.1.1",
- "eslint-utils": "^2.1.0",
- "eslint-visitor-keys": "^2.0.0",
- "espree": "^7.3.1",
- "esquery": "^1.2.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
"esutils": "^2.0.2",
- "file-entry-cache": "^6.0.0",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.0.0",
- "globals": "^12.1.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
- "js-yaml": "^3.13.1",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.4.1",
- "lodash": "^4.17.19",
- "minimatch": "^3.0.4",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "progress": "^2.0.0",
- "regexpp": "^3.1.0",
- "semver": "^7.2.1",
- "strip-ansi": "^6.0.0",
- "strip-json-comments": "^3.1.0",
- "table": "^5.2.3",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
},
"bin": {
"eslint": "bin/eslint.js"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
@@ -5302,18 +5875,6 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/eslint-config-expensify/node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/eslint-config-prettier": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz",
@@ -5533,6 +6094,36 @@
"node": "*"
}
},
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
+ "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.8.6"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": "*",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
"node_modules/eslint-plugin-react": {
"version": "7.34.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz",
@@ -5645,6 +6236,17 @@
"node": ">=4.0.0"
}
},
+ "node_modules/eslint-plugin-you-dont-need-lodash-underscore": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-you-dont-need-lodash-underscore/-/eslint-plugin-you-dont-need-lodash-underscore-6.14.0.tgz",
+ "integrity": "sha512-3zkkU/O1agczP7szJGHmisZJS/AknfVl6mb0Zqoc95dvFsdmfK+cbhrn+Ffy0UWB1pgDJwQr7kIO3rPstWs3Dw==",
+ "dependencies": {
+ "kebab-case": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -5683,24 +6285,67 @@
}
},
"node_modules/eslint/node_modules/@eslint/eslintrc": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz",
- "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==",
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
- "debug": "^4.1.1",
- "espree": "^7.3.0",
- "globals": "^12.1.0",
- "ignore": "^4.0.6",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
"import-fresh": "^3.2.1",
- "js-yaml": "^3.13.1",
- "lodash": "^4.17.19",
- "minimatch": "^3.0.4",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/@eslint/js": {
+ "version": "8.57.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz",
+ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/@humanwhocodes/config-array": {
+ "version": "0.11.14",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
+ "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.2",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/eslint/node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "dev": true
+ },
+ "node_modules/eslint/node_modules/acorn": {
+ "version": "8.11.3",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
+ "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
}
},
"node_modules/eslint/node_modules/ansi-styles": {
@@ -5718,6 +6363,12 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
+ "node_modules/eslint/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
"node_modules/eslint/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -5752,13 +6403,70 @@
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"dev": true
},
- "node_modules/eslint/node_modules/eslint-visitor-keys": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
- "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"engines": {
"node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
}
},
"node_modules/eslint/node_modules/file-entry-cache": {
@@ -5773,6 +6481,22 @@
"node": "^10.12.0 || >=12.0.0"
}
},
+ "node_modules/eslint/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/eslint/node_modules/flat-cache": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
@@ -5787,13 +6511,25 @@
"node": "^10.12.0 || >=12.0.0"
}
},
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/eslint/node_modules/globals": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
- "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
"dev": true,
"dependencies": {
- "type-fest": "^0.8.1"
+ "type-fest": "^0.20.2"
},
"engines": {
"node": ">=8"
@@ -5811,6 +6547,84 @@
"node": ">=8"
}
},
+ "node_modules/eslint/node_modules/ignore": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/eslint/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/eslint/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/eslint/node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/eslint/node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -6015,21 +6829,26 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
"node_modules/fast-glob": {
- "version": "3.2.5",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz",
- "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==",
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.0",
+ "glob-parent": "^5.1.2",
"merge2": "^1.3.0",
- "micromatch": "^4.0.2",
- "picomatch": "^2.2.1"
+ "micromatch": "^4.0.4"
},
"engines": {
- "node": ">=8"
+ "node": ">=8.6.0"
}
},
"node_modules/fast-json-stable-stringify": {
@@ -6447,16 +7266,16 @@
}
},
"node_modules/globby": {
- "version": "11.0.2",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz",
- "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==",
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true,
"dependencies": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
- "fast-glob": "^3.1.1",
- "ignore": "^5.1.4",
- "merge2": "^1.3.0",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
"slash": "^3.0.0"
},
"engines": {
@@ -6467,9 +7286,9 @@
}
},
"node_modules/globby/node_modules/ignore": {
- "version": "5.1.8",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
- "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
+ "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
"dev": true,
"engines": {
"node": ">= 4"
@@ -9815,6 +10634,11 @@
"node": ">=4.0"
}
},
+ "node_modules/kebab-case": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/kebab-case/-/kebab-case-1.0.2.tgz",
+ "integrity": "sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q=="
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -10612,6 +11436,18 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/pretty-format": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@@ -11246,29 +12082,6 @@
"node": ">=8"
}
},
- "node_modules/slice-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
- "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.0",
- "astral-regex": "^1.0.0",
- "is-fullwidth-code-point": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -11444,27 +12257,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^4.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/strip-ansi/node_modules/ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/strip-bom": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
@@ -11525,50 +12317,28 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true
},
- "node_modules/table": {
- "version": "5.4.6",
- "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
- "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
+ "node_modules/synckit": {
+ "version": "0.8.8",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz",
+ "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==",
"dev": true,
"dependencies": {
- "ajv": "^6.10.2",
- "lodash": "^4.17.14",
- "slice-ansi": "^2.1.0",
- "string-width": "^3.0.0"
+ "@pkgr/core": "^0.1.0",
+ "tslib": "^2.6.2"
},
"engines": {
- "node": ">=6.0.0"
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/unts"
}
},
- "node_modules/table/node_modules/emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+ "node_modules/synckit/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
"dev": true
},
- "node_modules/table/node_modules/is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/table/node_modules/string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
@@ -11671,6 +12441,18 @@
"node": ">=12"
}
},
+ "node_modules/ts-api-utils": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
+ "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
"node_modules/tsconfig-paths": {
"version": "3.15.0",
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
@@ -11738,12 +12520,15 @@
}
},
"node_modules/type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true,
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typed-array-buffer": {
@@ -11820,11 +12605,10 @@
}
},
"node_modules/typescript": {
- "version": "5.3.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
- "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
+ "version": "5.4.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
+ "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
"dev": true,
- "peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
diff --git a/package.json b/package.json
index 9e0554ca..a3b13a6c 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,22 @@
{
"name": "expensify-common",
- "version": "1.0.0",
+ "version": "2.0.0",
"author": "Expensify, Inc.",
"description": "Expensify libraries and components shared across different repos",
"homepage": "https://expensify.com",
- "main": "index.js",
"license": "MIT",
+ "main": "dist/index.js",
+ "types": "dist/index.d.ts",
+ "files": [
+ "dist/**/*",
+ "API.md",
+ "README.md",
+ "LICENSE.md"
+ ],
"scripts": {
"grunt": "grunt",
+ "typecheck": "tsc --noEmit",
+ "build": "tsc -p tsconfig.build.json && cp ./lib/*.d.ts ./dist",
"test": "jest",
"lint": "eslint lib/",
"prettier": "prettier --write lib/",
@@ -21,6 +30,7 @@
"dependencies": {
"classnames": "2.5.0",
"clipboard": "2.0.11",
+ "eslint-plugin-you-dont-need-lodash-underscore": "^6.14.0",
"html-entities": "^2.5.2",
"jquery": "3.6.0",
"localforage": "^1.10.0",
@@ -35,20 +45,28 @@
},
"devDependencies": {
"@babel/preset-env": "^7.24.4",
+ "@babel/preset-typescript": "^7.24.1",
"@lwc/eslint-plugin-lwc": "^1.8.0",
+ "@types/jest": "^29.5.12",
+ "@types/react-dom": "^18.3.0",
+ "@types/ua-parser-js": "^0.7.39",
+ "@typescript-eslint/eslint-plugin": "^7.9.0",
+ "@typescript-eslint/parser": "^7.9.0",
"babel-jest": "^29.0.0",
"babelify": "10.0.0",
- "eslint": "^7.15.0",
+ "eslint": "^8.57.0",
"eslint-config-expensify": "^2.0.48",
"eslint-config-prettier": "^8.10.0",
"eslint-plugin-jest": "^24.7.0",
+ "eslint-plugin-prettier": "^5.1.3",
"grunt": "1.6.1",
"grunt-chokidar": "1.0.2",
"grunt-eslint": "25.0.0",
"jest": "^29.0.0",
"jest-environment-jsdom": "^29.7.0",
"jit-grunt": "^0.10.0",
- "prettier": "^3.2.5"
+ "prettier": "^3.2.5",
+ "typescript": "^5.4.5"
},
"browserify": {
"transform": [
diff --git a/tsconfig.build.json b/tsconfig.build.json
new file mode 100644
index 00000000..d04f033a
--- /dev/null
+++ b/tsconfig.build.json
@@ -0,0 +1,5 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "./tsconfig.json",
+ "include": ["./lib"]
+}
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 00000000..92431b67
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://json.schemastore.org/tsconfig",
+ "compilerOptions": {
+ "target": "es2015",
+ "module": "commonjs",
+ "types": ["react", "jest", "node"],
+ "lib": ["esnext"],
+ "allowJs": true,
+ "checkJs": false,
+ "jsx": "react",
+ "isolatedModules": true,
+ "strict": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "declaration": true,
+ "outDir": "./dist"
+ },
+ "exclude": ["**/node_modules/**/*", "**/dist/**/*"]
+}