From 0a1e26e46ff89b2596ab8cf7f6462659ac34334e Mon Sep 17 00:00:00 2001 From: dragnoir Date: Thu, 9 May 2024 11:28:57 +0100 Subject: [PATCH 01/57] Fix: multi level blockquote HTML to Markdown --- lib/ExpensiMark.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 4b8a7eb2..45d7a9df 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -423,14 +423,28 @@ export default class ExpensiMark { regex: /<(blockquote|q)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi, replacement: (match, g1, g2) => { // We remove the line break before heading inside quote to avoid adding extra line - let resultString = g2 + let resultString = match .replace(/\n?(

# )/g, '$1') .replace(/(

|<\/h1>)+/g, '\n') .trim() .split('\n'); - const prependGreaterSign = (m) => `> ${m}`; - resultString = _.map(resultString, prependGreaterSign).join('\n'); + resultString = _.map(resultString, (m) => { + // Recursive function to replace nested
with ">" + function replaceBlockquotes(text) { + while (/
/i.test(text)) { + // Count how many
tags + let depth = (text.match(/
/gi) || []).length; + // Replace all blockquote tags and add ">" per depth level + text = text.replace(/
/gi, ''); + text = text.replace(/<\/blockquote>/gi, ''); + return `${'>'.repeat(depth)} ${text}`; + } + return text; + } + return replaceBlockquotes(m); + }).join('\n'); + // We want to keep
tag here and let method replaceBlockElementWithNewLine to handle the line break later return `
${resultString}
`; }, From 1c716c7cd06f5f327f5af720003ee6784a05c43d Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 15 May 2024 16:24:34 +0700 Subject: [PATCH 02/57] feat: add is valid phone number --- lib/ExpensiMark.js | 10 +++++++++- lib/str.d.ts | 5 +++++ lib/str.js | 12 ++++++++++++ package-lock.json | 9 +++++++++ package.json | 1 + 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 21f7081b..e20cf21e 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -178,7 +178,7 @@ export default class ExpensiMark { { name: 'reportMentions', - regex: /(?$1', }, @@ -202,6 +202,14 @@ export default class ExpensiMark { return match; } const phoneRegex = new RegExp(`^@${Constants.CONST.REG_EXP.PHONE_PART}$`); + const mention = g2.slice(1); + const metionWithoutSMSDomain = Str.removeSMSDomain(mention); + if ( + !Str.isValidMention(match) || + (new RegExp(`^${Constants.CONST.REG_EXP.PHONE_PART}$`).test(metionWithoutSMSDomain) && !Str.isValidPhoneNumber(metionWithoutSMSDomain)) + ) { + return match; + } return `${g1}${g2}${phoneRegex.test(g2) ? `@${Constants.CONST.SMS.DOMAIN}` : ''}`; }, rawInputReplacement: (match, g1, g2) => { diff --git a/lib/str.d.ts b/lib/str.d.ts index d703d8bf..f4f30487 100644 --- a/lib/str.d.ts +++ b/lib/str.d.ts @@ -485,6 +485,11 @@ declare const Str: { * Check for whether a phone number is valid according to E.164 standard. * @param phone */ + isValidPhoneNumber(phone: string): boolean; + /** + * Check for whether a phone number is valid. + * @param phone + */ isValidE164Phone(phone: string): boolean; /** * Check for whether a phone number is valid in different formats/standards. For example: diff --git a/lib/str.js b/lib/str.js index f9978b4e..d9ce6f6b 100644 --- a/lib/str.js +++ b/lib/str.js @@ -1,5 +1,6 @@ /* eslint-disable no-control-regex */ import _ from 'underscore'; +import {parsePhoneNumber} from 'awesome-phonenumber'; import * as HtmlEntities from 'html-entities'; import * as Constants from './CONST'; import * as UrlPatterns from './Url'; @@ -930,6 +931,17 @@ const Str = { return Constants.CONST.SMS.E164_REGEX.test(phone); }, + /** + * Check for whether a phone number is valid. + * @param {String} phone + * + * @return {bool} + */ + + isValidPhoneNumber(phone) { + return parsePhoneNumber(this.removeSMSDomain(phone)).possible; + }, + /** * Check for whether a phone number is valid according to E.164 standard. * @param {String} phone diff --git a/package-lock.json b/package-lock.json index 615318d5..5003d033 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "awesome-phonenumber": "^5.4.0", "classnames": "2.5.0", "clipboard": "2.0.11", "html-entities": "^2.5.2", @@ -3563,6 +3564,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/awesome-phonenumber": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/awesome-phonenumber/-/awesome-phonenumber-5.11.0.tgz", + "integrity": "sha512-25GfikMIo6CBQIqvjoewo4uiu5Ai7WqEC8gxesH3LDwCY43oEdkLaT15a+8adC7uWIJCGh+YQiBY5bjmDpoQcg==", + "engines": { + "node": ">=14" + } + }, "node_modules/axe-core": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", diff --git a/package.json b/package.json index 051a1584..440ee4d2 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "url": "git+ssh://git@github.com/Expensify/JS-Libs.git" }, "dependencies": { + "awesome-phonenumber": "^5.4.0", "classnames": "2.5.0", "clipboard": "2.0.11", "html-entities": "^2.5.2", From 647ffef04e7bce2c931f33671a0c1fbc70c4c7a5 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 15 May 2024 16:26:34 +0700 Subject: [PATCH 03/57] fix chore --- lib/ExpensiMark.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index e20cf21e..25db3e5c 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -178,7 +178,7 @@ export default class ExpensiMark { { name: 'reportMentions', - regex: /(?$1', }, From 322d7b7687fb49ee9ca427305670d9a1e4687e9b Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 15 May 2024 16:31:13 +0700 Subject: [PATCH 04/57] fix comment position --- lib/str.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/str.d.ts b/lib/str.d.ts index f4f30487..e4eb8acb 100644 --- a/lib/str.d.ts +++ b/lib/str.d.ts @@ -482,12 +482,12 @@ declare const Str: { */ isValidPhone(phone: string): boolean; /** - * Check for whether a phone number is valid according to E.164 standard. + * Check for whether a phone number is valid. * @param phone */ isValidPhoneNumber(phone: string): boolean; /** - * Check for whether a phone number is valid. + * Check for whether a phone number is valid according to E.164 standard. * @param phone */ isValidE164Phone(phone: string): boolean; From 4e9cdb02aa46b886388489c4d5f1da1561f7d1dd Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 15 May 2024 17:51:58 +0700 Subject: [PATCH 05/57] remove useless code --- lib/str.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/str.js b/lib/str.js index d9ce6f6b..65007fe2 100644 --- a/lib/str.js +++ b/lib/str.js @@ -939,7 +939,7 @@ const Str = { */ isValidPhoneNumber(phone) { - return parsePhoneNumber(this.removeSMSDomain(phone)).possible; + return parsePhoneNumber(phone).possible; }, /** From fa064832b1880d4d89b1334ccc5eded71c62b91f Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 15 May 2024 18:10:37 +0700 Subject: [PATCH 06/57] rename variable --- lib/ExpensiMark.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 25db3e5c..58234dba 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -198,18 +198,13 @@ export default class ExpensiMark { 'gim', ), replacement: (match, g1, g2) => { - if (!Str.isValidMention(match)) { - return match; - } - const phoneRegex = new RegExp(`^@${Constants.CONST.REG_EXP.PHONE_PART}$`); + const phoneNumberRegex = new RegExp(`^${Constants.CONST.REG_EXP.PHONE_PART}$`); const mention = g2.slice(1); const metionWithoutSMSDomain = Str.removeSMSDomain(mention); - if ( - !Str.isValidMention(match) || - (new RegExp(`^${Constants.CONST.REG_EXP.PHONE_PART}$`).test(metionWithoutSMSDomain) && !Str.isValidPhoneNumber(metionWithoutSMSDomain)) - ) { + if (!Str.isValidMention(match) || (phoneNumberRegex.test(metionWithoutSMSDomain) && !Str.isValidPhoneNumber(metionWithoutSMSDomain))) { return match; } + const phoneRegex = new RegExp(`^@${Constants.CONST.REG_EXP.PHONE_PART}$`); return `${g1}${g2}${phoneRegex.test(g2) ? `@${Constants.CONST.SMS.DOMAIN}` : ''}`; }, rawInputReplacement: (match, g1, g2) => { From 91d752fe313b6c0db544cb46871bedeeb749996b Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 11:47:12 +0200 Subject: [PATCH 07/57] Install deps, change configuration, add scripts to package.json --- package-lock.json | 1130 +++++++++++++++++++++++++++++++++++++-------- package.json | 23 +- 2 files changed, 945 insertions(+), 208 deletions(-) diff --git a/package-lock.json b/package-lock.json index 615318d5..81074c4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "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", @@ -26,19 +26,25 @@ "devDependencies": { "@babel/preset-env": "^7.24.4", "@lwc/eslint-plugin-lwc": "^1.7.2", + "@types/jest": "^29.5.12", + "@types/react-dom": "^18.3.0", + "@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": { @@ -1951,18 +1957,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 +2802,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 +2847,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 +2966,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 +3008,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", @@ -3031,6 +3060,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,6 +3185,145 @@ "eslint": "*" } }, + "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/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": "^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/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": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "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": "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/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": "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/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, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "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, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "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": { + "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", @@ -3072,6 +3341,127 @@ "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", @@ -3112,6 +3502,139 @@ } } }, + "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", @@ -3138,6 +3661,12 @@ "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", @@ -3527,15 +4056,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 +4856,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 +5416,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 +5829,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 +6048,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", @@ -5683,24 +6228,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 +6306,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 +6346,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 +6424,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 +6454,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 +6490,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 +6772,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 +7209,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 +7229,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" @@ -10612,6 +11374,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 +12020,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 +12195,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 +12255,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 +12379,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 +12458,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 +12543,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 051a1584..b2dfc076 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/", @@ -36,19 +45,25 @@ "devDependencies": { "@babel/preset-env": "^7.24.4", "@lwc/eslint-plugin-lwc": "^1.7.2", + "@types/jest": "^29.5.12", + "@types/react-dom": "^18.3.0", + "@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": [ From 3d910ce5e6eab38da16173e2ba5102d5b88d915d Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 11:48:42 +0200 Subject: [PATCH 08/57] Ignore dist --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 608a5535..e1699c98 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ npm-debug.log package.json-e .DS_Store *.swp +dist From ddfc91eda4aa42d7561af24f1d91ac3045cb7f07 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 11:48:58 +0200 Subject: [PATCH 09/57] Adjust prettier and eslint ignore files --- .eslintignore | 3 +++ .prettierignore | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 .prettierignore 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/.prettierignore b/.prettierignore new file mode 100644 index 00000000..b67fe5c9 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,4 @@ +dist +package.json +package-lock.json +*.html \ No newline at end of file From b981ab407d1fd2afb029c407a57e963842f97fde Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 11:49:09 +0200 Subject: [PATCH 10/57] Prepare eslint config --- .eslintrc.js | 63 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 02a609dc..c1de71a4 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,11 +1,58 @@ 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', + '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', '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', + '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', + }, + }, + ], }; From 479c9cf03377af0cfe5917da5b9c5d0b8ef97f0a Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 11:49:25 +0200 Subject: [PATCH 11/57] Prepare tsconfigs --- tsconfig.build.json | 5 +++++ tsconfig.json | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tsconfig.build.json create mode 100644 tsconfig.json diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..eb941d63 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,5 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./tsconfig.json", + "include": ["./lib"] +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..9873ff27 --- /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/**/*"] +} \ No newline at end of file From 243308a978df4fa9ebc0841447e228958a869c3c Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 11:50:25 +0200 Subject: [PATCH 12/57] Add prettier and typecheks workflows --- .github/workflows/lint.yml | 9 +++++++++ .github/workflows/typecheck.yml | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 .github/workflows/typecheck.yml 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/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 From e85751d183e288b1a06a0ead1de7205e61ec6cbc Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 11:50:41 +0200 Subject: [PATCH 13/57] Migrate CONST --- lib/CONST.d.ts | 852 ------------------------------------ lib/{CONST.jsx => CONST.ts} | 19 +- 2 files changed, 11 insertions(+), 860 deletions(-) delete mode 100644 lib/CONST.d.ts rename lib/{CONST.jsx => CONST.ts} (98%) 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 b68261b4..764469dd 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, /** @@ -883,12 +884,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', @@ -922,10 +923,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', @@ -997,4 +998,6 @@ export const PUBLIC_DOMAINS = [ 'yahoo.com', 'yahoo.com.br', 'ymail.com', -]; +] as const; + +export {g_cloudFront, g_cloudFrontImg, CONST, UI, PUBLIC_DOMAINS}; From 3914542418ff48d4a83dc9f1e06b656f02dd0c3e Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 11:54:30 +0200 Subject: [PATCH 14/57] Add endlines --- .prettierignore | 2 +- tsconfig.build.json | 2 +- tsconfig.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.prettierignore b/.prettierignore index b67fe5c9..d54e0bdf 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,4 @@ dist package.json package-lock.json -*.html \ No newline at end of file +*.html diff --git a/tsconfig.build.json b/tsconfig.build.json index eb941d63..d04f033a 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -2,4 +2,4 @@ "$schema": "https://json.schemastore.org/tsconfig", "extends": "./tsconfig.json", "include": ["./lib"] -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index 9873ff27..92431b67 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,4 +18,4 @@ "outDir": "./dist" }, "exclude": ["**/node_modules/**/*", "**/dist/**/*"] -} \ No newline at end of file +} From 0c0c65c1d35b486ab5a639d555dd84ae288f7ef2 Mon Sep 17 00:00:00 2001 From: nkdengineer <161821005+nkdengineer@users.noreply.github.com> Date: Fri, 17 May 2024 17:07:50 +0700 Subject: [PATCH 15/57] Update lib/str.d.ts Co-authored-by: Benjamin Limpich --- lib/str.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/str.d.ts b/lib/str.d.ts index e4eb8acb..f48bc35a 100644 --- a/lib/str.d.ts +++ b/lib/str.d.ts @@ -478,7 +478,7 @@ declare const Str: { /** * Check for whether a phone number is valid. * @param phone - * @deprecated use isValidE164Phone to validate E.164 phone numbers or isValidPhoneFormat to validate phone numbers in general + * @deprecated use isValidE164Phone to validate E.164 phone numbers, isValidPhoneFormat to validate phone number format, or isValidPhoneNumber to validate phone numbers in general */ isValidPhone(phone: string): boolean; /** From 1369f15b372feb507ef01101518db950fd4dfe0e Mon Sep 17 00:00:00 2001 From: nkdengineer <161821005+nkdengineer@users.noreply.github.com> Date: Fri, 17 May 2024 17:08:30 +0700 Subject: [PATCH 16/57] Update lib/str.js Co-authored-by: Benjamin Limpich --- lib/str.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/str.js b/lib/str.js index 65007fe2..12571587 100644 --- a/lib/str.js +++ b/lib/str.js @@ -937,7 +937,6 @@ const Str = { * * @return {bool} */ - isValidPhoneNumber(phone) { return parsePhoneNumber(phone).possible; }, From 9192abef6e2d48db713d2e344ea2d93f8f737e04 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Fri, 17 May 2024 17:09:55 +0700 Subject: [PATCH 17/57] fix: typo --- lib/ExpensiMark.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 58234dba..23ca7eb7 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -200,8 +200,8 @@ export default class ExpensiMark { replacement: (match, g1, g2) => { const phoneNumberRegex = new RegExp(`^${Constants.CONST.REG_EXP.PHONE_PART}$`); const mention = g2.slice(1); - const metionWithoutSMSDomain = Str.removeSMSDomain(mention); - if (!Str.isValidMention(match) || (phoneNumberRegex.test(metionWithoutSMSDomain) && !Str.isValidPhoneNumber(metionWithoutSMSDomain))) { + const mentionWithoutSMSDomain = Str.removeSMSDomain(mention); + if (!Str.isValidMention(match) || (phoneNumberRegex.test(mentionWithoutSMSDomain) && !Str.isValidPhoneNumber(mentionWithoutSMSDomain))) { return match; } const phoneRegex = new RegExp(`^@${Constants.CONST.REG_EXP.PHONE_PART}$`); From 13345403d0d7a1f706c6a713bd066d3698143d2a Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 13:44:22 +0200 Subject: [PATCH 18/57] Fix basic eslint errors --- .eslintrc.js | 1 + lib/API.jsx | 4 ++-- lib/ExpenseRule.jsx | 6 +----- lib/Log.jsx | 1 + lib/ReportHistoryStore.jsx | 3 --- lib/components/form/element/onOffSwitch.jsx | 1 + 6 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index c1de71a4..134c038d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -16,6 +16,7 @@ module.exports = { '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', diff --git a/lib/API.jsx b/lib/API.jsx index 6a6d0482..6393f28d 100644 --- a/lib/API.jsx +++ b/lib/API.jsx @@ -823,7 +823,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 +842,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/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/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/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/components/form/element/onOffSwitch.jsx b/lib/components/form/element/onOffSwitch.jsx index b3a4da29..efba64de 100644 --- a/lib/components/form/element/onOffSwitch.jsx +++ b/lib/components/form/element/onOffSwitch.jsx @@ -176,6 +176,7 @@ class OnOffSwitch extends Component { descriptionElm = (
); From d31f093ce46bbf4209fb78e913629b626e6e2d34 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 17 May 2024 13:49:33 +0200 Subject: [PATCH 19/57] Fix rest of the eslint issues --- lib/API.jsx | 1 + lib/Cookie.jsx | 2 +- lib/CredentialsWrapper.jsx | 4 ++- lib/Logger.jsx | 2 ++ lib/Network.jsx | 1 + lib/Templates.jsx | 27 ++++++++++----------- lib/components/form/element/onOffSwitch.jsx | 1 + 7 files changed, 22 insertions(+), 16 deletions(-) diff --git a/lib/API.jsx b/lib/API.jsx index 6393f28d..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); 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/Logger.jsx b/lib/Logger.jsx index d1e8180b..29735844 100644 --- a/lib/Logger.jsx +++ b/lib/Logger.jsx @@ -30,6 +30,7 @@ export default class Logger { // We don't care about log setting web cookies so let's define it as false const linesToLog = _.map(this.logLines, (l) => { + // eslint-disable-next-line no-param-reassign delete l.onlyFlushWithOthers; return l; }); @@ -38,6 +39,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); 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/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 efba64de..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 From eb6f98b4b46aa0d2b989ca62523721fa2f5a25f8 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 20 May 2024 08:23:41 +0200 Subject: [PATCH 20/57] Run prettier --- lib/ExpensiMark.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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', }, From a5b8bb778d87e52c93f8c4be56fa4e7b50724a13 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 20 May 2024 08:29:37 +0200 Subject: [PATCH 21/57] Add babel to tests to enable Typescript --- babel.config.js | 11 +---- package-lock.json | 108 +++++++++++++++++++++++++++++++--------------- package.json | 1 + 3 files changed, 75 insertions(+), 45 deletions(-) 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/package-lock.json b/package-lock.json index 81074c4e..eb88e12b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,6 +25,7 @@ }, "devDependencies": { "@babel/preset-env": "^7.24.4", + "@babel/preset-typescript": "^7.24.1", "@lwc/eslint-plugin-lwc": "^1.7.2", "@types/jest": "^29.5.12", "@types/react-dom": "^18.3.0", @@ -249,19 +250,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": { @@ -357,12 +358,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" @@ -412,9 +413,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" @@ -479,30 +480,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" @@ -777,12 +778,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" @@ -894,12 +895,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" @@ -1632,6 +1633,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", @@ -1813,6 +1832,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", @@ -1867,13 +1905,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": { diff --git a/package.json b/package.json index b2dfc076..c7875b7b 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ }, "devDependencies": { "@babel/preset-env": "^7.24.4", + "@babel/preset-typescript": "^7.24.1", "@lwc/eslint-plugin-lwc": "^1.7.2", "@types/jest": "^29.5.12", "@types/react-dom": "^18.3.0", From 1df5b90804ec21e83e6765d85812b46425b6efe6 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 20 May 2024 10:06:28 +0200 Subject: [PATCH 22/57] Migrate Logger to TS --- .eslintrc.js | 3 ++ lib/{Logger.jsx => Logger.ts} | 68 +++++++++++++++++++++-------------- 2 files changed, 44 insertions(+), 27 deletions(-) rename lib/{Logger.jsx => Logger.ts} (56%) diff --git a/.eslintrc.js b/.eslintrc.js index 134c038d..fa6b2448 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -42,6 +42,9 @@ module.exports = { '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': 'off', 'react/jsx-filename-extension': ['error', {extensions: ['.tsx', '.jsx']}], 'import/no-unresolved': 'error', 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], diff --git a/lib/Logger.jsx b/lib/Logger.ts similarity index 56% rename from lib/Logger.jsx rename to lib/Logger.ts index 29735844..cfd002ae 100644 --- a/lib/Logger.jsx +++ b/lib/Logger.ts @@ -1,8 +1,22 @@ -import _ from 'underscore'; +type Parameters = string | Record | Array>; +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,27 @@ export default class Logger { this.isDebug = isDebug; // Public Methods + // eslint-disable-next-line no-constructor-return 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), - }; + } as 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; @@ -49,12 +64,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, @@ -76,12 +90,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); } @@ -89,16 +103,16 @@ 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) { - params.stack = JSON.stringify(new Error().stack); + (params as Record).stack = JSON.stringify(new Error().stack); } this.add(msg, params, true); @@ -110,7 +124,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); } @@ -118,10 +132,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); } @@ -129,9 +143,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; } From 78b719e981f703ca6c9faa3ab7be3f8e6ac4e29c Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 20 May 2024 10:06:36 +0200 Subject: [PATCH 23/57] Migrate Device to TS --- lib/Device.d.ts | 7 ------- lib/{Device.jsx => Device.ts} | 9 ++++++++- package-lock.json | 7 +++++++ package.json | 1 + 4 files changed, 16 insertions(+), 8 deletions(-) delete mode 100644 lib/Device.d.ts rename lib/{Device.jsx => Device.ts} (65%) 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/package-lock.json b/package-lock.json index eb88e12b..669cab93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@lwc/eslint-plugin-lwc": "^1.7.2", "@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", @@ -3083,6 +3084,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", diff --git a/package.json b/package.json index c7875b7b..b0a00ddc 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@lwc/eslint-plugin-lwc": "^1.7.2", "@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", From d12063c2c8209a9af260baa71eb807b28fa4c4bc Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 20 May 2024 10:06:57 +0200 Subject: [PATCH 24/57] Remove Logger.d.ts --- lib/Logger.d.ts | 63 ------------------------------------------------- 1 file changed, 63 deletions(-) delete mode 100644 lib/Logger.d.ts 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 {}; From 55933f5b6ee38ebcb01c2c1585f17bc4c761dafa Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 20 May 2024 10:16:14 +0200 Subject: [PATCH 25/57] Migrate fastMerge to TS --- lib/fastMerge.d.ts | 10 ----- lib/{fastMerge.js => fastMerge.ts} | 62 +++++++++++++++--------------- 2 files changed, 31 insertions(+), 41 deletions(-) delete mode 100644 lib/fastMerge.d.ts rename lib/{fastMerge.js => fastMerge.ts} (51%) 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.ts similarity index 51% rename from lib/fastMerge.js rename to lib/fastMerge.ts index 57352cff..6b786654 100644 --- a/lib/fastMerge.js +++ b/lib/fastMerge.ts @@ -1,66 +1,71 @@ -import _ from 'underscore'; +/* eslint-disable @typescript-eslint/prefer-for-of */ // Mostly copied from https://medium.com/@lubaka.a/how-to-remove-lodash-performance-improvement-b306669ad0e1 /** - * @param {mixed} val - * @returns {boolean} + * Checks whether the given value can be merged. It has to be an object, but not an array, RegExp or Date. */ -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); +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); } /** - * @param {Object} target - * @param {Object} source - * @param {Boolean} shouldRemoveNullObjectValues - * @returns {Object} + * 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, source, shouldRemoveNullObjectValues = true) { - const destination = {}; +function mergeObject>(target: TObject | null, 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 = _.keys(target); + 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 = target[key] === null || source[key] === null; + const isSourceOrTargetNull = targetValue === null || sourceValue === null; const shouldOmitSourceKey = shouldRemoveNullObjectValues && isSourceOrTargetNull; if (!shouldOmitSourceKey) { - destination[key] = target[key]; + destination[key] = targetValue; } } } // lodash adds a small overhead so we don't use it here - const sourceKeys = _.keys(source); + 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 && source[key] === null; + const shouldOmitSourceKey = shouldRemoveNullObjectValues && sourceValue === null; // If we pass undefined as the updated value for a key, we want to generally ignore it - const isSourceKeyUndefined = source[key] === undefined; + const isSourceKeyUndefined = sourceValue === undefined; if (!isSourceKeyUndefined && !shouldOmitSourceKey) { - const isSourceKeyMergable = isMergeableObject(source[key]); + const isSourceKeyMergable = isMergeableObject(sourceValue); - if (isSourceKeyMergable && target[key]) { + if (isSourceKeyMergable && targetValue) { if (!shouldRemoveNullObjectValues || isSourceKeyMergable) { // eslint-disable-next-line no-use-before-define - destination[key] = fastMerge(target[key], source[key], shouldRemoveNullObjectValues); + destination[key] = fastMerge(targetValue as TObject, sourceValue, shouldRemoveNullObjectValues); } - } else if (!shouldRemoveNullObjectValues || source[key] !== null) { - destination[key] = source[key]; + } else if (!shouldRemoveNullObjectValues || sourceValue !== null) { + destination[key] = sourceValue; } } } - return destination; + return destination as TObject; } /** @@ -69,17 +74,12 @@ function mergeObject(target, source, shouldRemoveNullObjectValues = 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) { +function fastMerge>(target: TObject | null, source: TObject | null, shouldRemoveNullObjectValues = true): TObject | null { // 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) { + if (Array.isArray(source) || source === null || source === undefined) { return source; } return mergeObject(target, source, shouldRemoveNullObjectValues); From 35b468333aa4592170d2a011236ead1b2fa3dbcc Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 20 May 2024 12:32:14 +0200 Subject: [PATCH 26/57] Fix fastMerge types --- lib/fastMerge.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fastMerge.ts b/lib/fastMerge.ts index 6b786654..a7ce03bd 100644 --- a/lib/fastMerge.ts +++ b/lib/fastMerge.ts @@ -17,7 +17,7 @@ function isMergeableObject(value: unknown): value is Record { * @param shouldRemoveNestedNulls - If true, null object values will be removed. * @returns - The merged object. */ -function mergeObject>(target: TObject | null, source: TObject, shouldRemoveNullObjectValues = true): TObject { +function mergeObject>(target: TObject, source: TObject, shouldRemoveNullObjectValues = true): TObject { const destination: Record = {}; if (isMergeableObject(target)) { @@ -75,14 +75,14 @@ function mergeObject>(target: TObject | * 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 | null, source: TObject | null, shouldRemoveNullObjectValues = true): TObject | null { +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, source, shouldRemoveNullObjectValues); + return mergeObject(target as Record, source as Record, shouldRemoveNullObjectValues) as TObject; } export default fastMerge; From 2c983a1fa7567e0451406added17c14da974a5cb Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 20 May 2024 12:32:39 +0200 Subject: [PATCH 27/57] Create missing index.ts file --- .eslintrc.js | 10 ++++++++++ lib/index.ts | 21 +++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 lib/index.ts diff --git a/.eslintrc.js b/.eslintrc.js index fa6b2448..b996b4b7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -56,6 +56,16 @@ module.exports = { '@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/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'; From 0023d733a3e5bed7fa6c18aca7ef9af9c2367ac8 Mon Sep 17 00:00:00 2001 From: dragnoir Date: Mon, 20 May 2024 17:20:15 +0100 Subject: [PATCH 28/57] fix lint --- lib/ExpensiMark.js | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 45d7a9df..2d0e0a28 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -177,7 +177,7 @@ export default class ExpensiMark { { name: 'reportMentions', - regex: /(?$1', }, @@ -421,7 +421,7 @@ export default class ExpensiMark { { name: 'quote', regex: /<(blockquote|q)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi, - replacement: (match, g1, g2) => { + replacement(match) { // We remove the line break before heading inside quote to avoid adding extra line let resultString = match .replace(/\n?(

# )/g, '$1') @@ -429,21 +429,22 @@ export default class ExpensiMark { .trim() .split('\n'); - resultString = _.map(resultString, (m) => { + function processString(m) { // Recursive function to replace nested
with ">" function replaceBlockquotes(text) { - while (/
/i.test(text)) { - // Count how many
tags - let depth = (text.match(/
/gi) || []).length; - // Replace all blockquote tags and add ">" per depth level - text = text.replace(/
/gi, ''); - text = text.replace(/<\/blockquote>/gi, ''); - return `${'>'.repeat(depth)} ${text}`; - } - return text; - } + let modifiedText = text; + let depth; + do { + depth = (modifiedText.match(/
/gi) || []).length; + modifiedText = modifiedText.replace(/
/gi, ''); + modifiedText = modifiedText.replace(/<\/blockquote>/gi, ''); + } while (/
/i.test(modifiedText)); + return `${'>'.repeat(depth)} ${modifiedText}`; + } return replaceBlockquotes(m); - }).join('\n'); + } + + resultString = _.map(resultString, processString).join('\n'); // We want to keep
tag here and let method replaceBlockElementWithNewLine to handle the line break later return `
${resultString}
`; From cfc6b0a74a6d061c785ce52671f507563d6118df Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 21 May 2024 15:03:32 +0200 Subject: [PATCH 29/57] Adjust after review --- lib/Logger.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Logger.ts b/lib/Logger.ts index cfd002ae..fc1af734 100644 --- a/lib/Logger.ts +++ b/lib/Logger.ts @@ -111,8 +111,8 @@ export default class Logger { const msg = `[alrt] ${message}`; const params = parameters; - if (includeStackTrace) { - (params as Record).stack = JSON.stringify(new Error().stack); + if (includeStackTrace && typeof params === 'object' && !Array.isArray(params)) { + params.stack = JSON.stringify(new Error().stack); } this.add(msg, params, true); From 4bbd3542f75deab25ab2779f4288da5e53b1026b Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 21 May 2024 15:28:49 +0200 Subject: [PATCH 30/57] Add Error to Logger parameters type --- lib/Logger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Logger.ts b/lib/Logger.ts index fc1af734..a7ea2e28 100644 --- a/lib/Logger.ts +++ b/lib/Logger.ts @@ -1,4 +1,4 @@ -type Parameters = string | Record | Array>; +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; From 8fca7f384a22394c1115182e37d6afc3474a1fcd Mon Sep 17 00:00:00 2001 From: dragnoir Date: Wed, 22 May 2024 17:06:41 +0100 Subject: [PATCH 31/57] add tests --- __tests__/ExpensiMark-Markdown-test.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/__tests__/ExpensiMark-Markdown-test.js b/__tests__/ExpensiMark-Markdown-test.js index 49ea5af2..c342c6d0 100644 --- a/__tests__/ExpensiMark-Markdown-test.js +++ b/__tests__/ExpensiMark-Markdown-test.js @@ -497,6 +497,18 @@ test('map div with quotes', () => { expect(parser.htmlToMarkdown(testString)).toBe(resultString); }); +test('double quotes in same line', () => { + const testString = '
line 1
'; + const resultString = '>> line 1'; + expect(parser.htmlToMarkdown(testString)).toBe(resultString); +}); + +test('tripple quotes in same line', () => { + const testString = '
line 1
'; + const resultString = '>>> line 1'; + expect(parser.htmlToMarkdown(testString)).toBe(resultString); +}); + test('map table to newline', () => { const testString = 'line 1line 2'; const resultString = 'line 1\nline 2'; From 952ac7bb63ec0e3ab980576db4f6ffd52d5ae5d5 Mon Sep 17 00:00:00 2001 From: dragnoir Date: Wed, 22 May 2024 17:53:08 +0100 Subject: [PATCH 32/57] fix test errors --- lib/ExpensiMark.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 2d0e0a28..b4fbf5a7 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -421,14 +421,23 @@ export default class ExpensiMark { { name: 'quote', regex: /<(blockquote|q)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi, - replacement(match) { + replacement(match, g1, g2) { // We remove the line break before heading inside quote to avoid adding extra line - let resultString = match + let resultString = g2 .replace(/\n?(

# )/g, '$1') .replace(/(

|<\/h1>)+/g, '\n') .trim() .split('\n'); + // Wrap each string in the array with
and
+ // Define a named function to wrap each line with blockquote + function wrapWithBlockquote(line) { + return `
${line}
`; + } + + // Use _.map with the named function + resultString = _.map(resultString, wrapWithBlockquote); + function processString(m) { // Recursive function to replace nested
with ">" function replaceBlockquotes(text) { From b5aac5518660ed454827e263e95f9c99d6a047e7 Mon Sep 17 00:00:00 2001 From: dragnoir Date: Wed, 22 May 2024 17:55:57 +0100 Subject: [PATCH 33/57] fix typo --- lib/ExpensiMark.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index b4fbf5a7..610d4824 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -421,7 +421,7 @@ export default class ExpensiMark { { name: 'quote', regex: /<(blockquote|q)(?:"[^"]*"|'[^']*'|[^'">])*>([\s\S]*?)<\/\1>(?![^<]*(<\/pre>|<\/code>))/gi, - replacement(match, g1, g2) { + replacement: (match, g1, g2) => { // We remove the line break before heading inside quote to avoid adding extra line let resultString = g2 .replace(/\n?(

# )/g, '$1') From aab8898d374c7a0cd9a185aa56a70956a7eec95d Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 27 May 2024 11:18:26 +0200 Subject: [PATCH 34/57] Fix es/no-nullish-coalescing eslint rule --- .eslintrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index b996b4b7..7ca83b33 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -44,7 +44,7 @@ module.exports = { 'react/require-default-props': 'off', 'valid-jsdoc': 'off', 'es/no-optional-chaining': 'off', - 'es/no-nullish-coalescing': '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'], From 229b2f3582ada45001ac469a24258090b0eb08d9 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 27 May 2024 11:20:53 +0200 Subject: [PATCH 35/57] Remove return from a Logger constructor --- lib/Logger.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/Logger.ts b/lib/Logger.ts index a7ea2e28..90d70b9a 100644 --- a/lib/Logger.ts +++ b/lib/Logger.ts @@ -24,14 +24,11 @@ export default class Logger { this.isDebug = isDebug; // Public Methods - // eslint-disable-next-line no-constructor-return - 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), - } as 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); } /** From a19fc652343ebb317279722bc09a0e766ae2932b Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 27 May 2024 11:22:28 +0200 Subject: [PATCH 36/57] Configure you-dont-need-lodash-underscore eslint plugin --- .eslintrc.js | 10 +++++++++- package-lock.json | 17 +++++++++++++++++ package.json | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 7ca83b33..f49834cc 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -32,7 +32,15 @@ module.exports = { }, { files: ['*.ts', '*.tsx'], - extends: ['expensify', 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/stylistic', 'plugin:import/typescript', 'prettier', 'plugin:prettier/recommended'], + 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', diff --git a/package-lock.json b/package-lock.json index fb641e7a..8c8c3f38 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,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", @@ -6235,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", @@ -10622,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", diff --git a/package.json b/package.json index 2742f503..a3b13a6c 100644 --- a/package.json +++ b/package.json @@ -30,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", From 5ad4e37ebdc303ce4fab0993eb83298923ebe07b Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 27 May 2024 12:25:40 +0200 Subject: [PATCH 37/57] Add publish workflow from react-native-onyx --- .github/OSBotify-private-key.asc.gpg | Bin 0 -> 5132 bytes .github/workflows/publish.yml | 77 +++++++++++++++++++++++++++ .nvmrc | 1 + 3 files changed, 78 insertions(+) create mode 100644 .github/OSBotify-private-key.asc.gpg create mode 100644 .github/workflows/publish.yml create mode 100644 .nvmrc diff --git a/.github/OSBotify-private-key.asc.gpg b/.github/OSBotify-private-key.asc.gpg new file mode 100644 index 0000000000000000000000000000000000000000..c19d5c97866c2e3963409bd11f5438ac8a6c4505 GIT binary patch literal 5132 zcmV+n6!Yth4Fm}T0_R1YT2XmTpYPJ_0R$UWG_+^&y)TStIapY6XPk?lfXfa9`Z7?{ zjcVt6m?c?|J#SzRxz)vch?(Jx^3)8uB-SoqBa*#(AE6_riqcW8Y5fploaDDVA4 zL@3S|)Qy!_^Z1z(ERPkeR|4`@@xilwf=?8{Bh-UO6X_f8x0wcZ<T6wOVH~xnGOTvx9guumJm_zT$7&!&t^l7UnBxWzcy}YUk~f zTPO@CF{m+h4mX8*NQ1F(TYR=7=cELjk+L`l)q2&n2C*bs4qZbqybY*wwwZ6(T&xd4 zMu7fWOge;)%`x0`RoKKln$6|BY_922X2qo1f?if|M>M!`&y*8(_R8)t>&tU)asfbr zM+Nn)O9v_0?e~{x^P5l@jY|yudZ_zm*(cqtd|{`Wi%55qEKD^5yB3R<2-U+S_r4bXL68yiJCXQSV& zq^>|}r+FZeJ2m=yBX6Brg;caN4FE{#)0x{YVV2k+1~J0CUw}*34qu=o{}x&NbC#QT zfkFLm#z2CpFt;Ju3a`V?Ex#Iws+L!7ODSGzV6PC7caVb8{qFRh;`=xZj0J5Q2k%V8 zkjwiRl!jWb)Z+fn0h)RO2kr(M{|iOpA!H@f3E-qTO}f=bu1&@VYOry!nQMNtzfc_q zB^H@_>96)27^L9{#Vl(J!|F|kI)t4d-|yng96T2Qnu_a`ws3@_O8_u3^3ffBtUb8j zK?*tn-6`j@*HZ#-U%*cs;FoR3ocjjAwIp+>?hjCwyv`U2iCTQD(j@;iZ>nT%q6THY z#Oyo%BFpySny%`DzKrejHjR`3z8XJx($y%)X@rA*$!3D@zXlR9tH++J*ZR+QRx@KK%jIenS{L9?a|D(a}+_EEoJ>GF!rZI)EF z0v|35d@_qLE`$$^b8?Z~Wr|GA#wri>fu#2ZaRQBUB-L1z}b*?|HWODzD z+Bq$8fJC?io&A|Zl-vMd>P456f5&(b;ApCc4$`HCW;bCU#=->iAb82){H;B5YW7IV z^n*-8Hb%S(Y7O}OWb7z|Rq8`I@-6wv?LXE@Da-Nrl=(x6tmOXzy|>*-*lCe6>`G9& z{D5C!uK^qqjLX1#xQe+47)!jOL1Rnc{|u{KfLE_>Yhc6+o=3*%wZak;Ri0`;%bL5) zKajP!Hg|U#l*F>rps!65y6ll@H2-K_zu?DjZuYFvMps0%hU!bA+g>Cnm%Cx$DXw0k(V*QMvJb&Yf1m19j)l%_%oKs)mV}a-3K1&P>~zL5VA-4{`%=)Gj?uVswV-V8O@+MRL>g}~w1 z&7gXC6xvgQMbNnr)?#Nf>fl3t7aWr~D0N3oT0XFfu=VjS>hcOS zRP%e{f{0gnEELqfl;-ky0H20vBd58PVGqGo$@n{zquFAS!@>luFKr&BynEk`l?ky8 z0LIp>Y%VER-Z#Yq&TI_M9nsFC(dceLjf07xoU03O=B%{kupH8COv7)Z)RLL5G2VU z1;FZa%J8!?Eh(zIuXEH{$``6fF+JII4OxzC_EoHh0v~7#KTq}=Gnw@us=T5T3wj04 z>;d^R5Ic4pJ8>MlaCHtU1J-Awc~PTnXAvAv-yEB|i&B~=OASlQ$5X+JTCAxT=B&ES zKPpmrk*CNNo(Xycx+tPs64$Bp`#@!lYJ+eoG?;V4XHXAo(J@e4;RtU4;obl)*&93jRsrhnz*-cWVU3afZZT(I${55}%E?}F?QCtRA;ISejp=?A@cn}MDINaK6 z_mrmMYf~^K!~L9l{L|qaO}d zf{qw}hiRryTVjpAs3vnH3mbfnxXTjvk2Eo|2^9B&SZ|Gz2u?wsjcs%K!eP8o*<(=2 zmi9NOL>;;Mr0%^N93n_oFLuVi*T1SYOf_gZx{wG3c7x1;zJx{85s#W+%2p|2*CLW{ z4XZ~gGQlL9mK_gnUV~Nff-FseQk-^4Vgq0)jeh^1d0>sLDrG&r|L2@R{(27$j8}Gx zD6S{?ykiJ(znwFpL}-iw5Wh}Dn?n1}^aDubV`bu2m#ki1+^_2lI%yj)u-s>eUONmJ zX~A9k?=!T~^S%qT9w-o@%!j+;IOS-nL zKV|lPq~*-Nd9czz)!mGV2S-XGkuU916KgSpLx^l6*aR0yH7+BDVO7jSn3!f&NVcg> z(COWB_P|Qu4#}LOix*MR{ZVrIP8v4f8f9i&m*bdL2)57>cQ<)feN};$Ri$;jVIc!G@dID zFtjv2)9NGoceV%2tCb!mTkK!cyVDHo0+G-ad`$geQA*Se(l5hP>2JGzxF#EZGLdCy z^%B=Ej6*9g#at?{@waZ9<9YPGBHKP#&8~?jGD^q1?8_{%|5b)<;KR5~`nT^^e?fp6 z(k0XYp1@?$V2p77aj+Hkj17dokWPBY^X3@~FD{*WDuR{Mg1eofO!Oq5Lj}hDV5@z8 zMF^5`UV-ka;xt~nNs-_`|9%!HiUnx@kQi+Z0iMGOulZ{4AV4YuyB@A0jff8SPebRe z5x9$Dl1@`-#?^QxF2Y`UTv63w2?%=A=n#CNA}=1&LD|_dTeh<_?fmUATZRx7pMq#p z(`qbewCYo1AA8L(zfl@(CWo*4av&@Xzck{gOwzV*^faQAT@<>h8;b#0dR};lzy1{1 zt7e0ycDaDLAd*hJ(-D?SB3;#(Iu%TxlLc{i1tBDesorQl8S3#14*Qtx>ie)+r2*xr zat$;_>y1&3(>0AiJF;^RdL=Ja7a8c*X8RnRY86%gt{u6HeNUD5OArfk_3c`8sh+Cd zD>5tnd2hLK(?N%#@lp>G=Mk$Fv5gYJeb!fJ4haU`2eYD^U?5c%L^>FXqQvvI zbQP)nB0SXvS!~^)9Epw};Mz9Lyi>8F43IE-oHBro(KTIypYXfpCNvDT5p^motaN%) z7>3@5akT`Drj=RNBi0GGSYJbBClVV0sPG$!$P#P!cm$KCzi%pu|5MN4OAGvi*=(mQ zlF${&5GVHBo>X_?gqqZJ(WkY$Rs_>`v}(07SUwV17H4W6HTELDE;=O-$PMHvG&Lxv z3O9xnSPn&=RnBBZoS+V@#av4JgC0}Q$ChVz@?7UN%&jhTS?AA(&mIwJJZkS=EBKGq z(=%!xG)-Vi;=uo|f%%T1qeIT4+`R)v1-6dc-T$8rP%7d+A{GDU!Um%h%)_527Yn5D z{ym_|sz$RmvRii2$36~u>2EXb4PrA!4Wjb$YzlB$m5Dq(yO{_MJ~1!z*Zm+2$f%Qm z1HO}(IpCnm+WDDncYA%!gw;*&PqDo@1*}Q<3C4-S|QCi(7xiG4IGihAZ^l|50dIQP#;UK)|9(AkOUuK09(mxEs<&&v71jbKj%SIFatxf0>Q@uh>Dq64#Uu&wOb zvsPrY_a)?r@D~FRN0KZ*#qX!V9#a?-S;A=oRovteHSJ`fWKoU6VDzcb2ds`D-txEpdG0mR@Ln{c3Qb6n<{d66~Y3~5_U8Ttwd_2g7_S6Es7Sf zP?7NH(5<3>^c!ur{4apAHi#6w-yOcKi4&0Tmteft-IDZGwpJ|a`i27gc!BkC3V7)z zfnIdidm)o~Al|enYX`}I;f~0pT|-*Ba2PRAZx36opHuaC_YsCQ7{#18nrIQe{oCbh zhFc7>ikxdtGoyy@Vg3RFl{aynI@m+$fP$!Dz|mS!vt!UKd?pPsTOLoAWLNCcV#{Y~ z1*Q6A9`MV7)P4fY`Y?RRA%R}ouW|f-ywtY^v>->cv>!ObTnS)&65E317u*bcLjA88 z+Ww-;YQZ=foG|W!{%f|0RLi69LK6?zB!e(LSeBVM$WUy$_wG5NJKv0__2h0^nH19il*^G#X``d^b}g4#dj-DZgXH}$#FK2u!Wh|1a=oyABh3{{9eS% zJ>=ziby-Z=c5;?BUr?%*J|Iw7LHKuhYgIk7Ya}DTc=c{N24xv1> $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/.nvmrc b/.nvmrc new file mode 100644 index 00000000..62d44807 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +20.13.0 From 163f4e6a4f9bd5a05967cf3190473f9700aebf8a Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 27 May 2024 12:41:47 +0200 Subject: [PATCH 38/57] Ignore gpg and .tgz files --- .gitignore | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitignore b/.gitignore index e1699c98..78c6fc53 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,9 @@ package.json-e .DS_Store *.swp dist + +# Decrypted private key we do not want to commit +.github/OSBotify-private-key.asc + +# Published package +*.tgz From cfaa9f2788038d5492a2088cac32dbe35e883cf2 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 27 May 2024 12:41:55 +0200 Subject: [PATCH 39/57] Update readme --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) 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 From 1f9d3f3f57985e11b6b090ab8ef274ab4a3d3b43 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 27 May 2024 16:41:49 +0200 Subject: [PATCH 40/57] fix user mention not deleting phone domain --- lib/ExpensiMark.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 4a6a1fe9..415f70fb 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -475,15 +475,18 @@ export default class ExpensiMark { }, { name: 'userMention', - regex: //gi, - replacement: (match, g1, offset, string, extras) => { - const accountToNameMap = extras.accountIdToName; - if (!accountToNameMap || !accountToNameMap[g1]) { - Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); - return '@Hidden'; + regex: /(?:)|(?:(.*?)<\/mention-user>)/gi, + replacement: (match, g1, g2, offset, string, extras) => { + if (g1) { + const accountToNameMap = extras.accountIdToName; + if (!accountToNameMap || !accountToNameMap[g1]) { + Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); + return '@Hidden'; + } + + return `@${extras.accountIdToName[g1]}`; } - - return `@${extras.accountIdToName[g1]}`; + return Str.removeSMSDomain(g2) }, }, ]; From 7cb4212723984ed1c511397c058ada83617a2583 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 27 May 2024 17:04:41 +0200 Subject: [PATCH 41/57] add test case to phone number mention --- __tests__/ExpensiMark-Markdown-test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/__tests__/ExpensiMark-Markdown-test.js b/__tests__/ExpensiMark-Markdown-test.js index 0f8e8831..8f446820 100644 --- a/__tests__/ExpensiMark-Markdown-test.js +++ b/__tests__/ExpensiMark-Markdown-test.js @@ -756,6 +756,10 @@ test('Mention user html to markdown', () => { testString = '@user@DOMAIN.com'; expect(parser.htmlToMarkdown(testString)).toBe('@user@DOMAIN.com'); + // When there is a phone number mention the sms domain `@expensify.sms`should be removed from returned string + testString = '@+311231231@expensify.sms'; + expect(parser.htmlToMarkdown(testString)).toBe('@+311231231'); + // When there is `accountID` and no `extras`, `@Hidden` should be returned testString = ''; expect(parser.htmlToMarkdown(testString)).toBe('@Hidden'); From 321e4a7f5e618000be812d5b7dc76d00f81084f9 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 28 May 2024 00:07:18 +0000 Subject: [PATCH 42/57] 2.0.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8c8c3f38..daf95dee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "expensify-common", - "version": "2.0.0", + "version": "2.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "expensify-common", - "version": "2.0.0", + "version": "2.0.1", "license": "MIT", "dependencies": { "classnames": "2.5.0", diff --git a/package.json b/package.json index a3b13a6c..4df2f8da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "expensify-common", - "version": "2.0.0", + "version": "2.0.1", "author": "Expensify, Inc.", "description": "Expensify libraries and components shared across different repos", "homepage": "https://expensify.com", From 9353c9347b58cb2f587a8d1bbe7b215a0779493b Mon Sep 17 00:00:00 2001 From: Tsaqif Date: Tue, 28 May 2024 09:14:17 +0700 Subject: [PATCH 43/57] Modify mention user and mention report extras field names Signed-off-by: Tsaqif --- lib/ExpensiMark.d.ts | 2 +- lib/ExpensiMark.js | 27 +++++++++++++++------------ 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/ExpensiMark.d.ts b/lib/ExpensiMark.d.ts index f431df7e..fad8f1b6 100644 --- a/lib/ExpensiMark.d.ts +++ b/lib/ExpensiMark.d.ts @@ -35,7 +35,7 @@ declare type Rule = { }; declare type ExtrasObject = { - reportIdToName?: Record; + reportIDToName?: Record; accountIDToName?: Record; }; export default class ExpensiMark { diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 74e96891..13601667 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -464,7 +464,7 @@ export default class ExpensiMark { name: 'reportMentions', regex: //gi, replacement: (match, g1, offset, string, extras) => { - const reportToNameMap = extras.reportIdToName; + const reportToNameMap = extras.reportIDToName; if (!reportToNameMap || !reportToNameMap[g1]) { Log.alert('[ExpensiMark] Missing report name', {reportID: g1}); return '#Hidden'; @@ -478,13 +478,13 @@ export default class ExpensiMark { regex: /(?:)|(?:(.*?)<\/mention-user>)/gi, replacement: (match, g1, g2, offset, string, extras) => { if (g1) { - const accountToNameMap = extras.accountIdToName; + const accountToNameMap = extras.accountIDToName; if (!accountToNameMap || !accountToNameMap[g1]) { Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); return '@Hidden'; } - return `@${extras.accountIdToName[g1]}`; + return `@${accountToNameMap[g1]}`; } return Str.removeSMSDomain(g2) }, @@ -536,7 +536,7 @@ export default class ExpensiMark { name: 'reportMentions', regex: //gi, replacement: (match, g1, offset, string, extras) => { - const reportToNameMap = extras.reportIdToName; + const reportToNameMap = extras.reportIDToName; if (!reportToNameMap || !reportToNameMap[g1]) { Log.alert('[ExpensiMark] Missing report name', {reportID: g1}); return '#Hidden'; @@ -547,15 +547,18 @@ export default class ExpensiMark { }, { name: 'userMention', - regex: //gi, - replacement: (match, g1, offset, string, extras) => { - const accountToNameMap = extras.accountIdToName; - if (!accountToNameMap || !accountToNameMap[g1]) { - Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); - return '@Hidden'; - } + regex: /(?:)|(?:(.*?)<\/mention-user>)/gi, + replacement: (match, g1, g2, offset, string, extras) => { + if (g1) { + const accountToNameMap = extras.accountIDToName; + if (!accountToNameMap || !accountToNameMap[g1]) { + Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); + return '@Hidden'; + } - return `@${extras.accountIdToName[g1]}`; + return `@${accountToNameMap[g1]}`; + } + return Str.removeSMSDomain(g2) }, }, { From 01bdce7453e6aeb4fb3b97ff5728c0d0a1e58724 Mon Sep 17 00:00:00 2001 From: Tsaqif Date: Tue, 28 May 2024 09:48:21 +0700 Subject: [PATCH 44/57] Retrigger checks Signed-off-by: Tsaqif From 7ca4ba11dcb95e1316443c512985782db1804998 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 28 May 2024 11:31:26 +0200 Subject: [PATCH 45/57] Fix Url import --- lib/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.ts b/lib/index.ts index 72d34ee4..dc9c5b20 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -15,7 +15,7 @@ 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 * as Url from './Url'; export {default as fastMerge} from './fastMerge'; export {default as Str} from './str'; export {default as TLD_REGEX} from './tlds'; From 4f8896c5c847144e965b9f834a9be6b584dc718e Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 28 May 2024 11:31:46 +0200 Subject: [PATCH 46/57] Implement isWindowAvailable and isNavigatorAvailable --- lib/utils.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 lib/utils.ts diff --git a/lib/utils.ts b/lib/utils.ts new file mode 100644 index 00000000..05f79512 --- /dev/null +++ b/lib/utils.ts @@ -0,0 +1,11 @@ +/** Checks if the `window` global object is available. */ +function isWindowAvailable(): boolean { + return typeof window !== 'undefined'; +} + +/** Checks if the `navigator` global object is available. */ +function isNavigatorAvailable(): boolean { + return typeof navigator !== 'undefined'; +} + +export {isWindowAvailable, isNavigatorAvailable}; From d64b534331c40c32b45e40cce00a638474be097a Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 28 May 2024 11:32:05 +0200 Subject: [PATCH 47/57] Check if window and navigator are available --- lib/API.jsx | 3 ++- lib/BrowserDetect.jsx | 10 ++++++++++ lib/Log.jsx | 5 +++-- lib/Network.jsx | 9 ++++++--- lib/PubSub.jsx | 3 ++- lib/mixins/PubSub.jsx | 3 ++- lib/mixins/extraClasses.js | 5 ++++- 7 files changed, 29 insertions(+), 9 deletions(-) diff --git a/lib/API.jsx b/lib/API.jsx index 41cdafa2..5a98186f 100644 --- a/lib/API.jsx +++ b/lib/API.jsx @@ -8,6 +8,7 @@ import _ from 'underscore'; // Use this deferred lib so we don't have a dependency on jQuery (so we can use this module in mobile) import {Deferred} from 'simply-deferred'; import ExpensifyAPIDeferred from './APIDeferred'; +import {isWindowAvailable} from './utils'; /** * @param {Network} network @@ -47,7 +48,7 @@ export default function API(network, args) { network .get('/revision.txt') .done((codeRevision) => { - if (codeRevision.trim() === window.CODE_REVISION) { + if (isWindowAvailable() && codeRevision.trim() === window.CODE_REVISION) { console.debug('Code revision is up to date'); promise.resolve(); } else { diff --git a/lib/BrowserDetect.jsx b/lib/BrowserDetect.jsx index 2f5bfb60..c67d2a79 100644 --- a/lib/BrowserDetect.jsx +++ b/lib/BrowserDetect.jsx @@ -1,3 +1,5 @@ +import {isNavigatorAvailable, isWindowAvailable} from './utils'; + const BROWSERS = { EDGE: 'Edge', CHROME: 'Chrome', @@ -13,6 +15,10 @@ const MOBILE_PLATFORMS = { }; function searchString() { + if (!isWindowAvailable() || !isNavigatorAvailable()) { + return ''; + } + const data = [ { string: navigator.userAgent, @@ -72,6 +78,10 @@ function searchString() { } function getMobileDevice() { + if (!isNavigatorAvailable()) { + return ''; + } + const data = [ { devices: ['iPhone', 'iPad', 'iPod'], diff --git a/lib/Log.jsx b/lib/Log.jsx index b114979b..bd55a1f9 100644 --- a/lib/Log.jsx +++ b/lib/Log.jsx @@ -3,6 +3,7 @@ import _ from 'underscore'; import API from './API'; import Network from './Network'; import Logger from './Logger'; +import {isWindowAvailable} from './utils'; /** * Network interface for logger. @@ -23,7 +24,7 @@ function serverLoggingCallback(logger, params) { * @param {String} message */ function clientLoggingCallback(message) { - if (typeof window.g_printableReport !== 'undefined' && window.g_printableReport === true) { + if (isWindowAvailable() && typeof window.g_printableReport !== 'undefined' && window.g_printableReport === true) { return; } @@ -35,5 +36,5 @@ function clientLoggingCallback(message) { export default new Logger({ serverLoggingCallback, clientLoggingCallback, - isDebug: window.DEBUG, + isDebug: isWindowAvailable() ? window.DEBUG : false, }); diff --git a/lib/Network.jsx b/lib/Network.jsx index 96897136..85c6e432 100644 --- a/lib/Network.jsx +++ b/lib/Network.jsx @@ -1,5 +1,6 @@ import $ from 'jquery'; import _ from 'underscore'; +import {isWindowAvailable} from './utils'; /** * Adds our API command to the URL so the API call is more easily identified in the @@ -40,9 +41,11 @@ export default function Network(endpoint) { } // Attach a listener to the event indicating that we're leaving a page - window.onbeforeunload = () => { - isNavigatingAway = true; - }; + if (isWindowAvailable()) { + window.onbeforeunload = () => { + isNavigatingAway = true; + }; + } return { /** diff --git a/lib/PubSub.jsx b/lib/PubSub.jsx index 31014c4a..28fc6ea7 100644 --- a/lib/PubSub.jsx +++ b/lib/PubSub.jsx @@ -1,6 +1,7 @@ import _ from 'underscore'; import has from 'lodash/has'; import Log from './Log'; +import {isWindowAvailable} from './utils'; /** * PubSub @@ -125,4 +126,4 @@ const PubSubModule = { }, }; -export default window !== undefined && window.PubSub ? window.PubSub : PubSubModule; +export default isWindowAvailable() && window.PubSub ? window.PubSub : PubSubModule; diff --git a/lib/mixins/PubSub.jsx b/lib/mixins/PubSub.jsx index 86855a5d..8be94395 100644 --- a/lib/mixins/PubSub.jsx +++ b/lib/mixins/PubSub.jsx @@ -1,7 +1,8 @@ import _ from 'underscore'; import PubSubModule from '../PubSub'; +import {isWindowAvailable} from '../utils'; -const PubSub = window.PubSub || PubSubModule; +const PubSub = (isWindowAvailable() && window.PubSub) || PubSubModule; /** * This mixin sets up automatic PubSub bindings which will be removed when diff --git a/lib/mixins/extraClasses.js b/lib/mixins/extraClasses.js index 5588bc6b..13acbfb1 100644 --- a/lib/mixins/extraClasses.js +++ b/lib/mixins/extraClasses.js @@ -22,9 +22,12 @@ * return
; * } */ + +import {isWindowAvailable} from '../utils'; + export default { propTypes: { - extraClasses: window.PropTypes.oneOfType([window.PropTypes.string, window.PropTypes.array, window.PropTypes.object]), + extraClasses: isWindowAvailable() && window.PropTypes.oneOfType([window.PropTypes.string, window.PropTypes.array, window.PropTypes.object]), }, UNSAFE_componentWillReceiveProps(nextProps) { From fd503c40554df9b5e46be8fa946673e558717805 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 28 May 2024 12:11:01 +0200 Subject: [PATCH 48/57] Rerun prettier workflow From 83ae253b4ff7bd3a386e72c0297de0b10c133344 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 28 May 2024 12:30:35 +0200 Subject: [PATCH 49/57] Fix prettier diff --- lib/ExpensiMark.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 74e96891..3f4decb2 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -483,10 +483,10 @@ export default class ExpensiMark { Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); return '@Hidden'; } - + return `@${extras.accountIdToName[g1]}`; } - return Str.removeSMSDomain(g2) + return Str.removeSMSDomain(g2); }, }, ]; From 50e7c5d0e3e51122ee11d3b72df128cf350a318b Mon Sep 17 00:00:00 2001 From: Tsaqif Date: Tue, 28 May 2024 20:42:47 +0700 Subject: [PATCH 50/57] Change extras field names in tests Signed-off-by: Tsaqif --- __tests__/ExpensiMark-HTMLToText-test.js | 4 ++-- __tests__/ExpensiMark-Markdown-test.js | 4 ++-- lib/ExpensiMark.js | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/__tests__/ExpensiMark-HTMLToText-test.js b/__tests__/ExpensiMark-HTMLToText-test.js index 39f5bebc..6757803b 100644 --- a/__tests__/ExpensiMark-HTMLToText-test.js +++ b/__tests__/ExpensiMark-HTMLToText-test.js @@ -151,7 +151,7 @@ test('Mention user html to text', () => { expect(parser.htmlToText(testString)).toBe('@Hidden'); const extras = { - accountIdToName: { + accountIDToName: { '1234': 'user@domain.com', }, }; @@ -180,7 +180,7 @@ test('Mention report html to text', () => { expect(parser.htmlToText(testString)).toBe('#Hidden'); const extras = { - reportIdToName: { + reportIDToName: { '1234': '#room-name', }, }; diff --git a/__tests__/ExpensiMark-Markdown-test.js b/__tests__/ExpensiMark-Markdown-test.js index 8f446820..a8bf1769 100644 --- a/__tests__/ExpensiMark-Markdown-test.js +++ b/__tests__/ExpensiMark-Markdown-test.js @@ -765,7 +765,7 @@ test('Mention user html to markdown', () => { expect(parser.htmlToMarkdown(testString)).toBe('@Hidden'); const extras = { - accountIdToName: { + accountIDToName: { '1234': 'user@domain.com', }, }; @@ -794,7 +794,7 @@ test('Mention report html to markdown', () => { expect(parser.htmlToText(testString)).toBe('#Hidden'); const extras = { - reportIdToName: { + reportIDToName: { '1234': '#room-name', }, }; diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index 13601667..ca47ade9 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -483,10 +483,10 @@ export default class ExpensiMark { Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); return '@Hidden'; } - + return `@${accountToNameMap[g1]}`; } - return Str.removeSMSDomain(g2) + return Str.removeSMSDomain(g2); }, }, ]; @@ -558,7 +558,7 @@ export default class ExpensiMark { return `@${accountToNameMap[g1]}`; } - return Str.removeSMSDomain(g2) + return Str.removeSMSDomain(g2); }, }, { From b30975dc16535a2a5e88c0bf1ed2a266004d0e93 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 28 May 2024 17:18:39 +0200 Subject: [PATCH 51/57] Fix getMobileDevice on ios and android --- lib/BrowserDetect.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/BrowserDetect.jsx b/lib/BrowserDetect.jsx index c67d2a79..63894f96 100644 --- a/lib/BrowserDetect.jsx +++ b/lib/BrowserDetect.jsx @@ -78,7 +78,7 @@ function searchString() { } function getMobileDevice() { - if (!isNavigatorAvailable()) { + if (!isNavigatorAvailable() || !navigator.userAgent) { return ''; } From 1137c3f640c41bc72997d4da2c05ac058d60ab6b Mon Sep 17 00:00:00 2001 From: Tsaqif Date: Tue, 28 May 2024 22:30:44 +0700 Subject: [PATCH 52/57] revert some changes Signed-off-by: Tsaqif --- lib/ExpensiMark.js | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/ExpensiMark.js b/lib/ExpensiMark.js index ca47ade9..b72f2054 100644 --- a/lib/ExpensiMark.js +++ b/lib/ExpensiMark.js @@ -484,7 +484,7 @@ export default class ExpensiMark { return '@Hidden'; } - return `@${accountToNameMap[g1]}`; + return `@${extras.accountIDToName[g1]}`; } return Str.removeSMSDomain(g2); }, @@ -547,18 +547,14 @@ export default class ExpensiMark { }, { name: 'userMention', - regex: /(?:)|(?:(.*?)<\/mention-user>)/gi, - replacement: (match, g1, g2, offset, string, extras) => { - if (g1) { - const accountToNameMap = extras.accountIDToName; - if (!accountToNameMap || !accountToNameMap[g1]) { - Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); - return '@Hidden'; - } - - return `@${accountToNameMap[g1]}`; + regex: //gi, + replacement: (match, g1, offset, string, extras) => { + const accountToNameMap = extras.accountIDToName; + if (!accountToNameMap || !accountToNameMap[g1]) { + Log.alert('[ExpensiMark] Missing account name', {accountID: g1}); + return '@Hidden'; } - return Str.removeSMSDomain(g2); + return `@${extras.accountIDToName[g1]}`; }, }, { From c5ad05379f301971657abf16410d9203f3ae8f5f Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 28 May 2024 15:31:25 +0000 Subject: [PATCH 53/57] 2.0.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index daf95dee..2549f9f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "expensify-common", - "version": "2.0.1", + "version": "2.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "expensify-common", - "version": "2.0.1", + "version": "2.0.2", "license": "MIT", "dependencies": { "classnames": "2.5.0", diff --git a/package.json b/package.json index 4df2f8da..75bc0d6a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "expensify-common", - "version": "2.0.1", + "version": "2.0.2", "author": "Expensify, Inc.", "description": "Expensify libraries and components shared across different repos", "homepage": "https://expensify.com", From 484b980cec748a4f69bb28f00f35e4d0d246b779 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 28 May 2024 16:02:25 +0000 Subject: [PATCH 54/57] 2.0.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2549f9f2..880b8d7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "expensify-common", - "version": "2.0.2", + "version": "2.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "expensify-common", - "version": "2.0.2", + "version": "2.0.3", "license": "MIT", "dependencies": { "classnames": "2.5.0", diff --git a/package.json b/package.json index 75bc0d6a..f920d0a9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "expensify-common", - "version": "2.0.2", + "version": "2.0.3", "author": "Expensify, Inc.", "description": "Expensify libraries and components shared across different repos", "homepage": "https://expensify.com", From b805fed6887aa94a7787757fe7f7fd12ab6a6dda Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 28 May 2024 21:30:38 +0000 Subject: [PATCH 55/57] 2.0.4 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 53b57c83..15510924 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "expensify-common", - "version": "2.0.3", + "version": "2.0.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "expensify-common", - "version": "2.0.3", + "version": "2.0.4", "license": "MIT", "dependencies": { "awesome-phonenumber": "^5.4.0", diff --git a/package.json b/package.json index 405d5f8c..2d775c63 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "expensify-common", - "version": "2.0.3", + "version": "2.0.4", "author": "Expensify, Inc.", "description": "Expensify libraries and components shared across different repos", "homepage": "https://expensify.com", From 32e14db3bb816c216dbbde5170e405a2b881af12 Mon Sep 17 00:00:00 2001 From: dragnoir Date: Wed, 29 May 2024 08:54:56 +0100 Subject: [PATCH 56/57] fix typo --- __tests__/ExpensiMark-Markdown-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__tests__/ExpensiMark-Markdown-test.js b/__tests__/ExpensiMark-Markdown-test.js index 00a0173f..093f5ca5 100644 --- a/__tests__/ExpensiMark-Markdown-test.js +++ b/__tests__/ExpensiMark-Markdown-test.js @@ -503,7 +503,7 @@ test('double quotes in same line', () => { expect(parser.htmlToMarkdown(testString)).toBe(resultString); }); -test('tripple quotes in same line', () => { +test('triple quotes in same line', () => { const testString = '
line 1
'; const resultString = '>>> line 1'; expect(parser.htmlToMarkdown(testString)).toBe(resultString); From 05c03d415268019284103e3fb4dc0c09107bbb46 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 29 May 2024 08:10:19 +0000 Subject: [PATCH 57/57] 2.0.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 15510924..19a4bcde 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "expensify-common", - "version": "2.0.4", + "version": "2.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "expensify-common", - "version": "2.0.4", + "version": "2.0.5", "license": "MIT", "dependencies": { "awesome-phonenumber": "^5.4.0", diff --git a/package.json b/package.json index 2d775c63..c32b1999 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "expensify-common", - "version": "2.0.4", + "version": "2.0.5", "author": "Expensify, Inc.", "description": "Expensify libraries and components shared across different repos", "homepage": "https://expensify.com",