diff --git a/.eslintignore b/.eslintignore index aa8b769dfede..3d966d096add 100644 --- a/.eslintignore +++ b/.eslintignore @@ -10,3 +10,4 @@ docs/vendor/** docs/assets/** web/gtm.js **/.expo/** +src/libs/SearchParser/searchParser.js diff --git a/.eslintrc.js b/.eslintrc.js index 198620c70b0f..cb1219533278 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -66,6 +66,15 @@ const restrictedImportPaths = [ "For 'ExpensiMark', please use '@libs/Parser' instead.", ].join('\n'), }, + { + name: 'lodash/memoize', + message: "Please use '@src/libs/memoize' instead.", + }, + { + name: 'lodash', + importNames: ['memoize'], + message: "Please use '@src/libs/memoize' instead.", + }, ]; const restrictedImportPatterns = [ @@ -97,7 +106,7 @@ module.exports = { 'plugin:@typescript-eslint/recommended-type-checked', 'plugin:@typescript-eslint/stylistic-type-checked', 'plugin:you-dont-need-lodash-underscore/all', - 'prettier', + 'plugin:prettier/recommended', ], plugins: ['@typescript-eslint', 'jsdoc', 'you-dont-need-lodash-underscore', 'react-native-a11y', 'react', 'testing-library', 'eslint-plugin-react-compiler'], ignorePatterns: ['lib/**'], diff --git a/.github/.eslintrc.js b/.github/.eslintrc.js index d6d39822b737..d1f75405f7a2 100644 --- a/.github/.eslintrc.js +++ b/.github/.eslintrc.js @@ -6,5 +6,6 @@ module.exports = { '@lwc/lwc/no-async-await': 'off', 'no-await-in-loop': 'off', 'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'], + 'no-continue': 'off', }, }; diff --git a/.github/actions/composite/buildAndroidE2EAPK/action.yml b/.github/actions/composite/buildAndroidE2EAPK/action.yml index 47e13f6313a0..cfce0d3ec7d8 100644 --- a/.github/actions/composite/buildAndroidE2EAPK/action.yml +++ b/.github/actions/composite/buildAndroidE2EAPK/action.yml @@ -53,7 +53,7 @@ runs: distribution: "oracle" java-version: "17" - - uses: ruby/setup-ruby@a05e47355e80e57b9a67566a813648fa67d92011 + - uses: ruby/setup-ruby@v1.187.0 with: ruby-version: "2.7" bundler-cache: true @@ -72,9 +72,11 @@ runs: - name: Build APK run: npm run ${{ inputs.PACKAGE_SCRIPT_NAME }} shell: bash + env: + RUBYOPT: '-rostruct' - name: Upload APK - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 + uses: actions/upload-artifact@v4 with: name: ${{ inputs.ARTIFACT_NAME }} path: ${{ inputs.APP_OUTPUT_PATH }} diff --git a/.github/actions/javascript/authorChecklist/index.js b/.github/actions/javascript/authorChecklist/index.js index e9861f8737a6..9b4b5dac69f5 100644 --- a/.github/actions/javascript/authorChecklist/index.js +++ b/.github/actions/javascript/authorChecklist/index.js @@ -17016,7 +17016,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -17024,6 +17038,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -17400,12 +17417,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/awaitStagingDeploys/index.js b/.github/actions/javascript/awaitStagingDeploys/index.js index 6ec9bbf06aeb..cfbe438022a0 100644 --- a/.github/actions/javascript/awaitStagingDeploys/index.js +++ b/.github/actions/javascript/awaitStagingDeploys/index.js @@ -12257,7 +12257,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -12265,6 +12279,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -12641,12 +12658,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/checkDeployBlockers/index.js b/.github/actions/javascript/checkDeployBlockers/index.js index c6518f4e61c9..e0cb48b0a9c4 100644 --- a/.github/actions/javascript/checkDeployBlockers/index.js +++ b/.github/actions/javascript/checkDeployBlockers/index.js @@ -11540,7 +11540,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11548,6 +11562,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11924,12 +11941,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js index 260dd0847c8d..d9fa61b08448 100644 --- a/.github/actions/javascript/createOrUpdateStagingDeploy/index.js +++ b/.github/actions/javascript/createOrUpdateStagingDeploy/index.js @@ -14352,7 +14352,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -14360,6 +14374,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -14954,12 +14971,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/getArtifactInfo/index.js b/.github/actions/javascript/getArtifactInfo/index.js index cde9cf8748db..c1cca94b6cbd 100644 --- a/.github/actions/javascript/getArtifactInfo/index.js +++ b/.github/actions/javascript/getArtifactInfo/index.js @@ -11501,7 +11501,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11509,6 +11523,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11885,12 +11902,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/getDeployPullRequestList/getDeployPullRequestList.ts b/.github/actions/javascript/getDeployPullRequestList/getDeployPullRequestList.ts index 08519c40413b..c15036c93232 100644 --- a/.github/actions/javascript/getDeployPullRequestList/getDeployPullRequestList.ts +++ b/.github/actions/javascript/getDeployPullRequestList/getDeployPullRequestList.ts @@ -40,10 +40,15 @@ async function run() { }) ).data.jobs.some((job) => job.name.startsWith('Build and deploy') && job.conclusion === 'success') ) { + console.log(`Deploy was not a success: ${lastSuccessfulDeploy.html_url}, looking at the next one`); lastSuccessfulDeploy = completedDeploys.shift(); } - const priorTag = completedDeploys[0].head_branch; + if (!lastSuccessfulDeploy) { + throw new Error('Could not find a prior successful deploy'); + } + + const priorTag = lastSuccessfulDeploy.head_branch; console.log(`Looking for PRs deployed to ${deployEnv} between ${priorTag} and ${inputTag}`); const prList = await GitUtils.getPullRequestsMergedBetween(priorTag ?? '', inputTag); console.log('Found the pull request list: ', prList); diff --git a/.github/actions/javascript/getDeployPullRequestList/index.js b/.github/actions/javascript/getDeployPullRequestList/index.js index cfe512076ecd..3173dd2358eb 100644 --- a/.github/actions/javascript/getDeployPullRequestList/index.js +++ b/.github/actions/javascript/getDeployPullRequestList/index.js @@ -11529,9 +11529,13 @@ async function run() { run_id: lastSuccessfulDeploy.id, filter: 'latest', })).data.jobs.some((job) => job.name.startsWith('Build and deploy') && job.conclusion === 'success')) { + console.log(`Deploy was not a success: ${lastSuccessfulDeploy.html_url}, looking at the next one`); lastSuccessfulDeploy = completedDeploys.shift(); } - const priorTag = completedDeploys[0].head_branch; + if (!lastSuccessfulDeploy) { + throw new Error('Could not find a prior successful deploy'); + } + const priorTag = lastSuccessfulDeploy.head_branch; console.log(`Looking for PRs deployed to ${deployEnv} between ${priorTag} and ${inputTag}`); const prList = await GitUtils_1.default.getPullRequestsMergedBetween(priorTag ?? '', inputTag); console.log('Found the pull request list: ', prList); @@ -11631,7 +11635,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', + }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11639,6 +11657,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -12233,12 +12254,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/getPreviousVersion/index.js b/.github/actions/javascript/getPreviousVersion/index.js index 29d02cc4dbac..aff2a13da163 100644 --- a/.github/actions/javascript/getPreviousVersion/index.js +++ b/.github/actions/javascript/getPreviousVersion/index.js @@ -2768,7 +2768,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -2776,6 +2790,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; diff --git a/.github/actions/javascript/getPullRequestDetails/index.js b/.github/actions/javascript/getPullRequestDetails/index.js index 8fa081de17fa..f1c2054cca1d 100644 --- a/.github/actions/javascript/getPullRequestDetails/index.js +++ b/.github/actions/javascript/getPullRequestDetails/index.js @@ -11603,7 +11603,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11611,6 +11625,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11987,12 +12004,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/getReleaseBody/getReleaseBody.ts b/.github/actions/javascript/getReleaseBody/getReleaseBody.ts index 10024fedc5e7..3d8bd90599ed 100644 --- a/.github/actions/javascript/getReleaseBody/getReleaseBody.ts +++ b/.github/actions/javascript/getReleaseBody/getReleaseBody.ts @@ -1,12 +1,32 @@ import * as core from '@actions/core'; +import type {components as OctokitComponents} from '@octokit/openapi-types'; import * as ActionUtils from '@github/libs/ActionUtils'; import GithubUtils from '@github/libs/GithubUtils'; +type GitHubPR = OctokitComponents['schemas']['pull-request-simple']; + // Parse the stringified JSON array of PR numbers, and cast each from String -> Number const PRList = ActionUtils.getJSONInput('PR_LIST', {required: true}) as number[]; console.log('Got PR list: ', String(PRList)); -const releaseBody = GithubUtils.getReleaseBody(PRList); -console.log(`Generated release body: ${releaseBody}`); +/** + * Generate the well-formatted body of a production release. + */ +function getReleaseBody(pullRequests: GitHubPR[]): string { + return pullRequests.map((pr) => `- ${pr.title} by ${pr.user?.login ?? 'unknown'} in ${pr.html_url}`).join('\r\n'); +} + +async function run() { + const allPRs = await GithubUtils.fetchAllPullRequests(PRList); + if (!allPRs) { + core.setFailed(`something went wrong getting PRList ${JSON.stringify(PRList)}`); + return; + } + const releaseBody = getReleaseBody(allPRs); + console.log(`Generated release body: ${releaseBody}`); + core.setOutput('RELEASE_BODY', releaseBody); +} -core.setOutput('RELEASE_BODY', releaseBody); +if (require.main === module) { + run(); +} diff --git a/.github/actions/javascript/getReleaseBody/index.js b/.github/actions/javascript/getReleaseBody/index.js index 81b73876db95..2cce52e62787 100644 --- a/.github/actions/javascript/getReleaseBody/index.js +++ b/.github/actions/javascript/getReleaseBody/index.js @@ -11459,9 +11459,25 @@ const GithubUtils_1 = __importDefault(__nccwpck_require__(9296)); // Parse the stringified JSON array of PR numbers, and cast each from String -> Number const PRList = ActionUtils.getJSONInput('PR_LIST', { required: true }); console.log('Got PR list: ', String(PRList)); -const releaseBody = GithubUtils_1.default.getReleaseBody(PRList); -console.log(`Generated release body: ${releaseBody}`); -core.setOutput('RELEASE_BODY', releaseBody); +/** + * Generate the well-formatted body of a production release. + */ +function getReleaseBody(pullRequests) { + return pullRequests.map((pr) => `- ${pr.title} by ${pr.user?.login ?? 'unknown'} in ${pr.html_url}`).join('\r\n'); +} +async function run() { + const allPRs = await GithubUtils_1.default.fetchAllPullRequests(PRList); + if (!allPRs) { + core.setFailed(`something went wrong getting PRList ${JSON.stringify(PRList)}`); + return; + } + const releaseBody = getReleaseBody(allPRs); + console.log(`Generated release body: ${releaseBody}`); + core.setOutput('RELEASE_BODY', releaseBody); +} +if (require.main === require.cache[eval('__filename')]) { + run(); +} /***/ }), @@ -11547,7 +11563,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11555,6 +11585,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11931,12 +11964,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/isStagingDeployLocked/index.js b/.github/actions/javascript/isStagingDeployLocked/index.js index feccd44beb1a..19acda9b7474 100644 --- a/.github/actions/javascript/isStagingDeployLocked/index.js +++ b/.github/actions/javascript/isStagingDeployLocked/index.js @@ -11501,7 +11501,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11509,6 +11523,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11885,12 +11902,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/markPullRequestsAsDeployed/index.js b/.github/actions/javascript/markPullRequestsAsDeployed/index.js index ba474583a2fe..06d569d6fb5a 100644 --- a/.github/actions/javascript/markPullRequestsAsDeployed/index.js +++ b/.github/actions/javascript/markPullRequestsAsDeployed/index.js @@ -11708,7 +11708,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11716,6 +11730,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -12092,12 +12109,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/postTestBuildComment/index.js b/.github/actions/javascript/postTestBuildComment/index.js index 68f3b11f45f1..6c47718584ce 100644 --- a/.github/actions/javascript/postTestBuildComment/index.js +++ b/.github/actions/javascript/postTestBuildComment/index.js @@ -11600,7 +11600,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11608,6 +11622,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11984,12 +12001,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/proposalPoliceComment/action.yml b/.github/actions/javascript/proposalPoliceComment/action.yml new file mode 100644 index 000000000000..ab649f9bd44f --- /dev/null +++ b/.github/actions/javascript/proposalPoliceComment/action.yml @@ -0,0 +1,15 @@ +name: 'ProposalPoliceā„¢ Comment Check Script' +description: 'Verifies whether a proposal comment follows the template OR an updated proposal had substantial changes' +inputs: + GITHUB_TOKEN: + description: 'Auth token for New Expensify Github' + required: true + PROPOSAL_POLICE_API_KEY: + description: 'OpenAI API key for accessing AI services' + required: true + PROPOSAL_POLICE_ASSISTANT_ID: + description: 'OpenAI Assistant ID for personalized AI assistant' + required: true +runs: + using: 'node20' + main: './index.js' diff --git a/.github/actions/javascript/proposalPoliceComment/index.js b/.github/actions/javascript/proposalPoliceComment/index.js new file mode 100644 index 000000000000..49dbe3b52cf7 --- /dev/null +++ b/.github/actions/javascript/proposalPoliceComment/index.js @@ -0,0 +1,25893 @@ +/** + * NOTE: This is a compiled file. DO NOT directly edit this file. + */ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ 7351: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.issue = exports.issueCommand = void 0; +const os = __importStar(__nccwpck_require__(2037)); +const utils_1 = __nccwpck_require__(5278); +/** + * Commands + * + * Command Format: + * ::name key=value,key=value::message + * + * Examples: + * ::warning::This is the message + * ::set-env name=MY_VAR::some value + */ +function issueCommand(command, properties, message) { + const cmd = new Command(command, properties, message); + process.stdout.write(cmd.toString() + os.EOL); +} +exports.issueCommand = issueCommand; +function issue(name, message = '') { + issueCommand(name, {}, message); +} +exports.issue = issue; +const CMD_STRING = '::'; +class Command { + constructor(command, properties, message) { + if (!command) { + command = 'missing.command'; + } + this.command = command; + this.properties = properties; + this.message = message; + } + toString() { + let cmdStr = CMD_STRING + this.command; + if (this.properties && Object.keys(this.properties).length > 0) { + cmdStr += ' '; + let first = true; + for (const key in this.properties) { + if (this.properties.hasOwnProperty(key)) { + const val = this.properties[key]; + if (val) { + if (first) { + first = false; + } + else { + cmdStr += ','; + } + cmdStr += `${key}=${escapeProperty(val)}`; + } + } + } + } + cmdStr += `${CMD_STRING}${escapeData(this.message)}`; + return cmdStr; + } +} +function escapeData(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A'); +} +function escapeProperty(s) { + return utils_1.toCommandValue(s) + .replace(/%/g, '%25') + .replace(/\r/g, '%0D') + .replace(/\n/g, '%0A') + .replace(/:/g, '%3A') + .replace(/,/g, '%2C'); +} +//# sourceMappingURL=command.js.map + +/***/ }), + +/***/ 2186: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getIDToken = exports.getState = exports.saveState = exports.group = exports.endGroup = exports.startGroup = exports.info = exports.notice = exports.warning = exports.error = exports.debug = exports.isDebug = exports.setFailed = exports.setCommandEcho = exports.setOutput = exports.getBooleanInput = exports.getMultilineInput = exports.getInput = exports.addPath = exports.setSecret = exports.exportVariable = exports.ExitCode = void 0; +const command_1 = __nccwpck_require__(7351); +const file_command_1 = __nccwpck_require__(717); +const utils_1 = __nccwpck_require__(5278); +const os = __importStar(__nccwpck_require__(2037)); +const path = __importStar(__nccwpck_require__(1017)); +const oidc_utils_1 = __nccwpck_require__(8041); +/** + * The code to exit an action + */ +var ExitCode; +(function (ExitCode) { + /** + * A code indicating that the action was successful + */ + ExitCode[ExitCode["Success"] = 0] = "Success"; + /** + * A code indicating that the action was a failure + */ + ExitCode[ExitCode["Failure"] = 1] = "Failure"; +})(ExitCode = exports.ExitCode || (exports.ExitCode = {})); +//----------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------- +/** + * Sets env variable for this action and future actions in the job + * @param name the name of the variable to set + * @param val the value of the variable. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function exportVariable(name, val) { + const convertedVal = utils_1.toCommandValue(val); + process.env[name] = convertedVal; + const filePath = process.env['GITHUB_ENV'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); + } + command_1.issueCommand('set-env', { name }, convertedVal); +} +exports.exportVariable = exportVariable; +/** + * Registers a secret which will get masked from logs + * @param secret value of the secret + */ +function setSecret(secret) { + command_1.issueCommand('add-mask', {}, secret); +} +exports.setSecret = setSecret; +/** + * Prepends inputPath to the PATH (for this action and future actions) + * @param inputPath + */ +function addPath(inputPath) { + const filePath = process.env['GITHUB_PATH'] || ''; + if (filePath) { + file_command_1.issueFileCommand('PATH', inputPath); + } + else { + command_1.issueCommand('add-path', {}, inputPath); + } + process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; +} +exports.addPath = addPath; +/** + * Gets the value of an input. + * Unless trimWhitespace is set to false in InputOptions, the value is also trimmed. + * Returns an empty string if the value is not defined. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string + */ +function getInput(name, options) { + const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; + if (options && options.required && !val) { + throw new Error(`Input required and not supplied: ${name}`); + } + if (options && options.trimWhitespace === false) { + return val; + } + return val.trim(); +} +exports.getInput = getInput; +/** + * Gets the values of an multiline input. Each value is also trimmed. + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns string[] + * + */ +function getMultilineInput(name, options) { + const inputs = getInput(name, options) + .split('\n') + .filter(x => x !== ''); + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); +} +exports.getMultilineInput = getMultilineInput; +/** + * Gets the input value of the boolean type in the YAML 1.2 "core schema" specification. + * Support boolean input list: `true | True | TRUE | false | False | FALSE` . + * The return value is also in boolean type. + * ref: https://yaml.org/spec/1.2/spec.html#id2804923 + * + * @param name name of the input to get + * @param options optional. See InputOptions. + * @returns boolean + */ +function getBooleanInput(name, options) { + const trueValue = ['true', 'True', 'TRUE']; + const falseValue = ['false', 'False', 'FALSE']; + const val = getInput(name, options); + if (trueValue.includes(val)) + return true; + if (falseValue.includes(val)) + return false; + throw new TypeError(`Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` + + `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``); +} +exports.getBooleanInput = getBooleanInput; +/** + * Sets the value of an output. + * + * @param name name of the output to set + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); + } + process.stdout.write(os.EOL); + command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); +} +exports.setOutput = setOutput; +/** + * Enables or disables the echoing of commands into stdout for the rest of the step. + * Echoing is disabled by default if ACTIONS_STEP_DEBUG is not set. + * + */ +function setCommandEcho(enabled) { + command_1.issue('echo', enabled ? 'on' : 'off'); +} +exports.setCommandEcho = setCommandEcho; +//----------------------------------------------------------------------- +// Results +//----------------------------------------------------------------------- +/** + * Sets the action status to failed. + * When the action exits it will be with an exit code of 1 + * @param message add error issue message + */ +function setFailed(message) { + process.exitCode = ExitCode.Failure; + error(message); +} +exports.setFailed = setFailed; +//----------------------------------------------------------------------- +// Logging Commands +//----------------------------------------------------------------------- +/** + * Gets whether Actions Step Debug is on or not + */ +function isDebug() { + return process.env['RUNNER_DEBUG'] === '1'; +} +exports.isDebug = isDebug; +/** + * Writes debug message to user log + * @param message debug message + */ +function debug(message) { + command_1.issueCommand('debug', {}, message); +} +exports.debug = debug; +/** + * Adds an error issue + * @param message error issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function error(message, properties = {}) { + command_1.issueCommand('error', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.error = error; +/** + * Adds a warning issue + * @param message warning issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function warning(message, properties = {}) { + command_1.issueCommand('warning', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.warning = warning; +/** + * Adds a notice issue + * @param message notice issue message. Errors will be converted to string via toString() + * @param properties optional properties to add to the annotation. + */ +function notice(message, properties = {}) { + command_1.issueCommand('notice', utils_1.toCommandProperties(properties), message instanceof Error ? message.toString() : message); +} +exports.notice = notice; +/** + * Writes info to log with console.log. + * @param message info message + */ +function info(message) { + process.stdout.write(message + os.EOL); +} +exports.info = info; +/** + * Begin an output group. + * + * Output until the next `groupEnd` will be foldable in this group + * + * @param name The name of the output group + */ +function startGroup(name) { + command_1.issue('group', name); +} +exports.startGroup = startGroup; +/** + * End an output group. + */ +function endGroup() { + command_1.issue('endgroup'); +} +exports.endGroup = endGroup; +/** + * Wrap an asynchronous function call in a group. + * + * Returns the same type as the function itself. + * + * @param name The name of the group + * @param fn The function to wrap in the group + */ +function group(name, fn) { + return __awaiter(this, void 0, void 0, function* () { + startGroup(name); + let result; + try { + result = yield fn(); + } + finally { + endGroup(); + } + return result; + }); +} +exports.group = group; +//----------------------------------------------------------------------- +// Wrapper action state +//----------------------------------------------------------------------- +/** + * Saves state for current action, the state can only be retrieved by this action's post job execution. + * + * @param name name of the state to store + * @param value value to store. Non-string values will be converted to a string via JSON.stringify + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function saveState(name, value) { + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); + } + command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); +} +exports.saveState = saveState; +/** + * Gets the value of an state set by this action's main execution. + * + * @param name name of the state to get + * @returns string + */ +function getState(name) { + return process.env[`STATE_${name}`] || ''; +} +exports.getState = getState; +function getIDToken(aud) { + return __awaiter(this, void 0, void 0, function* () { + return yield oidc_utils_1.OidcClient.getIDToken(aud); + }); +} +exports.getIDToken = getIDToken; +/** + * Summary exports + */ +var summary_1 = __nccwpck_require__(1327); +Object.defineProperty(exports, "summary", ({ enumerable: true, get: function () { return summary_1.summary; } })); +/** + * @deprecated use core.summary + */ +var summary_2 = __nccwpck_require__(1327); +Object.defineProperty(exports, "markdownSummary", ({ enumerable: true, get: function () { return summary_2.markdownSummary; } })); +/** + * Path exports + */ +var path_utils_1 = __nccwpck_require__(2981); +Object.defineProperty(exports, "toPosixPath", ({ enumerable: true, get: function () { return path_utils_1.toPosixPath; } })); +Object.defineProperty(exports, "toWin32Path", ({ enumerable: true, get: function () { return path_utils_1.toWin32Path; } })); +Object.defineProperty(exports, "toPlatformPath", ({ enumerable: true, get: function () { return path_utils_1.toPlatformPath; } })); +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 717: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// For internal use, subject to change. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +const fs = __importStar(__nccwpck_require__(7147)); +const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(5840); +const utils_1 = __nccwpck_require__(5278); +function issueFileCommand(command, message) { + const filePath = process.env[`GITHUB_${command}`]; + if (!filePath) { + throw new Error(`Unable to find environment variable for file command ${command}`); + } + if (!fs.existsSync(filePath)) { + throw new Error(`Missing file at path: ${filePath}`); + } + fs.appendFileSync(filePath, `${utils_1.toCommandValue(message)}${os.EOL}`, { + encoding: 'utf8' + }); +} +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + const convertedValue = utils_1.toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; +//# sourceMappingURL=file-command.js.map + +/***/ }), + +/***/ 8041: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.OidcClient = void 0; +const http_client_1 = __nccwpck_require__(6255); +const auth_1 = __nccwpck_require__(5526); +const core_1 = __nccwpck_require__(2186); +class OidcClient { + static createHttpClient(allowRetry = true, maxRetry = 10) { + const requestOptions = { + allowRetries: allowRetry, + maxRetries: maxRetry + }; + return new http_client_1.HttpClient('actions/oidc-client', [new auth_1.BearerCredentialHandler(OidcClient.getRequestToken())], requestOptions); + } + static getRequestToken() { + const token = process.env['ACTIONS_ID_TOKEN_REQUEST_TOKEN']; + if (!token) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_TOKEN env variable'); + } + return token; + } + static getIDTokenUrl() { + const runtimeUrl = process.env['ACTIONS_ID_TOKEN_REQUEST_URL']; + if (!runtimeUrl) { + throw new Error('Unable to get ACTIONS_ID_TOKEN_REQUEST_URL env variable'); + } + return runtimeUrl; + } + static getCall(id_token_url) { + var _a; + return __awaiter(this, void 0, void 0, function* () { + const httpclient = OidcClient.createHttpClient(); + const res = yield httpclient + .getJson(id_token_url) + .catch(error => { + throw new Error(`Failed to get ID Token. \n + Error Code : ${error.statusCode}\n + Error Message: ${error.result.message}`); + }); + const id_token = (_a = res.result) === null || _a === void 0 ? void 0 : _a.value; + if (!id_token) { + throw new Error('Response json body do not have ID Token field'); + } + return id_token; + }); + } + static getIDToken(audience) { + return __awaiter(this, void 0, void 0, function* () { + try { + // New ID Token is requested from action service + let id_token_url = OidcClient.getIDTokenUrl(); + if (audience) { + const encodedAudience = encodeURIComponent(audience); + id_token_url = `${id_token_url}&audience=${encodedAudience}`; + } + core_1.debug(`ID token url is ${id_token_url}`); + const id_token = yield OidcClient.getCall(id_token_url); + core_1.setSecret(id_token); + return id_token; + } + catch (error) { + throw new Error(`Error message: ${error.message}`); + } + }); + } +} +exports.OidcClient = OidcClient; +//# sourceMappingURL=oidc-utils.js.map + +/***/ }), + +/***/ 2981: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0; +const path = __importStar(__nccwpck_require__(1017)); +/** + * toPosixPath converts the given path to the posix form. On Windows, \\ will be + * replaced with /. + * + * @param pth. Path to transform. + * @return string Posix path. + */ +function toPosixPath(pth) { + return pth.replace(/[\\]/g, '/'); +} +exports.toPosixPath = toPosixPath; +/** + * toWin32Path converts the given path to the win32 form. On Linux, / will be + * replaced with \\. + * + * @param pth. Path to transform. + * @return string Win32 path. + */ +function toWin32Path(pth) { + return pth.replace(/[/]/g, '\\'); +} +exports.toWin32Path = toWin32Path; +/** + * toPlatformPath converts the given path to a platform-specific path. It does + * this by replacing instances of / and \ with the platform-specific path + * separator. + * + * @param pth The path to platformize. + * @return string The platform-specific path. + */ +function toPlatformPath(pth) { + return pth.replace(/[/\\]/g, path.sep); +} +exports.toPlatformPath = toPlatformPath; +//# sourceMappingURL=path-utils.js.map + +/***/ }), + +/***/ 1327: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.summary = exports.markdownSummary = exports.SUMMARY_DOCS_URL = exports.SUMMARY_ENV_VAR = void 0; +const os_1 = __nccwpck_require__(2037); +const fs_1 = __nccwpck_require__(7147); +const { access, appendFile, writeFile } = fs_1.promises; +exports.SUMMARY_ENV_VAR = 'GITHUB_STEP_SUMMARY'; +exports.SUMMARY_DOCS_URL = 'https://docs.github.com/actions/using-workflows/workflow-commands-for-github-actions#adding-a-job-summary'; +class Summary { + constructor() { + this._buffer = ''; + } + /** + * Finds the summary file path from the environment, rejects if env var is not found or file does not exist + * Also checks r/w permissions. + * + * @returns step summary file path + */ + filePath() { + return __awaiter(this, void 0, void 0, function* () { + if (this._filePath) { + return this._filePath; + } + const pathFromEnv = process.env[exports.SUMMARY_ENV_VAR]; + if (!pathFromEnv) { + throw new Error(`Unable to find environment variable for $${exports.SUMMARY_ENV_VAR}. Check if your runtime environment supports job summaries.`); + } + try { + yield access(pathFromEnv, fs_1.constants.R_OK | fs_1.constants.W_OK); + } + catch (_a) { + throw new Error(`Unable to access summary file: '${pathFromEnv}'. Check if the file has correct read/write permissions.`); + } + this._filePath = pathFromEnv; + return this._filePath; + }); + } + /** + * Wraps content in an HTML tag, adding any HTML attributes + * + * @param {string} tag HTML tag to wrap + * @param {string | null} content content within the tag + * @param {[attribute: string]: string} attrs key-value list of HTML attributes to add + * + * @returns {string} content wrapped in HTML element + */ + wrap(tag, content, attrs = {}) { + const htmlAttrs = Object.entries(attrs) + .map(([key, value]) => ` ${key}="${value}"`) + .join(''); + if (!content) { + return `<${tag}${htmlAttrs}>`; + } + return `<${tag}${htmlAttrs}>${content}`; + } + /** + * Writes text in the buffer to the summary buffer file and empties buffer. Will append by default. + * + * @param {SummaryWriteOptions} [options] (optional) options for write operation + * + * @returns {Promise} summary instance + */ + write(options) { + return __awaiter(this, void 0, void 0, function* () { + const overwrite = !!(options === null || options === void 0 ? void 0 : options.overwrite); + const filePath = yield this.filePath(); + const writeFunc = overwrite ? writeFile : appendFile; + yield writeFunc(filePath, this._buffer, { encoding: 'utf8' }); + return this.emptyBuffer(); + }); + } + /** + * Clears the summary buffer and wipes the summary file + * + * @returns {Summary} summary instance + */ + clear() { + return __awaiter(this, void 0, void 0, function* () { + return this.emptyBuffer().write({ overwrite: true }); + }); + } + /** + * Returns the current summary buffer as a string + * + * @returns {string} string of summary buffer + */ + stringify() { + return this._buffer; + } + /** + * If the summary buffer is empty + * + * @returns {boolen} true if the buffer is empty + */ + isEmptyBuffer() { + return this._buffer.length === 0; + } + /** + * Resets the summary buffer without writing to summary file + * + * @returns {Summary} summary instance + */ + emptyBuffer() { + this._buffer = ''; + return this; + } + /** + * Adds raw text to the summary buffer + * + * @param {string} text content to add + * @param {boolean} [addEOL=false] (optional) append an EOL to the raw text (default: false) + * + * @returns {Summary} summary instance + */ + addRaw(text, addEOL = false) { + this._buffer += text; + return addEOL ? this.addEOL() : this; + } + /** + * Adds the operating system-specific end-of-line marker to the buffer + * + * @returns {Summary} summary instance + */ + addEOL() { + return this.addRaw(os_1.EOL); + } + /** + * Adds an HTML codeblock to the summary buffer + * + * @param {string} code content to render within fenced code block + * @param {string} lang (optional) language to syntax highlight code + * + * @returns {Summary} summary instance + */ + addCodeBlock(code, lang) { + const attrs = Object.assign({}, (lang && { lang })); + const element = this.wrap('pre', this.wrap('code', code), attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML list to the summary buffer + * + * @param {string[]} items list of items to render + * @param {boolean} [ordered=false] (optional) if the rendered list should be ordered or not (default: false) + * + * @returns {Summary} summary instance + */ + addList(items, ordered = false) { + const tag = ordered ? 'ol' : 'ul'; + const listItems = items.map(item => this.wrap('li', item)).join(''); + const element = this.wrap(tag, listItems); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML table to the summary buffer + * + * @param {SummaryTableCell[]} rows table rows + * + * @returns {Summary} summary instance + */ + addTable(rows) { + const tableBody = rows + .map(row => { + const cells = row + .map(cell => { + if (typeof cell === 'string') { + return this.wrap('td', cell); + } + const { header, data, colspan, rowspan } = cell; + const tag = header ? 'th' : 'td'; + const attrs = Object.assign(Object.assign({}, (colspan && { colspan })), (rowspan && { rowspan })); + return this.wrap(tag, data, attrs); + }) + .join(''); + return this.wrap('tr', cells); + }) + .join(''); + const element = this.wrap('table', tableBody); + return this.addRaw(element).addEOL(); + } + /** + * Adds a collapsable HTML details element to the summary buffer + * + * @param {string} label text for the closed state + * @param {string} content collapsable content + * + * @returns {Summary} summary instance + */ + addDetails(label, content) { + const element = this.wrap('details', this.wrap('summary', label) + content); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML image tag to the summary buffer + * + * @param {string} src path to the image you to embed + * @param {string} alt text description of the image + * @param {SummaryImageOptions} options (optional) addition image attributes + * + * @returns {Summary} summary instance + */ + addImage(src, alt, options) { + const { width, height } = options || {}; + const attrs = Object.assign(Object.assign({}, (width && { width })), (height && { height })); + const element = this.wrap('img', null, Object.assign({ src, alt }, attrs)); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML section heading element + * + * @param {string} text heading text + * @param {number | string} [level=1] (optional) the heading level, default: 1 + * + * @returns {Summary} summary instance + */ + addHeading(text, level) { + const tag = `h${level}`; + const allowedTag = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(tag) + ? tag + : 'h1'; + const element = this.wrap(allowedTag, text); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML thematic break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addSeparator() { + const element = this.wrap('hr', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML line break (
) to the summary buffer + * + * @returns {Summary} summary instance + */ + addBreak() { + const element = this.wrap('br', null); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML blockquote to the summary buffer + * + * @param {string} text quote text + * @param {string} cite (optional) citation url + * + * @returns {Summary} summary instance + */ + addQuote(text, cite) { + const attrs = Object.assign({}, (cite && { cite })); + const element = this.wrap('blockquote', text, attrs); + return this.addRaw(element).addEOL(); + } + /** + * Adds an HTML anchor tag to the summary buffer + * + * @param {string} text link text/content + * @param {string} href hyperlink + * + * @returns {Summary} summary instance + */ + addLink(text, href) { + const element = this.wrap('a', text, { href }); + return this.addRaw(element).addEOL(); + } +} +const _summary = new Summary(); +/** + * @deprecated use `core.summary` + */ +exports.markdownSummary = _summary; +exports.summary = _summary; +//# sourceMappingURL=summary.js.map + +/***/ }), + +/***/ 5278: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// We use any as a valid input type +/* eslint-disable @typescript-eslint/no-explicit-any */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.toCommandProperties = exports.toCommandValue = void 0; +/** + * Sanitizes an input into a string so it can be passed into issueCommand safely + * @param input input to sanitize into a string + */ +function toCommandValue(input) { + if (input === null || input === undefined) { + return ''; + } + else if (typeof input === 'string' || input instanceof String) { + return input; + } + return JSON.stringify(input); +} +exports.toCommandValue = toCommandValue; +/** + * + * @param annotationProperties + * @returns The command properties to send with the actual annotation command + * See IssueCommandProperties: https://github.com/actions/runner/blob/main/src/Runner.Worker/ActionCommandManager.cs#L646 + */ +function toCommandProperties(annotationProperties) { + if (!Object.keys(annotationProperties).length) { + return {}; + } + return { + title: annotationProperties.title, + file: annotationProperties.file, + line: annotationProperties.startLine, + endLine: annotationProperties.endLine, + col: annotationProperties.startColumn, + endColumn: annotationProperties.endColumn + }; +} +exports.toCommandProperties = toCommandProperties; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 4087: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Context = void 0; +const fs_1 = __nccwpck_require__(7147); +const os_1 = __nccwpck_require__(2037); +class Context { + /** + * Hydrate the context from the environment + */ + constructor() { + var _a, _b, _c; + this.payload = {}; + if (process.env.GITHUB_EVENT_PATH) { + if (fs_1.existsSync(process.env.GITHUB_EVENT_PATH)) { + this.payload = JSON.parse(fs_1.readFileSync(process.env.GITHUB_EVENT_PATH, { encoding: 'utf8' })); + } + else { + const path = process.env.GITHUB_EVENT_PATH; + process.stdout.write(`GITHUB_EVENT_PATH ${path} does not exist${os_1.EOL}`); + } + } + this.eventName = process.env.GITHUB_EVENT_NAME; + this.sha = process.env.GITHUB_SHA; + this.ref = process.env.GITHUB_REF; + this.workflow = process.env.GITHUB_WORKFLOW; + this.action = process.env.GITHUB_ACTION; + this.actor = process.env.GITHUB_ACTOR; + this.job = process.env.GITHUB_JOB; + this.runNumber = parseInt(process.env.GITHUB_RUN_NUMBER, 10); + this.runId = parseInt(process.env.GITHUB_RUN_ID, 10); + this.apiUrl = (_a = process.env.GITHUB_API_URL) !== null && _a !== void 0 ? _a : `https://api.github.com`; + this.serverUrl = (_b = process.env.GITHUB_SERVER_URL) !== null && _b !== void 0 ? _b : `https://github.com`; + this.graphqlUrl = (_c = process.env.GITHUB_GRAPHQL_URL) !== null && _c !== void 0 ? _c : `https://api.github.com/graphql`; + } + get issue() { + const payload = this.payload; + return Object.assign(Object.assign({}, this.repo), { number: (payload.issue || payload.pull_request || payload).number }); + } + get repo() { + if (process.env.GITHUB_REPOSITORY) { + const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/'); + return { owner, repo }; + } + if (this.payload.repository) { + return { + owner: this.payload.repository.owner.login, + repo: this.payload.repository.name + }; + } + throw new Error("context.repo requires a GITHUB_REPOSITORY environment variable like 'owner/repo'"); + } +} +exports.Context = Context; +//# sourceMappingURL=context.js.map + +/***/ }), + +/***/ 5438: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getOctokit = exports.context = void 0; +const Context = __importStar(__nccwpck_require__(4087)); +const utils_1 = __nccwpck_require__(3030); +exports.context = new Context.Context(); +/** + * Returns a hydrated octokit ready to use for GitHub Actions + * + * @param token the repo PAT or GITHUB_TOKEN + * @param options other options to set + */ +function getOctokit(token, options, ...additionalPlugins) { + const GitHubWithPlugins = utils_1.GitHub.plugin(...additionalPlugins); + return new GitHubWithPlugins(utils_1.getOctokitOptions(token, options)); +} +exports.getOctokit = getOctokit; +//# sourceMappingURL=github.js.map + +/***/ }), + +/***/ 7914: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getApiBaseUrl = exports.getProxyAgent = exports.getAuthString = void 0; +const httpClient = __importStar(__nccwpck_require__(6255)); +function getAuthString(token, options) { + if (!token && !options.auth) { + throw new Error('Parameter token or opts.auth is required'); + } + else if (token && options.auth) { + throw new Error('Parameters token and opts.auth may not both be specified'); + } + return typeof options.auth === 'string' ? options.auth : `token ${token}`; +} +exports.getAuthString = getAuthString; +function getProxyAgent(destinationUrl) { + const hc = new httpClient.HttpClient(); + return hc.getAgent(destinationUrl); +} +exports.getProxyAgent = getProxyAgent; +function getApiBaseUrl() { + return process.env['GITHUB_API_URL'] || 'https://api.github.com'; +} +exports.getApiBaseUrl = getApiBaseUrl; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 3030: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getOctokitOptions = exports.GitHub = exports.defaults = exports.context = void 0; +const Context = __importStar(__nccwpck_require__(4087)); +const Utils = __importStar(__nccwpck_require__(7914)); +// octokit + plugins +const core_1 = __nccwpck_require__(8525); +const plugin_rest_endpoint_methods_1 = __nccwpck_require__(3044); +const plugin_paginate_rest_1 = __nccwpck_require__(8945); +exports.context = new Context.Context(); +const baseUrl = Utils.getApiBaseUrl(); +exports.defaults = { + baseUrl, + request: { + agent: Utils.getProxyAgent(baseUrl) + } +}; +exports.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(exports.defaults); +/** + * Convience function to correctly format Octokit Options to pass into the constructor. + * + * @param token the repo PAT or GITHUB_TOKEN + * @param options other options to set + */ +function getOctokitOptions(token, options) { + const opts = Object.assign({}, options || {}); // Shallow clone - don't mutate the object provided by the caller + // Auth + const auth = Utils.getAuthString(token, opts); + if (auth) { + opts.auth = auth; + } + return opts; +} +exports.getOctokitOptions = getOctokitOptions; +//# sourceMappingURL=utils.js.map + +/***/ }), + +/***/ 673: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +const REGEX_IS_INSTALLATION_LEGACY = /^v1\./; +const REGEX_IS_INSTALLATION = /^ghs_/; +const REGEX_IS_USER_TO_SERVER = /^ghu_/; +async function auth(token) { + const isApp = token.split(/\./).length === 3; + const isInstallation = REGEX_IS_INSTALLATION_LEGACY.test(token) || REGEX_IS_INSTALLATION.test(token); + const isUserToServer = REGEX_IS_USER_TO_SERVER.test(token); + const tokenType = isApp ? "app" : isInstallation ? "installation" : isUserToServer ? "user-to-server" : "oauth"; + return { + type: "token", + token: token, + tokenType + }; +} + +/** + * Prefix token for usage in the Authorization header + * + * @param token OAuth token or JSON Web Token + */ +function withAuthorizationPrefix(token) { + if (token.split(/\./).length === 3) { + return `bearer ${token}`; + } + + return `token ${token}`; +} + +async function hook(token, request, route, parameters) { + const endpoint = request.endpoint.merge(route, parameters); + endpoint.headers.authorization = withAuthorizationPrefix(token); + return request(endpoint); +} + +const createTokenAuth = function createTokenAuth(token) { + if (!token) { + throw new Error("[@octokit/auth-token] No token passed to createTokenAuth"); + } + + if (typeof token !== "string") { + throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string"); + } + + token = token.replace(/^(token|bearer) +/i, ""); + return Object.assign(auth.bind(null, token), { + hook: hook.bind(null, token) + }); +}; + +exports.createTokenAuth = createTokenAuth; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 8525: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var universalUserAgent = __nccwpck_require__(5030); +var beforeAfterHook = __nccwpck_require__(3682); +var request = __nccwpck_require__(9353); +var graphql = __nccwpck_require__(6422); +var authToken = __nccwpck_require__(673); + +function _objectWithoutPropertiesLoose(source, excluded) { + if (source == null) return {}; + var target = {}; + var sourceKeys = Object.keys(source); + var key, i; + + for (i = 0; i < sourceKeys.length; i++) { + key = sourceKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + target[key] = source[key]; + } + + return target; +} + +function _objectWithoutProperties(source, excluded) { + if (source == null) return {}; + + var target = _objectWithoutPropertiesLoose(source, excluded); + + var key, i; + + if (Object.getOwnPropertySymbols) { + var sourceSymbolKeys = Object.getOwnPropertySymbols(source); + + for (i = 0; i < sourceSymbolKeys.length; i++) { + key = sourceSymbolKeys[i]; + if (excluded.indexOf(key) >= 0) continue; + if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; + target[key] = source[key]; + } + } + + return target; +} + +const VERSION = "3.6.0"; + +const _excluded = ["authStrategy"]; +class Octokit { + constructor(options = {}) { + const hook = new beforeAfterHook.Collection(); + const requestDefaults = { + baseUrl: request.request.endpoint.DEFAULTS.baseUrl, + headers: {}, + request: Object.assign({}, options.request, { + // @ts-ignore internal usage only, no need to type + hook: hook.bind(null, "request") + }), + mediaType: { + previews: [], + format: "" + } + }; // prepend default user agent with `options.userAgent` if set + + requestDefaults.headers["user-agent"] = [options.userAgent, `octokit-core.js/${VERSION} ${universalUserAgent.getUserAgent()}`].filter(Boolean).join(" "); + + if (options.baseUrl) { + requestDefaults.baseUrl = options.baseUrl; + } + + if (options.previews) { + requestDefaults.mediaType.previews = options.previews; + } + + if (options.timeZone) { + requestDefaults.headers["time-zone"] = options.timeZone; + } + + this.request = request.request.defaults(requestDefaults); + this.graphql = graphql.withCustomRequest(this.request).defaults(requestDefaults); + this.log = Object.assign({ + debug: () => {}, + info: () => {}, + warn: console.warn.bind(console), + error: console.error.bind(console) + }, options.log); + this.hook = hook; // (1) If neither `options.authStrategy` nor `options.auth` are set, the `octokit` instance + // is unauthenticated. The `this.auth()` method is a no-op and no request hook is registered. + // (2) If only `options.auth` is set, use the default token authentication strategy. + // (3) If `options.authStrategy` is set then use it and pass in `options.auth`. Always pass own request as many strategies accept a custom request instance. + // TODO: type `options.auth` based on `options.authStrategy`. + + if (!options.authStrategy) { + if (!options.auth) { + // (1) + this.auth = async () => ({ + type: "unauthenticated" + }); + } else { + // (2) + const auth = authToken.createTokenAuth(options.auth); // @ts-ignore ĀÆ\_(惄)_/ĀÆ + + hook.wrap("request", auth.hook); + this.auth = auth; + } + } else { + const { + authStrategy + } = options, + otherOptions = _objectWithoutProperties(options, _excluded); + + const auth = authStrategy(Object.assign({ + request: this.request, + log: this.log, + // we pass the current octokit instance as well as its constructor options + // to allow for authentication strategies that return a new octokit instance + // that shares the same internal state as the current one. The original + // requirement for this was the "event-octokit" authentication strategy + // of https://github.com/probot/octokit-auth-probot. + octokit: this, + octokitOptions: otherOptions + }, options.auth)); // @ts-ignore ĀÆ\_(惄)_/ĀÆ + + hook.wrap("request", auth.hook); + this.auth = auth; + } // apply plugins + // https://stackoverflow.com/a/16345172 + + + const classConstructor = this.constructor; + classConstructor.plugins.forEach(plugin => { + Object.assign(this, plugin(this, options)); + }); + } + + static defaults(defaults) { + const OctokitWithDefaults = class extends this { + constructor(...args) { + const options = args[0] || {}; + + if (typeof defaults === "function") { + super(defaults(options)); + return; + } + + super(Object.assign({}, defaults, options, options.userAgent && defaults.userAgent ? { + userAgent: `${options.userAgent} ${defaults.userAgent}` + } : null)); + } + + }; + return OctokitWithDefaults; + } + /** + * Attach a plugin (or many) to your Octokit instance. + * + * @example + * const API = Octokit.plugin(plugin1, plugin2, plugin3, ...) + */ + + + static plugin(...newPlugins) { + var _a; + + const currentPlugins = this.plugins; + const NewOctokit = (_a = class extends this {}, _a.plugins = currentPlugins.concat(newPlugins.filter(plugin => !currentPlugins.includes(plugin))), _a); + return NewOctokit; + } + +} +Octokit.VERSION = VERSION; +Octokit.plugins = []; + +exports.Octokit = Octokit; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 8713: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var isPlainObject = __nccwpck_require__(3287); +var universalUserAgent = __nccwpck_require__(5030); + +function lowercaseKeys(object) { + if (!object) { + return {}; + } + + return Object.keys(object).reduce((newObj, key) => { + newObj[key.toLowerCase()] = object[key]; + return newObj; + }, {}); +} + +function mergeDeep(defaults, options) { + const result = Object.assign({}, defaults); + Object.keys(options).forEach(key => { + if (isPlainObject.isPlainObject(options[key])) { + if (!(key in defaults)) Object.assign(result, { + [key]: options[key] + });else result[key] = mergeDeep(defaults[key], options[key]); + } else { + Object.assign(result, { + [key]: options[key] + }); + } + }); + return result; +} + +function removeUndefinedProperties(obj) { + for (const key in obj) { + if (obj[key] === undefined) { + delete obj[key]; + } + } + + return obj; +} + +function merge(defaults, route, options) { + if (typeof route === "string") { + let [method, url] = route.split(" "); + options = Object.assign(url ? { + method, + url + } : { + url: method + }, options); + } else { + options = Object.assign({}, route); + } // lowercase header names before merging with defaults to avoid duplicates + + + options.headers = lowercaseKeys(options.headers); // remove properties with undefined values before merging + + removeUndefinedProperties(options); + removeUndefinedProperties(options.headers); + const mergedOptions = mergeDeep(defaults || {}, options); // mediaType.previews arrays are merged, instead of overwritten + + if (defaults && defaults.mediaType.previews.length) { + mergedOptions.mediaType.previews = defaults.mediaType.previews.filter(preview => !mergedOptions.mediaType.previews.includes(preview)).concat(mergedOptions.mediaType.previews); + } + + mergedOptions.mediaType.previews = mergedOptions.mediaType.previews.map(preview => preview.replace(/-preview/, "")); + return mergedOptions; +} + +function addQueryParameters(url, parameters) { + const separator = /\?/.test(url) ? "&" : "?"; + const names = Object.keys(parameters); + + if (names.length === 0) { + return url; + } + + return url + separator + names.map(name => { + if (name === "q") { + return "q=" + parameters.q.split("+").map(encodeURIComponent).join("+"); + } + + return `${name}=${encodeURIComponent(parameters[name])}`; + }).join("&"); +} + +const urlVariableRegex = /\{[^}]+\}/g; + +function removeNonChars(variableName) { + return variableName.replace(/^\W+|\W+$/g, "").split(/,/); +} + +function extractUrlVariableNames(url) { + const matches = url.match(urlVariableRegex); + + if (!matches) { + return []; + } + + return matches.map(removeNonChars).reduce((a, b) => a.concat(b), []); +} + +function omit(object, keysToOmit) { + return Object.keys(object).filter(option => !keysToOmit.includes(option)).reduce((obj, key) => { + obj[key] = object[key]; + return obj; + }, {}); +} + +// Based on https://github.com/bramstein/url-template, licensed under BSD +// TODO: create separate package. +// +// Copyright (c) 2012-2014, Bram Stein +// All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/* istanbul ignore file */ +function encodeReserved(str) { + return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) { + if (!/%[0-9A-Fa-f]/.test(part)) { + part = encodeURI(part).replace(/%5B/g, "[").replace(/%5D/g, "]"); + } + + return part; + }).join(""); +} + +function encodeUnreserved(str) { + return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { + return "%" + c.charCodeAt(0).toString(16).toUpperCase(); + }); +} + +function encodeValue(operator, value, key) { + value = operator === "+" || operator === "#" ? encodeReserved(value) : encodeUnreserved(value); + + if (key) { + return encodeUnreserved(key) + "=" + value; + } else { + return value; + } +} + +function isDefined(value) { + return value !== undefined && value !== null; +} + +function isKeyOperator(operator) { + return operator === ";" || operator === "&" || operator === "?"; +} + +function getValues(context, operator, key, modifier) { + var value = context[key], + result = []; + + if (isDefined(value) && value !== "") { + if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") { + value = value.toString(); + + if (modifier && modifier !== "*") { + value = value.substring(0, parseInt(modifier, 10)); + } + + result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : "")); + } else { + if (modifier === "*") { + if (Array.isArray(value)) { + value.filter(isDefined).forEach(function (value) { + result.push(encodeValue(operator, value, isKeyOperator(operator) ? key : "")); + }); + } else { + Object.keys(value).forEach(function (k) { + if (isDefined(value[k])) { + result.push(encodeValue(operator, value[k], k)); + } + }); + } + } else { + const tmp = []; + + if (Array.isArray(value)) { + value.filter(isDefined).forEach(function (value) { + tmp.push(encodeValue(operator, value)); + }); + } else { + Object.keys(value).forEach(function (k) { + if (isDefined(value[k])) { + tmp.push(encodeUnreserved(k)); + tmp.push(encodeValue(operator, value[k].toString())); + } + }); + } + + if (isKeyOperator(operator)) { + result.push(encodeUnreserved(key) + "=" + tmp.join(",")); + } else if (tmp.length !== 0) { + result.push(tmp.join(",")); + } + } + } + } else { + if (operator === ";") { + if (isDefined(value)) { + result.push(encodeUnreserved(key)); + } + } else if (value === "" && (operator === "&" || operator === "?")) { + result.push(encodeUnreserved(key) + "="); + } else if (value === "") { + result.push(""); + } + } + + return result; +} + +function parseUrl(template) { + return { + expand: expand.bind(null, template) + }; +} + +function expand(template, context) { + var operators = ["+", "#", ".", "/", ";", "?", "&"]; + return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) { + if (expression) { + let operator = ""; + const values = []; + + if (operators.indexOf(expression.charAt(0)) !== -1) { + operator = expression.charAt(0); + expression = expression.substr(1); + } + + expression.split(/,/g).forEach(function (variable) { + var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable); + values.push(getValues(context, operator, tmp[1], tmp[2] || tmp[3])); + }); + + if (operator && operator !== "+") { + var separator = ","; + + if (operator === "?") { + separator = "&"; + } else if (operator !== "#") { + separator = operator; + } + + return (values.length !== 0 ? operator : "") + values.join(separator); + } else { + return values.join(","); + } + } else { + return encodeReserved(literal); + } + }); +} + +function parse(options) { + // https://fetch.spec.whatwg.org/#methods + let method = options.method.toUpperCase(); // replace :varname with {varname} to make it RFC 6570 compatible + + let url = (options.url || "/").replace(/:([a-z]\w+)/g, "{$1}"); + let headers = Object.assign({}, options.headers); + let body; + let parameters = omit(options, ["method", "baseUrl", "url", "headers", "request", "mediaType"]); // extract variable names from URL to calculate remaining variables later + + const urlVariableNames = extractUrlVariableNames(url); + url = parseUrl(url).expand(parameters); + + if (!/^http/.test(url)) { + url = options.baseUrl + url; + } + + const omittedParameters = Object.keys(options).filter(option => urlVariableNames.includes(option)).concat("baseUrl"); + const remainingParameters = omit(parameters, omittedParameters); + const isBinaryRequest = /application\/octet-stream/i.test(headers.accept); + + if (!isBinaryRequest) { + if (options.mediaType.format) { + // e.g. application/vnd.github.v3+json => application/vnd.github.v3.raw + headers.accept = headers.accept.split(/,/).map(preview => preview.replace(/application\/vnd(\.\w+)(\.v3)?(\.\w+)?(\+json)?$/, `application/vnd$1$2.${options.mediaType.format}`)).join(","); + } + + if (options.mediaType.previews.length) { + const previewsFromAcceptHeader = headers.accept.match(/[\w-]+(?=-preview)/g) || []; + headers.accept = previewsFromAcceptHeader.concat(options.mediaType.previews).map(preview => { + const format = options.mediaType.format ? `.${options.mediaType.format}` : "+json"; + return `application/vnd.github.${preview}-preview${format}`; + }).join(","); + } + } // for GET/HEAD requests, set URL query parameters from remaining parameters + // for PATCH/POST/PUT/DELETE requests, set request body from remaining parameters + + + if (["GET", "HEAD"].includes(method)) { + url = addQueryParameters(url, remainingParameters); + } else { + if ("data" in remainingParameters) { + body = remainingParameters.data; + } else { + if (Object.keys(remainingParameters).length) { + body = remainingParameters; + } else { + headers["content-length"] = 0; + } + } + } // default content-type for JSON if body is set + + + if (!headers["content-type"] && typeof body !== "undefined") { + headers["content-type"] = "application/json; charset=utf-8"; + } // GitHub expects 'content-length: 0' header for PUT/PATCH requests without body. + // fetch does not allow to set `content-length` header, but we can set body to an empty string + + + if (["PATCH", "PUT"].includes(method) && typeof body === "undefined") { + body = ""; + } // Only return body/request keys if present + + + return Object.assign({ + method, + url, + headers + }, typeof body !== "undefined" ? { + body + } : null, options.request ? { + request: options.request + } : null); +} + +function endpointWithDefaults(defaults, route, options) { + return parse(merge(defaults, route, options)); +} + +function withDefaults(oldDefaults, newDefaults) { + const DEFAULTS = merge(oldDefaults, newDefaults); + const endpoint = endpointWithDefaults.bind(null, DEFAULTS); + return Object.assign(endpoint, { + DEFAULTS, + defaults: withDefaults.bind(null, DEFAULTS), + merge: merge.bind(null, DEFAULTS), + parse + }); +} + +const VERSION = "6.0.12"; + +const userAgent = `octokit-endpoint.js/${VERSION} ${universalUserAgent.getUserAgent()}`; // DEFAULTS has all properties set that EndpointOptions has, except url. +// So we use RequestParameters and add method as additional required property. + +const DEFAULTS = { + method: "GET", + baseUrl: "https://api.github.com", + headers: { + accept: "application/vnd.github.v3+json", + "user-agent": userAgent + }, + mediaType: { + format: "", + previews: [] + } +}; + +const endpoint = withDefaults(null, DEFAULTS); + +exports.endpoint = endpoint; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 6422: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var request = __nccwpck_require__(9353); +var universalUserAgent = __nccwpck_require__(5030); + +const VERSION = "4.8.0"; + +function _buildMessageForResponseErrors(data) { + return `Request failed due to following response errors:\n` + data.errors.map(e => ` - ${e.message}`).join("\n"); +} + +class GraphqlResponseError extends Error { + constructor(request, headers, response) { + super(_buildMessageForResponseErrors(response)); + this.request = request; + this.headers = headers; + this.response = response; + this.name = "GraphqlResponseError"; // Expose the errors and response data in their shorthand properties. + + this.errors = response.errors; + this.data = response.data; // Maintains proper stack trace (only available on V8) + + /* istanbul ignore next */ + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } + +} + +const NON_VARIABLE_OPTIONS = ["method", "baseUrl", "url", "headers", "request", "query", "mediaType"]; +const FORBIDDEN_VARIABLE_OPTIONS = ["query", "method", "url"]; +const GHES_V3_SUFFIX_REGEX = /\/api\/v3\/?$/; +function graphql(request, query, options) { + if (options) { + if (typeof query === "string" && "query" in options) { + return Promise.reject(new Error(`[@octokit/graphql] "query" cannot be used as variable name`)); + } + + for (const key in options) { + if (!FORBIDDEN_VARIABLE_OPTIONS.includes(key)) continue; + return Promise.reject(new Error(`[@octokit/graphql] "${key}" cannot be used as variable name`)); + } + } + + const parsedOptions = typeof query === "string" ? Object.assign({ + query + }, options) : query; + const requestOptions = Object.keys(parsedOptions).reduce((result, key) => { + if (NON_VARIABLE_OPTIONS.includes(key)) { + result[key] = parsedOptions[key]; + return result; + } + + if (!result.variables) { + result.variables = {}; + } + + result.variables[key] = parsedOptions[key]; + return result; + }, {}); // workaround for GitHub Enterprise baseUrl set with /api/v3 suffix + // https://github.com/octokit/auth-app.js/issues/111#issuecomment-657610451 + + const baseUrl = parsedOptions.baseUrl || request.endpoint.DEFAULTS.baseUrl; + + if (GHES_V3_SUFFIX_REGEX.test(baseUrl)) { + requestOptions.url = baseUrl.replace(GHES_V3_SUFFIX_REGEX, "/api/graphql"); + } + + return request(requestOptions).then(response => { + if (response.data.errors) { + const headers = {}; + + for (const key of Object.keys(response.headers)) { + headers[key] = response.headers[key]; + } + + throw new GraphqlResponseError(requestOptions, headers, response.data); + } + + return response.data.data; + }); +} + +function withDefaults(request$1, newDefaults) { + const newRequest = request$1.defaults(newDefaults); + + const newApi = (query, options) => { + return graphql(newRequest, query, options); + }; + + return Object.assign(newApi, { + defaults: withDefaults.bind(null, newRequest), + endpoint: request.request.endpoint + }); +} + +const graphql$1 = withDefaults(request.request, { + headers: { + "user-agent": `octokit-graphql.js/${VERSION} ${universalUserAgent.getUserAgent()}` + }, + method: "POST", + url: "/graphql" +}); +function withCustomRequest(customRequest) { + return withDefaults(customRequest, { + method: "POST", + url: "/graphql" + }); +} + +exports.GraphqlResponseError = GraphqlResponseError; +exports.graphql = graphql$1; +exports.withCustomRequest = withCustomRequest; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 8945: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +const VERSION = "2.21.3"; + +function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + enumerableOnly && (symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + })), keys.push.apply(keys, symbols); + } + + return keys; +} + +function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = null != arguments[i] ? arguments[i] : {}; + i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { + _defineProperty(target, key, source[key]); + }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + + return target; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +/** + * Some ā€œlistā€ response that can be paginated have a different response structure + * + * They have a `total_count` key in the response (search also has `incomplete_results`, + * /installation/repositories also has `repository_selection`), as well as a key with + * the list of the items which name varies from endpoint to endpoint. + * + * Octokit normalizes these responses so that paginated results are always returned following + * the same structure. One challenge is that if the list response has only one page, no Link + * header is provided, so this header alone is not sufficient to check wether a response is + * paginated or not. + * + * We check if a "total_count" key is present in the response data, but also make sure that + * a "url" property is not, as the "Get the combined status for a specific ref" endpoint would + * otherwise match: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref + */ +function normalizePaginatedListResponse(response) { + // endpoints can respond with 204 if repository is empty + if (!response.data) { + return _objectSpread2(_objectSpread2({}, response), {}, { + data: [] + }); + } + + const responseNeedsNormalization = "total_count" in response.data && !("url" in response.data); + if (!responseNeedsNormalization) return response; // keep the additional properties intact as there is currently no other way + // to retrieve the same information. + + const incompleteResults = response.data.incomplete_results; + const repositorySelection = response.data.repository_selection; + const totalCount = response.data.total_count; + delete response.data.incomplete_results; + delete response.data.repository_selection; + delete response.data.total_count; + const namespaceKey = Object.keys(response.data)[0]; + const data = response.data[namespaceKey]; + response.data = data; + + if (typeof incompleteResults !== "undefined") { + response.data.incomplete_results = incompleteResults; + } + + if (typeof repositorySelection !== "undefined") { + response.data.repository_selection = repositorySelection; + } + + response.data.total_count = totalCount; + return response; +} + +function iterator(octokit, route, parameters) { + const options = typeof route === "function" ? route.endpoint(parameters) : octokit.request.endpoint(route, parameters); + const requestMethod = typeof route === "function" ? route : octokit.request; + const method = options.method; + const headers = options.headers; + let url = options.url; + return { + [Symbol.asyncIterator]: () => ({ + async next() { + if (!url) return { + done: true + }; + + try { + const response = await requestMethod({ + method, + url, + headers + }); + const normalizedResponse = normalizePaginatedListResponse(response); // `response.headers.link` format: + // '; rel="next", ; rel="last"' + // sets `url` to undefined if "next" URL is not present or `link` header is not set + + url = ((normalizedResponse.headers.link || "").match(/<([^>]+)>;\s*rel="next"/) || [])[1]; + return { + value: normalizedResponse + }; + } catch (error) { + if (error.status !== 409) throw error; + url = ""; + return { + value: { + status: 200, + headers: {}, + data: [] + } + }; + } + } + + }) + }; +} + +function paginate(octokit, route, parameters, mapFn) { + if (typeof parameters === "function") { + mapFn = parameters; + parameters = undefined; + } + + return gather(octokit, [], iterator(octokit, route, parameters)[Symbol.asyncIterator](), mapFn); +} + +function gather(octokit, results, iterator, mapFn) { + return iterator.next().then(result => { + if (result.done) { + return results; + } + + let earlyExit = false; + + function done() { + earlyExit = true; + } + + results = results.concat(mapFn ? mapFn(result.value, done) : result.value.data); + + if (earlyExit) { + return results; + } + + return gather(octokit, results, iterator, mapFn); + }); +} + +const composePaginateRest = Object.assign(paginate, { + iterator +}); + +const paginatingEndpoints = ["GET /app/hook/deliveries", "GET /app/installations", "GET /applications/grants", "GET /authorizations", "GET /enterprises/{enterprise}/actions/permissions/organizations", "GET /enterprises/{enterprise}/actions/runner-groups", "GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations", "GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners", "GET /enterprises/{enterprise}/actions/runners", "GET /enterprises/{enterprise}/audit-log", "GET /enterprises/{enterprise}/secret-scanning/alerts", "GET /enterprises/{enterprise}/settings/billing/advanced-security", "GET /events", "GET /gists", "GET /gists/public", "GET /gists/starred", "GET /gists/{gist_id}/comments", "GET /gists/{gist_id}/commits", "GET /gists/{gist_id}/forks", "GET /installation/repositories", "GET /issues", "GET /licenses", "GET /marketplace_listing/plans", "GET /marketplace_listing/plans/{plan_id}/accounts", "GET /marketplace_listing/stubbed/plans", "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts", "GET /networks/{owner}/{repo}/events", "GET /notifications", "GET /organizations", "GET /orgs/{org}/actions/cache/usage-by-repository", "GET /orgs/{org}/actions/permissions/repositories", "GET /orgs/{org}/actions/runner-groups", "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories", "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners", "GET /orgs/{org}/actions/runners", "GET /orgs/{org}/actions/secrets", "GET /orgs/{org}/actions/secrets/{secret_name}/repositories", "GET /orgs/{org}/audit-log", "GET /orgs/{org}/blocks", "GET /orgs/{org}/code-scanning/alerts", "GET /orgs/{org}/codespaces", "GET /orgs/{org}/credential-authorizations", "GET /orgs/{org}/dependabot/secrets", "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories", "GET /orgs/{org}/events", "GET /orgs/{org}/external-groups", "GET /orgs/{org}/failed_invitations", "GET /orgs/{org}/hooks", "GET /orgs/{org}/hooks/{hook_id}/deliveries", "GET /orgs/{org}/installations", "GET /orgs/{org}/invitations", "GET /orgs/{org}/invitations/{invitation_id}/teams", "GET /orgs/{org}/issues", "GET /orgs/{org}/members", "GET /orgs/{org}/migrations", "GET /orgs/{org}/migrations/{migration_id}/repositories", "GET /orgs/{org}/outside_collaborators", "GET /orgs/{org}/packages", "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", "GET /orgs/{org}/projects", "GET /orgs/{org}/public_members", "GET /orgs/{org}/repos", "GET /orgs/{org}/secret-scanning/alerts", "GET /orgs/{org}/settings/billing/advanced-security", "GET /orgs/{org}/team-sync/groups", "GET /orgs/{org}/teams", "GET /orgs/{org}/teams/{team_slug}/discussions", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", "GET /orgs/{org}/teams/{team_slug}/invitations", "GET /orgs/{org}/teams/{team_slug}/members", "GET /orgs/{org}/teams/{team_slug}/projects", "GET /orgs/{org}/teams/{team_slug}/repos", "GET /orgs/{org}/teams/{team_slug}/teams", "GET /projects/columns/{column_id}/cards", "GET /projects/{project_id}/collaborators", "GET /projects/{project_id}/columns", "GET /repos/{owner}/{repo}/actions/artifacts", "GET /repos/{owner}/{repo}/actions/caches", "GET /repos/{owner}/{repo}/actions/runners", "GET /repos/{owner}/{repo}/actions/runs", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs", "GET /repos/{owner}/{repo}/actions/secrets", "GET /repos/{owner}/{repo}/actions/workflows", "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs", "GET /repos/{owner}/{repo}/assignees", "GET /repos/{owner}/{repo}/branches", "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations", "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs", "GET /repos/{owner}/{repo}/code-scanning/alerts", "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", "GET /repos/{owner}/{repo}/code-scanning/analyses", "GET /repos/{owner}/{repo}/codespaces", "GET /repos/{owner}/{repo}/codespaces/devcontainers", "GET /repos/{owner}/{repo}/codespaces/secrets", "GET /repos/{owner}/{repo}/collaborators", "GET /repos/{owner}/{repo}/comments", "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/commits", "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments", "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls", "GET /repos/{owner}/{repo}/commits/{ref}/check-runs", "GET /repos/{owner}/{repo}/commits/{ref}/check-suites", "GET /repos/{owner}/{repo}/commits/{ref}/status", "GET /repos/{owner}/{repo}/commits/{ref}/statuses", "GET /repos/{owner}/{repo}/contributors", "GET /repos/{owner}/{repo}/dependabot/secrets", "GET /repos/{owner}/{repo}/deployments", "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses", "GET /repos/{owner}/{repo}/environments", "GET /repos/{owner}/{repo}/events", "GET /repos/{owner}/{repo}/forks", "GET /repos/{owner}/{repo}/git/matching-refs/{ref}", "GET /repos/{owner}/{repo}/hooks", "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries", "GET /repos/{owner}/{repo}/invitations", "GET /repos/{owner}/{repo}/issues", "GET /repos/{owner}/{repo}/issues/comments", "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/issues/events", "GET /repos/{owner}/{repo}/issues/{issue_number}/comments", "GET /repos/{owner}/{repo}/issues/{issue_number}/events", "GET /repos/{owner}/{repo}/issues/{issue_number}/labels", "GET /repos/{owner}/{repo}/issues/{issue_number}/reactions", "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline", "GET /repos/{owner}/{repo}/keys", "GET /repos/{owner}/{repo}/labels", "GET /repos/{owner}/{repo}/milestones", "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels", "GET /repos/{owner}/{repo}/notifications", "GET /repos/{owner}/{repo}/pages/builds", "GET /repos/{owner}/{repo}/projects", "GET /repos/{owner}/{repo}/pulls", "GET /repos/{owner}/{repo}/pulls/comments", "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments", "GET /repos/{owner}/{repo}/pulls/{pull_number}/commits", "GET /repos/{owner}/{repo}/pulls/{pull_number}/files", "GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers", "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews", "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", "GET /repos/{owner}/{repo}/releases", "GET /repos/{owner}/{repo}/releases/{release_id}/assets", "GET /repos/{owner}/{repo}/releases/{release_id}/reactions", "GET /repos/{owner}/{repo}/secret-scanning/alerts", "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations", "GET /repos/{owner}/{repo}/stargazers", "GET /repos/{owner}/{repo}/subscribers", "GET /repos/{owner}/{repo}/tags", "GET /repos/{owner}/{repo}/teams", "GET /repos/{owner}/{repo}/topics", "GET /repositories", "GET /repositories/{repository_id}/environments/{environment_name}/secrets", "GET /search/code", "GET /search/commits", "GET /search/issues", "GET /search/labels", "GET /search/repositories", "GET /search/topics", "GET /search/users", "GET /teams/{team_id}/discussions", "GET /teams/{team_id}/discussions/{discussion_number}/comments", "GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions", "GET /teams/{team_id}/discussions/{discussion_number}/reactions", "GET /teams/{team_id}/invitations", "GET /teams/{team_id}/members", "GET /teams/{team_id}/projects", "GET /teams/{team_id}/repos", "GET /teams/{team_id}/teams", "GET /user/blocks", "GET /user/codespaces", "GET /user/codespaces/secrets", "GET /user/emails", "GET /user/followers", "GET /user/following", "GET /user/gpg_keys", "GET /user/installations", "GET /user/installations/{installation_id}/repositories", "GET /user/issues", "GET /user/keys", "GET /user/marketplace_purchases", "GET /user/marketplace_purchases/stubbed", "GET /user/memberships/orgs", "GET /user/migrations", "GET /user/migrations/{migration_id}/repositories", "GET /user/orgs", "GET /user/packages", "GET /user/packages/{package_type}/{package_name}/versions", "GET /user/public_emails", "GET /user/repos", "GET /user/repository_invitations", "GET /user/starred", "GET /user/subscriptions", "GET /user/teams", "GET /users", "GET /users/{username}/events", "GET /users/{username}/events/orgs/{org}", "GET /users/{username}/events/public", "GET /users/{username}/followers", "GET /users/{username}/following", "GET /users/{username}/gists", "GET /users/{username}/gpg_keys", "GET /users/{username}/keys", "GET /users/{username}/orgs", "GET /users/{username}/packages", "GET /users/{username}/projects", "GET /users/{username}/received_events", "GET /users/{username}/received_events/public", "GET /users/{username}/repos", "GET /users/{username}/starred", "GET /users/{username}/subscriptions"]; + +function isPaginatingEndpoint(arg) { + if (typeof arg === "string") { + return paginatingEndpoints.includes(arg); + } else { + return false; + } +} + +/** + * @param octokit Octokit instance + * @param options Options passed to Octokit constructor + */ + +function paginateRest(octokit) { + return { + paginate: Object.assign(paginate.bind(null, octokit), { + iterator: iterator.bind(null, octokit) + }) + }; +} +paginateRest.VERSION = VERSION; + +exports.composePaginateRest = composePaginateRest; +exports.isPaginatingEndpoint = isPaginatingEndpoint; +exports.paginateRest = paginateRest; +exports.paginatingEndpoints = paginatingEndpoints; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 7471: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var deprecation = __nccwpck_require__(8932); +var once = _interopDefault(__nccwpck_require__(1223)); + +const logOnceCode = once(deprecation => console.warn(deprecation)); +const logOnceHeaders = once(deprecation => console.warn(deprecation)); +/** + * Error with extra properties to help with debugging + */ + +class RequestError extends Error { + constructor(message, statusCode, options) { + super(message); // Maintains proper stack trace (only available on V8) + + /* istanbul ignore next */ + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + + this.name = "HttpError"; + this.status = statusCode; + let headers; + + if ("headers" in options && typeof options.headers !== "undefined") { + headers = options.headers; + } + + if ("response" in options) { + this.response = options.response; + headers = options.response.headers; + } // redact request credentials without mutating original request options + + + const requestCopy = Object.assign({}, options.request); + + if (options.request.headers.authorization) { + requestCopy.headers = Object.assign({}, options.request.headers, { + authorization: options.request.headers.authorization.replace(/ .*$/, " [REDACTED]") + }); + } + + requestCopy.url = requestCopy.url // client_id & client_secret can be passed as URL query parameters to increase rate limit + // see https://developer.github.com/v3/#increasing-the-unauthenticated-rate-limit-for-oauth-applications + .replace(/\bclient_secret=\w+/g, "client_secret=[REDACTED]") // OAuth tokens can be passed as URL query parameters, although it is not recommended + // see https://developer.github.com/v3/#oauth2-token-sent-in-a-header + .replace(/\baccess_token=\w+/g, "access_token=[REDACTED]"); + this.request = requestCopy; // deprecations + + Object.defineProperty(this, "code", { + get() { + logOnceCode(new deprecation.Deprecation("[@octokit/request-error] `error.code` is deprecated, use `error.status`.")); + return statusCode; + } + + }); + Object.defineProperty(this, "headers", { + get() { + logOnceHeaders(new deprecation.Deprecation("[@octokit/request-error] `error.headers` is deprecated, use `error.response.headers`.")); + return headers || {}; + } + + }); + } + +} + +exports.RequestError = RequestError; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 9353: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var endpoint = __nccwpck_require__(8713); +var universalUserAgent = __nccwpck_require__(5030); +var isPlainObject = __nccwpck_require__(3287); +var nodeFetch = _interopDefault(__nccwpck_require__(467)); +var requestError = __nccwpck_require__(7471); + +const VERSION = "5.6.3"; + +function getBufferResponse(response) { + return response.arrayBuffer(); +} + +function fetchWrapper(requestOptions) { + const log = requestOptions.request && requestOptions.request.log ? requestOptions.request.log : console; + + if (isPlainObject.isPlainObject(requestOptions.body) || Array.isArray(requestOptions.body)) { + requestOptions.body = JSON.stringify(requestOptions.body); + } + + let headers = {}; + let status; + let url; + const fetch = requestOptions.request && requestOptions.request.fetch || nodeFetch; + return fetch(requestOptions.url, Object.assign({ + method: requestOptions.method, + body: requestOptions.body, + headers: requestOptions.headers, + redirect: requestOptions.redirect + }, // `requestOptions.request.agent` type is incompatible + // see https://github.com/octokit/types.ts/pull/264 + requestOptions.request)).then(async response => { + url = response.url; + status = response.status; + + for (const keyAndValue of response.headers) { + headers[keyAndValue[0]] = keyAndValue[1]; + } + + if ("deprecation" in headers) { + const matches = headers.link && headers.link.match(/<([^>]+)>; rel="deprecation"/); + const deprecationLink = matches && matches.pop(); + log.warn(`[@octokit/request] "${requestOptions.method} ${requestOptions.url}" is deprecated. It is scheduled to be removed on ${headers.sunset}${deprecationLink ? `. See ${deprecationLink}` : ""}`); + } + + if (status === 204 || status === 205) { + return; + } // GitHub API returns 200 for HEAD requests + + + if (requestOptions.method === "HEAD") { + if (status < 400) { + return; + } + + throw new requestError.RequestError(response.statusText, status, { + response: { + url, + status, + headers, + data: undefined + }, + request: requestOptions + }); + } + + if (status === 304) { + throw new requestError.RequestError("Not modified", status, { + response: { + url, + status, + headers, + data: await getResponseData(response) + }, + request: requestOptions + }); + } + + if (status >= 400) { + const data = await getResponseData(response); + const error = new requestError.RequestError(toErrorMessage(data), status, { + response: { + url, + status, + headers, + data + }, + request: requestOptions + }); + throw error; + } + + return getResponseData(response); + }).then(data => { + return { + status, + url, + headers, + data + }; + }).catch(error => { + if (error instanceof requestError.RequestError) throw error; + throw new requestError.RequestError(error.message, 500, { + request: requestOptions + }); + }); +} + +async function getResponseData(response) { + const contentType = response.headers.get("content-type"); + + if (/application\/json/.test(contentType)) { + return response.json(); + } + + if (!contentType || /^text\/|charset=utf-8$/.test(contentType)) { + return response.text(); + } + + return getBufferResponse(response); +} + +function toErrorMessage(data) { + if (typeof data === "string") return data; // istanbul ignore else - just in case + + if ("message" in data) { + if (Array.isArray(data.errors)) { + return `${data.message}: ${data.errors.map(JSON.stringify).join(", ")}`; + } + + return data.message; + } // istanbul ignore next - just in case + + + return `Unknown error: ${JSON.stringify(data)}`; +} + +function withDefaults(oldEndpoint, newDefaults) { + const endpoint = oldEndpoint.defaults(newDefaults); + + const newApi = function (route, parameters) { + const endpointOptions = endpoint.merge(route, parameters); + + if (!endpointOptions.request || !endpointOptions.request.hook) { + return fetchWrapper(endpoint.parse(endpointOptions)); + } + + const request = (route, parameters) => { + return fetchWrapper(endpoint.parse(endpoint.merge(route, parameters))); + }; + + Object.assign(request, { + endpoint, + defaults: withDefaults.bind(null, endpoint) + }); + return endpointOptions.request.hook(request, endpointOptions); + }; + + return Object.assign(newApi, { + endpoint, + defaults: withDefaults.bind(null, endpoint) + }); +} + +const request = withDefaults(endpoint.endpoint, { + headers: { + "user-agent": `octokit-request.js/${VERSION} ${universalUserAgent.getUserAgent()}` + } +}); + +exports.request = request; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 5526: +/***/ (function(__unused_webpack_module, exports) { + +"use strict"; + +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.PersonalAccessTokenCredentialHandler = exports.BearerCredentialHandler = exports.BasicCredentialHandler = void 0; +class BasicCredentialHandler { + constructor(username, password) { + this.username = username; + this.password = password; + } + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`${this.username}:${this.password}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BasicCredentialHandler = BasicCredentialHandler; +class BearerCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Bearer ${this.token}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.BearerCredentialHandler = BearerCredentialHandler; +class PersonalAccessTokenCredentialHandler { + constructor(token) { + this.token = token; + } + // currently implements pre-authorization + // TODO: support preAuth = false where it hooks on 401 + prepareRequest(options) { + if (!options.headers) { + throw Error('The request has no headers'); + } + options.headers['Authorization'] = `Basic ${Buffer.from(`PAT:${this.token}`).toString('base64')}`; + } + // This handler cannot handle 401 + canHandleAuthentication() { + return false; + } + handleAuthentication() { + return __awaiter(this, void 0, void 0, function* () { + throw new Error('not implemented'); + }); + } +} +exports.PersonalAccessTokenCredentialHandler = PersonalAccessTokenCredentialHandler; +//# sourceMappingURL=auth.js.map + +/***/ }), + +/***/ 6255: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/* eslint-disable @typescript-eslint/no-explicit-any */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.HttpClient = exports.isHttps = exports.HttpClientResponse = exports.HttpClientError = exports.getProxyUrl = exports.MediaTypes = exports.Headers = exports.HttpCodes = void 0; +const http = __importStar(__nccwpck_require__(3685)); +const https = __importStar(__nccwpck_require__(5687)); +const pm = __importStar(__nccwpck_require__(9835)); +const tunnel = __importStar(__nccwpck_require__(4294)); +var HttpCodes; +(function (HttpCodes) { + HttpCodes[HttpCodes["OK"] = 200] = "OK"; + HttpCodes[HttpCodes["MultipleChoices"] = 300] = "MultipleChoices"; + HttpCodes[HttpCodes["MovedPermanently"] = 301] = "MovedPermanently"; + HttpCodes[HttpCodes["ResourceMoved"] = 302] = "ResourceMoved"; + HttpCodes[HttpCodes["SeeOther"] = 303] = "SeeOther"; + HttpCodes[HttpCodes["NotModified"] = 304] = "NotModified"; + HttpCodes[HttpCodes["UseProxy"] = 305] = "UseProxy"; + HttpCodes[HttpCodes["SwitchProxy"] = 306] = "SwitchProxy"; + HttpCodes[HttpCodes["TemporaryRedirect"] = 307] = "TemporaryRedirect"; + HttpCodes[HttpCodes["PermanentRedirect"] = 308] = "PermanentRedirect"; + HttpCodes[HttpCodes["BadRequest"] = 400] = "BadRequest"; + HttpCodes[HttpCodes["Unauthorized"] = 401] = "Unauthorized"; + HttpCodes[HttpCodes["PaymentRequired"] = 402] = "PaymentRequired"; + HttpCodes[HttpCodes["Forbidden"] = 403] = "Forbidden"; + HttpCodes[HttpCodes["NotFound"] = 404] = "NotFound"; + HttpCodes[HttpCodes["MethodNotAllowed"] = 405] = "MethodNotAllowed"; + HttpCodes[HttpCodes["NotAcceptable"] = 406] = "NotAcceptable"; + HttpCodes[HttpCodes["ProxyAuthenticationRequired"] = 407] = "ProxyAuthenticationRequired"; + HttpCodes[HttpCodes["RequestTimeout"] = 408] = "RequestTimeout"; + HttpCodes[HttpCodes["Conflict"] = 409] = "Conflict"; + HttpCodes[HttpCodes["Gone"] = 410] = "Gone"; + HttpCodes[HttpCodes["TooManyRequests"] = 429] = "TooManyRequests"; + HttpCodes[HttpCodes["InternalServerError"] = 500] = "InternalServerError"; + HttpCodes[HttpCodes["NotImplemented"] = 501] = "NotImplemented"; + HttpCodes[HttpCodes["BadGateway"] = 502] = "BadGateway"; + HttpCodes[HttpCodes["ServiceUnavailable"] = 503] = "ServiceUnavailable"; + HttpCodes[HttpCodes["GatewayTimeout"] = 504] = "GatewayTimeout"; +})(HttpCodes = exports.HttpCodes || (exports.HttpCodes = {})); +var Headers; +(function (Headers) { + Headers["Accept"] = "accept"; + Headers["ContentType"] = "content-type"; +})(Headers = exports.Headers || (exports.Headers = {})); +var MediaTypes; +(function (MediaTypes) { + MediaTypes["ApplicationJson"] = "application/json"; +})(MediaTypes = exports.MediaTypes || (exports.MediaTypes = {})); +/** + * Returns the proxy URL, depending upon the supplied url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ +function getProxyUrl(serverUrl) { + const proxyUrl = pm.getProxyUrl(new URL(serverUrl)); + return proxyUrl ? proxyUrl.href : ''; +} +exports.getProxyUrl = getProxyUrl; +const HttpRedirectCodes = [ + HttpCodes.MovedPermanently, + HttpCodes.ResourceMoved, + HttpCodes.SeeOther, + HttpCodes.TemporaryRedirect, + HttpCodes.PermanentRedirect +]; +const HttpResponseRetryCodes = [ + HttpCodes.BadGateway, + HttpCodes.ServiceUnavailable, + HttpCodes.GatewayTimeout +]; +const RetryableHttpVerbs = ['OPTIONS', 'GET', 'DELETE', 'HEAD']; +const ExponentialBackoffCeiling = 10; +const ExponentialBackoffTimeSlice = 5; +class HttpClientError extends Error { + constructor(message, statusCode) { + super(message); + this.name = 'HttpClientError'; + this.statusCode = statusCode; + Object.setPrototypeOf(this, HttpClientError.prototype); + } +} +exports.HttpClientError = HttpClientError; +class HttpClientResponse { + constructor(message) { + this.message = message; + } + readBody() { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + let output = Buffer.alloc(0); + this.message.on('data', (chunk) => { + output = Buffer.concat([output, chunk]); + }); + this.message.on('end', () => { + resolve(output.toString()); + }); + })); + }); + } +} +exports.HttpClientResponse = HttpClientResponse; +function isHttps(requestUrl) { + const parsedUrl = new URL(requestUrl); + return parsedUrl.protocol === 'https:'; +} +exports.isHttps = isHttps; +class HttpClient { + constructor(userAgent, handlers, requestOptions) { + this._ignoreSslError = false; + this._allowRedirects = true; + this._allowRedirectDowngrade = false; + this._maxRedirects = 50; + this._allowRetries = false; + this._maxRetries = 1; + this._keepAlive = false; + this._disposed = false; + this.userAgent = userAgent; + this.handlers = handlers || []; + this.requestOptions = requestOptions; + if (requestOptions) { + if (requestOptions.ignoreSslError != null) { + this._ignoreSslError = requestOptions.ignoreSslError; + } + this._socketTimeout = requestOptions.socketTimeout; + if (requestOptions.allowRedirects != null) { + this._allowRedirects = requestOptions.allowRedirects; + } + if (requestOptions.allowRedirectDowngrade != null) { + this._allowRedirectDowngrade = requestOptions.allowRedirectDowngrade; + } + if (requestOptions.maxRedirects != null) { + this._maxRedirects = Math.max(requestOptions.maxRedirects, 0); + } + if (requestOptions.keepAlive != null) { + this._keepAlive = requestOptions.keepAlive; + } + if (requestOptions.allowRetries != null) { + this._allowRetries = requestOptions.allowRetries; + } + if (requestOptions.maxRetries != null) { + this._maxRetries = requestOptions.maxRetries; + } + } + } + options(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('OPTIONS', requestUrl, null, additionalHeaders || {}); + }); + } + get(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('GET', requestUrl, null, additionalHeaders || {}); + }); + } + del(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('DELETE', requestUrl, null, additionalHeaders || {}); + }); + } + post(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('POST', requestUrl, data, additionalHeaders || {}); + }); + } + patch(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PATCH', requestUrl, data, additionalHeaders || {}); + }); + } + put(requestUrl, data, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('PUT', requestUrl, data, additionalHeaders || {}); + }); + } + head(requestUrl, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request('HEAD', requestUrl, null, additionalHeaders || {}); + }); + } + sendStream(verb, requestUrl, stream, additionalHeaders) { + return __awaiter(this, void 0, void 0, function* () { + return this.request(verb, requestUrl, stream, additionalHeaders); + }); + } + /** + * Gets a typed object from an endpoint + * Be aware that not found returns a null. Other errors (4xx, 5xx) reject the promise + */ + getJson(requestUrl, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + const res = yield this.get(requestUrl, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + postJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.post(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + putJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.put(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + patchJson(requestUrl, obj, additionalHeaders = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = JSON.stringify(obj, null, 2); + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.Accept, MediaTypes.ApplicationJson); + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader(additionalHeaders, Headers.ContentType, MediaTypes.ApplicationJson); + const res = yield this.patch(requestUrl, data, additionalHeaders); + return this._processResponse(res, this.requestOptions); + }); + } + /** + * Makes a raw http request. + * All other methods such as get, post, patch, and request ultimately call this. + * Prefer get, del, post and patch + */ + request(verb, requestUrl, data, headers) { + return __awaiter(this, void 0, void 0, function* () { + if (this._disposed) { + throw new Error('Client has already been disposed.'); + } + const parsedUrl = new URL(requestUrl); + let info = this._prepareRequest(verb, parsedUrl, headers); + // Only perform retries on reads since writes may not be idempotent. + const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) + ? this._maxRetries + 1 + : 1; + let numTries = 0; + let response; + do { + response = yield this.requestRaw(info, data); + // Check if it's an authentication challenge + if (response && + response.message && + response.message.statusCode === HttpCodes.Unauthorized) { + let authenticationHandler; + for (const handler of this.handlers) { + if (handler.canHandleAuthentication(response)) { + authenticationHandler = handler; + break; + } + } + if (authenticationHandler) { + return authenticationHandler.handleAuthentication(this, info, data); + } + else { + // We have received an unauthorized response but have no handlers to handle it. + // Let the response return to the caller. + return response; + } + } + let redirectsRemaining = this._maxRedirects; + while (response.message.statusCode && + HttpRedirectCodes.includes(response.message.statusCode) && + this._allowRedirects && + redirectsRemaining > 0) { + const redirectUrl = response.message.headers['location']; + if (!redirectUrl) { + // if there's no location to redirect to, we won't + break; + } + const parsedRedirectUrl = new URL(redirectUrl); + if (parsedUrl.protocol === 'https:' && + parsedUrl.protocol !== parsedRedirectUrl.protocol && + !this._allowRedirectDowngrade) { + throw new Error('Redirect from HTTPS to HTTP protocol. This downgrade is not allowed for security reasons. If you want to allow this behavior, set the allowRedirectDowngrade option to true.'); + } + // we need to finish reading the response before reassigning response + // which will leak the open socket. + yield response.readBody(); + // strip authorization header if redirected to a different hostname + if (parsedRedirectUrl.hostname !== parsedUrl.hostname) { + for (const header in headers) { + // header names are case insensitive + if (header.toLowerCase() === 'authorization') { + delete headers[header]; + } + } + } + // let's make the request with the new redirectUrl + info = this._prepareRequest(verb, parsedRedirectUrl, headers); + response = yield this.requestRaw(info, data); + redirectsRemaining--; + } + if (!response.message.statusCode || + !HttpResponseRetryCodes.includes(response.message.statusCode)) { + // If not a retry code, return immediately instead of retrying + return response; + } + numTries += 1; + if (numTries < maxTries) { + yield response.readBody(); + yield this._performExponentialBackoff(numTries); + } + } while (numTries < maxTries); + return response; + }); + } + /** + * Needs to be called if keepAlive is set to true in request options. + */ + dispose() { + if (this._agent) { + this._agent.destroy(); + } + this._disposed = true; + } + /** + * Raw request. + * @param info + * @param data + */ + requestRaw(info, data) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => { + function callbackForResult(err, res) { + if (err) { + reject(err); + } + else if (!res) { + // If `err` is not passed, then `res` must be passed. + reject(new Error('Unknown error')); + } + else { + resolve(res); + } + } + this.requestRawWithCallback(info, data, callbackForResult); + }); + }); + } + /** + * Raw request with callback. + * @param info + * @param data + * @param onResult + */ + requestRawWithCallback(info, data, onResult) { + if (typeof data === 'string') { + if (!info.options.headers) { + info.options.headers = {}; + } + info.options.headers['Content-Length'] = Buffer.byteLength(data, 'utf8'); + } + let callbackCalled = false; + function handleResult(err, res) { + if (!callbackCalled) { + callbackCalled = true; + onResult(err, res); + } + } + const req = info.httpModule.request(info.options, (msg) => { + const res = new HttpClientResponse(msg); + handleResult(undefined, res); + }); + let socket; + req.on('socket', sock => { + socket = sock; + }); + // If we ever get disconnected, we want the socket to timeout eventually + req.setTimeout(this._socketTimeout || 3 * 60000, () => { + if (socket) { + socket.end(); + } + handleResult(new Error(`Request timeout: ${info.options.path}`)); + }); + req.on('error', function (err) { + // err has statusCode property + // res should have headers + handleResult(err); + }); + if (data && typeof data === 'string') { + req.write(data, 'utf8'); + } + if (data && typeof data !== 'string') { + data.on('close', function () { + req.end(); + }); + data.pipe(req); + } + else { + req.end(); + } + } + /** + * Gets an http agent. This function is useful when you need an http agent that handles + * routing through a proxy server - depending upon the url and proxy environment variables. + * @param serverUrl The server URL where the request will be sent. For example, https://api.github.com + */ + getAgent(serverUrl) { + const parsedUrl = new URL(serverUrl); + return this._getAgent(parsedUrl); + } + _prepareRequest(method, requestUrl, headers) { + const info = {}; + info.parsedUrl = requestUrl; + const usingSsl = info.parsedUrl.protocol === 'https:'; + info.httpModule = usingSsl ? https : http; + const defaultPort = usingSsl ? 443 : 80; + info.options = {}; + info.options.host = info.parsedUrl.hostname; + info.options.port = info.parsedUrl.port + ? parseInt(info.parsedUrl.port) + : defaultPort; + info.options.path = + (info.parsedUrl.pathname || '') + (info.parsedUrl.search || ''); + info.options.method = method; + info.options.headers = this._mergeHeaders(headers); + if (this.userAgent != null) { + info.options.headers['user-agent'] = this.userAgent; + } + info.options.agent = this._getAgent(info.parsedUrl); + // gives handlers an opportunity to participate + if (this.handlers) { + for (const handler of this.handlers) { + handler.prepareRequest(info.options); + } + } + return info; + } + _mergeHeaders(headers) { + if (this.requestOptions && this.requestOptions.headers) { + return Object.assign({}, lowercaseKeys(this.requestOptions.headers), lowercaseKeys(headers || {})); + } + return lowercaseKeys(headers || {}); + } + _getExistingOrDefaultHeader(additionalHeaders, header, _default) { + let clientHeader; + if (this.requestOptions && this.requestOptions.headers) { + clientHeader = lowercaseKeys(this.requestOptions.headers)[header]; + } + return additionalHeaders[header] || clientHeader || _default; + } + _getAgent(parsedUrl) { + let agent; + const proxyUrl = pm.getProxyUrl(parsedUrl); + const useProxy = proxyUrl && proxyUrl.hostname; + if (this._keepAlive && useProxy) { + agent = this._proxyAgent; + } + if (this._keepAlive && !useProxy) { + agent = this._agent; + } + // if agent is already assigned use that agent. + if (agent) { + return agent; + } + const usingSsl = parsedUrl.protocol === 'https:'; + let maxSockets = 100; + if (this.requestOptions) { + maxSockets = this.requestOptions.maxSockets || http.globalAgent.maxSockets; + } + // This is `useProxy` again, but we need to check `proxyURl` directly for TypeScripts's flow analysis. + if (proxyUrl && proxyUrl.hostname) { + const agentOptions = { + maxSockets, + keepAlive: this._keepAlive, + proxy: Object.assign(Object.assign({}, ((proxyUrl.username || proxyUrl.password) && { + proxyAuth: `${proxyUrl.username}:${proxyUrl.password}` + })), { host: proxyUrl.hostname, port: proxyUrl.port }) + }; + let tunnelAgent; + const overHttps = proxyUrl.protocol === 'https:'; + if (usingSsl) { + tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp; + } + else { + tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp; + } + agent = tunnelAgent(agentOptions); + this._proxyAgent = agent; + } + // if reusing agent across request and tunneling agent isn't assigned create a new agent + if (this._keepAlive && !agent) { + const options = { keepAlive: this._keepAlive, maxSockets }; + agent = usingSsl ? new https.Agent(options) : new http.Agent(options); + this._agent = agent; + } + // if not using private agent and tunnel agent isn't setup then use global agent + if (!agent) { + agent = usingSsl ? https.globalAgent : http.globalAgent; + } + if (usingSsl && this._ignoreSslError) { + // we don't want to set NODE_TLS_REJECT_UNAUTHORIZED=0 since that will affect request for entire process + // http.RequestOptions doesn't expose a way to modify RequestOptions.agent.options + // we have to cast it to any and change it directly + agent.options = Object.assign(agent.options || {}, { + rejectUnauthorized: false + }); + } + return agent; + } + _performExponentialBackoff(retryNumber) { + return __awaiter(this, void 0, void 0, function* () { + retryNumber = Math.min(ExponentialBackoffCeiling, retryNumber); + const ms = ExponentialBackoffTimeSlice * Math.pow(2, retryNumber); + return new Promise(resolve => setTimeout(() => resolve(), ms)); + }); + } + _processResponse(res, options) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () { + const statusCode = res.message.statusCode || 0; + const response = { + statusCode, + result: null, + headers: {} + }; + // not found leads to null obj returned + if (statusCode === HttpCodes.NotFound) { + resolve(response); + } + // get the result from the body + function dateTimeDeserializer(key, value) { + if (typeof value === 'string') { + const a = new Date(value); + if (!isNaN(a.valueOf())) { + return a; + } + } + return value; + } + let obj; + let contents; + try { + contents = yield res.readBody(); + if (contents && contents.length > 0) { + if (options && options.deserializeDates) { + obj = JSON.parse(contents, dateTimeDeserializer); + } + else { + obj = JSON.parse(contents); + } + response.result = obj; + } + response.headers = res.message.headers; + } + catch (err) { + // Invalid resource (contents not json); leaving result obj null + } + // note that 3xx redirects are handled by the http layer. + if (statusCode > 299) { + let msg; + // if exception/error in body, attempt to get better error + if (obj && obj.message) { + msg = obj.message; + } + else if (contents && contents.length > 0) { + // it may be the case that the exception is in the body message as string + msg = contents; + } + else { + msg = `Failed request: (${statusCode})`; + } + const err = new HttpClientError(msg, statusCode); + err.result = response.result; + reject(err); + } + else { + resolve(response); + } + })); + }); + } +} +exports.HttpClient = HttpClient; +const lowercaseKeys = (obj) => Object.keys(obj).reduce((c, k) => ((c[k.toLowerCase()] = obj[k]), c), {}); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 9835: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.checkBypass = exports.getProxyUrl = void 0; +function getProxyUrl(reqUrl) { + const usingSsl = reqUrl.protocol === 'https:'; + if (checkBypass(reqUrl)) { + return undefined; + } + const proxyVar = (() => { + if (usingSsl) { + return process.env['https_proxy'] || process.env['HTTPS_PROXY']; + } + else { + return process.env['http_proxy'] || process.env['HTTP_PROXY']; + } + })(); + if (proxyVar) { + return new URL(proxyVar); + } + else { + return undefined; + } +} +exports.getProxyUrl = getProxyUrl; +function checkBypass(reqUrl) { + if (!reqUrl.hostname) { + return false; + } + const noProxy = process.env['no_proxy'] || process.env['NO_PROXY'] || ''; + if (!noProxy) { + return false; + } + // Determine the request port + let reqPort; + if (reqUrl.port) { + reqPort = Number(reqUrl.port); + } + else if (reqUrl.protocol === 'http:') { + reqPort = 80; + } + else if (reqUrl.protocol === 'https:') { + reqPort = 443; + } + // Format the request hostname and hostname with port + const upperReqHosts = [reqUrl.hostname.toUpperCase()]; + if (typeof reqPort === 'number') { + upperReqHosts.push(`${upperReqHosts[0]}:${reqPort}`); + } + // Compare request host against noproxy + for (const upperNoProxyItem of noProxy + .split(',') + .map(x => x.trim().toUpperCase()) + .filter(x => x)) { + if (upperReqHosts.some(x => x === upperNoProxyItem)) { + return true; + } + } + return false; +} +exports.checkBypass = checkBypass; +//# sourceMappingURL=proxy.js.map + +/***/ }), + +/***/ 4193: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +const VERSION = "3.1.0"; + +/** + * Some ā€œlistā€ response that can be paginated have a different response structure + * + * They have a `total_count` key in the response (search also has `incomplete_results`, + * /installation/repositories also has `repository_selection`), as well as a key with + * the list of the items which name varies from endpoint to endpoint. + * + * Octokit normalizes these responses so that paginated results are always returned following + * the same structure. One challenge is that if the list response has only one page, no Link + * header is provided, so this header alone is not sufficient to check wether a response is + * paginated or not. + * + * We check if a "total_count" key is present in the response data, but also make sure that + * a "url" property is not, as the "Get the combined status for a specific ref" endpoint would + * otherwise match: https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref + */ +function normalizePaginatedListResponse(response) { + // endpoints can respond with 204 if repository is empty + if (!response.data) { + return { ...response, + data: [] + }; + } + + const responseNeedsNormalization = "total_count" in response.data && !("url" in response.data); + if (!responseNeedsNormalization) return response; // keep the additional properties intact as there is currently no other way + // to retrieve the same information. + + const incompleteResults = response.data.incomplete_results; + const repositorySelection = response.data.repository_selection; + const totalCount = response.data.total_count; + delete response.data.incomplete_results; + delete response.data.repository_selection; + delete response.data.total_count; + const namespaceKey = Object.keys(response.data)[0]; + const data = response.data[namespaceKey]; + response.data = data; + + if (typeof incompleteResults !== "undefined") { + response.data.incomplete_results = incompleteResults; + } + + if (typeof repositorySelection !== "undefined") { + response.data.repository_selection = repositorySelection; + } + + response.data.total_count = totalCount; + return response; +} + +function iterator(octokit, route, parameters) { + const options = typeof route === "function" ? route.endpoint(parameters) : octokit.request.endpoint(route, parameters); + const requestMethod = typeof route === "function" ? route : octokit.request; + const method = options.method; + const headers = options.headers; + let url = options.url; + return { + [Symbol.asyncIterator]: () => ({ + async next() { + if (!url) return { + done: true + }; + + try { + const response = await requestMethod({ + method, + url, + headers + }); + const normalizedResponse = normalizePaginatedListResponse(response); // `response.headers.link` format: + // '; rel="next", ; rel="last"' + // sets `url` to undefined if "next" URL is not present or `link` header is not set + + url = ((normalizedResponse.headers.link || "").match(/<([^>]+)>;\s*rel="next"/) || [])[1]; + return { + value: normalizedResponse + }; + } catch (error) { + if (error.status !== 409) throw error; + url = ""; + return { + value: { + status: 200, + headers: {}, + data: [] + } + }; + } + } + + }) + }; +} + +function paginate(octokit, route, parameters, mapFn) { + if (typeof parameters === "function") { + mapFn = parameters; + parameters = undefined; + } + + return gather(octokit, [], iterator(octokit, route, parameters)[Symbol.asyncIterator](), mapFn); +} + +function gather(octokit, results, iterator, mapFn) { + return iterator.next().then(result => { + if (result.done) { + return results; + } + + let earlyExit = false; + + function done() { + earlyExit = true; + } + + results = results.concat(mapFn ? mapFn(result.value, done) : result.value.data); + + if (earlyExit) { + return results; + } + + return gather(octokit, results, iterator, mapFn); + }); +} + +const composePaginateRest = Object.assign(paginate, { + iterator +}); + +const paginatingEndpoints = ["GET /app/hook/deliveries", "GET /app/installations", "GET /applications/grants", "GET /authorizations", "GET /enterprises/{enterprise}/actions/permissions/organizations", "GET /enterprises/{enterprise}/actions/runner-groups", "GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/organizations", "GET /enterprises/{enterprise}/actions/runner-groups/{runner_group_id}/runners", "GET /enterprises/{enterprise}/actions/runners", "GET /enterprises/{enterprise}/audit-log", "GET /enterprises/{enterprise}/code-scanning/alerts", "GET /enterprises/{enterprise}/secret-scanning/alerts", "GET /enterprises/{enterprise}/settings/billing/advanced-security", "GET /events", "GET /gists", "GET /gists/public", "GET /gists/starred", "GET /gists/{gist_id}/comments", "GET /gists/{gist_id}/commits", "GET /gists/{gist_id}/forks", "GET /installation/repositories", "GET /issues", "GET /licenses", "GET /marketplace_listing/plans", "GET /marketplace_listing/plans/{plan_id}/accounts", "GET /marketplace_listing/stubbed/plans", "GET /marketplace_listing/stubbed/plans/{plan_id}/accounts", "GET /networks/{owner}/{repo}/events", "GET /notifications", "GET /organizations", "GET /orgs/{org}/actions/cache/usage-by-repository", "GET /orgs/{org}/actions/permissions/repositories", "GET /orgs/{org}/actions/runner-groups", "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/repositories", "GET /orgs/{org}/actions/runner-groups/{runner_group_id}/runners", "GET /orgs/{org}/actions/runners", "GET /orgs/{org}/actions/secrets", "GET /orgs/{org}/actions/secrets/{secret_name}/repositories", "GET /orgs/{org}/audit-log", "GET /orgs/{org}/blocks", "GET /orgs/{org}/code-scanning/alerts", "GET /orgs/{org}/codespaces", "GET /orgs/{org}/credential-authorizations", "GET /orgs/{org}/dependabot/secrets", "GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories", "GET /orgs/{org}/events", "GET /orgs/{org}/external-groups", "GET /orgs/{org}/failed_invitations", "GET /orgs/{org}/hooks", "GET /orgs/{org}/hooks/{hook_id}/deliveries", "GET /orgs/{org}/installations", "GET /orgs/{org}/invitations", "GET /orgs/{org}/invitations/{invitation_id}/teams", "GET /orgs/{org}/issues", "GET /orgs/{org}/members", "GET /orgs/{org}/migrations", "GET /orgs/{org}/migrations/{migration_id}/repositories", "GET /orgs/{org}/outside_collaborators", "GET /orgs/{org}/packages", "GET /orgs/{org}/packages/{package_type}/{package_name}/versions", "GET /orgs/{org}/projects", "GET /orgs/{org}/public_members", "GET /orgs/{org}/repos", "GET /orgs/{org}/secret-scanning/alerts", "GET /orgs/{org}/settings/billing/advanced-security", "GET /orgs/{org}/team-sync/groups", "GET /orgs/{org}/teams", "GET /orgs/{org}/teams/{team_slug}/discussions", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions", "GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions", "GET /orgs/{org}/teams/{team_slug}/invitations", "GET /orgs/{org}/teams/{team_slug}/members", "GET /orgs/{org}/teams/{team_slug}/projects", "GET /orgs/{org}/teams/{team_slug}/repos", "GET /orgs/{org}/teams/{team_slug}/teams", "GET /projects/columns/{column_id}/cards", "GET /projects/{project_id}/collaborators", "GET /projects/{project_id}/columns", "GET /repos/{owner}/{repo}/actions/artifacts", "GET /repos/{owner}/{repo}/actions/caches", "GET /repos/{owner}/{repo}/actions/runners", "GET /repos/{owner}/{repo}/actions/runs", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs", "GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs", "GET /repos/{owner}/{repo}/actions/secrets", "GET /repos/{owner}/{repo}/actions/workflows", "GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs", "GET /repos/{owner}/{repo}/assignees", "GET /repos/{owner}/{repo}/branches", "GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations", "GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs", "GET /repos/{owner}/{repo}/code-scanning/alerts", "GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", "GET /repos/{owner}/{repo}/code-scanning/analyses", "GET /repos/{owner}/{repo}/codespaces", "GET /repos/{owner}/{repo}/codespaces/devcontainers", "GET /repos/{owner}/{repo}/codespaces/secrets", "GET /repos/{owner}/{repo}/collaborators", "GET /repos/{owner}/{repo}/comments", "GET /repos/{owner}/{repo}/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/commits", "GET /repos/{owner}/{repo}/commits/{commit_sha}/comments", "GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls", "GET /repos/{owner}/{repo}/commits/{ref}/check-runs", "GET /repos/{owner}/{repo}/commits/{ref}/check-suites", "GET /repos/{owner}/{repo}/commits/{ref}/status", "GET /repos/{owner}/{repo}/commits/{ref}/statuses", "GET /repos/{owner}/{repo}/contributors", "GET /repos/{owner}/{repo}/dependabot/secrets", "GET /repos/{owner}/{repo}/deployments", "GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses", "GET /repos/{owner}/{repo}/environments", "GET /repos/{owner}/{repo}/events", "GET /repos/{owner}/{repo}/forks", "GET /repos/{owner}/{repo}/git/matching-refs/{ref}", "GET /repos/{owner}/{repo}/hooks", "GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries", "GET /repos/{owner}/{repo}/invitations", "GET /repos/{owner}/{repo}/issues", "GET /repos/{owner}/{repo}/issues/comments", "GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/issues/events", "GET /repos/{owner}/{repo}/issues/{issue_number}/comments", "GET /repos/{owner}/{repo}/issues/{issue_number}/events", "GET /repos/{owner}/{repo}/issues/{issue_number}/labels", "GET /repos/{owner}/{repo}/issues/{issue_number}/reactions", "GET /repos/{owner}/{repo}/issues/{issue_number}/timeline", "GET /repos/{owner}/{repo}/keys", "GET /repos/{owner}/{repo}/labels", "GET /repos/{owner}/{repo}/milestones", "GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels", "GET /repos/{owner}/{repo}/notifications", "GET /repos/{owner}/{repo}/pages/builds", "GET /repos/{owner}/{repo}/projects", "GET /repos/{owner}/{repo}/pulls", "GET /repos/{owner}/{repo}/pulls/comments", "GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions", "GET /repos/{owner}/{repo}/pulls/{pull_number}/comments", "GET /repos/{owner}/{repo}/pulls/{pull_number}/commits", "GET /repos/{owner}/{repo}/pulls/{pull_number}/files", "GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers", "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews", "GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments", "GET /repos/{owner}/{repo}/releases", "GET /repos/{owner}/{repo}/releases/{release_id}/assets", "GET /repos/{owner}/{repo}/releases/{release_id}/reactions", "GET /repos/{owner}/{repo}/secret-scanning/alerts", "GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations", "GET /repos/{owner}/{repo}/stargazers", "GET /repos/{owner}/{repo}/subscribers", "GET /repos/{owner}/{repo}/tags", "GET /repos/{owner}/{repo}/teams", "GET /repos/{owner}/{repo}/topics", "GET /repositories", "GET /repositories/{repository_id}/environments/{environment_name}/secrets", "GET /search/code", "GET /search/commits", "GET /search/issues", "GET /search/labels", "GET /search/repositories", "GET /search/topics", "GET /search/users", "GET /teams/{team_id}/discussions", "GET /teams/{team_id}/discussions/{discussion_number}/comments", "GET /teams/{team_id}/discussions/{discussion_number}/comments/{comment_number}/reactions", "GET /teams/{team_id}/discussions/{discussion_number}/reactions", "GET /teams/{team_id}/invitations", "GET /teams/{team_id}/members", "GET /teams/{team_id}/projects", "GET /teams/{team_id}/repos", "GET /teams/{team_id}/teams", "GET /user/blocks", "GET /user/codespaces", "GET /user/codespaces/secrets", "GET /user/emails", "GET /user/followers", "GET /user/following", "GET /user/gpg_keys", "GET /user/installations", "GET /user/installations/{installation_id}/repositories", "GET /user/issues", "GET /user/keys", "GET /user/marketplace_purchases", "GET /user/marketplace_purchases/stubbed", "GET /user/memberships/orgs", "GET /user/migrations", "GET /user/migrations/{migration_id}/repositories", "GET /user/orgs", "GET /user/packages", "GET /user/packages/{package_type}/{package_name}/versions", "GET /user/public_emails", "GET /user/repos", "GET /user/repository_invitations", "GET /user/starred", "GET /user/subscriptions", "GET /user/teams", "GET /users", "GET /users/{username}/events", "GET /users/{username}/events/orgs/{org}", "GET /users/{username}/events/public", "GET /users/{username}/followers", "GET /users/{username}/following", "GET /users/{username}/gists", "GET /users/{username}/gpg_keys", "GET /users/{username}/keys", "GET /users/{username}/orgs", "GET /users/{username}/packages", "GET /users/{username}/projects", "GET /users/{username}/received_events", "GET /users/{username}/received_events/public", "GET /users/{username}/repos", "GET /users/{username}/starred", "GET /users/{username}/subscriptions"]; + +function isPaginatingEndpoint(arg) { + if (typeof arg === "string") { + return paginatingEndpoints.includes(arg); + } else { + return false; + } +} + +/** + * @param octokit Octokit instance + * @param options Options passed to Octokit constructor + */ + +function paginateRest(octokit) { + return { + paginate: Object.assign(paginate.bind(null, octokit), { + iterator: iterator.bind(null, octokit) + }) + }; +} +paginateRest.VERSION = VERSION; + +exports.composePaginateRest = composePaginateRest; +exports.isPaginatingEndpoint = isPaginatingEndpoint; +exports.paginateRest = paginateRest; +exports.paginatingEndpoints = paginatingEndpoints; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 3044: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + + if (enumerableOnly) { + symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + } + + keys.push.apply(keys, symbols); + } + + return keys; +} + +function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + + if (i % 2) { + ownKeys(Object(source), true).forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + + return target; +} + +function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; +} + +const Endpoints = { + actions: { + addCustomLabelsToSelfHostedRunnerForOrg: ["POST /orgs/{org}/actions/runners/{runner_id}/labels"], + addCustomLabelsToSelfHostedRunnerForRepo: ["POST /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"], + addSelectedRepoToOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"], + approveWorkflowRun: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve"], + cancelWorkflowRun: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel"], + createOrUpdateEnvironmentSecret: ["PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"], + createOrUpdateOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}"], + createOrUpdateRepoSecret: ["PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}"], + createRegistrationTokenForOrg: ["POST /orgs/{org}/actions/runners/registration-token"], + createRegistrationTokenForRepo: ["POST /repos/{owner}/{repo}/actions/runners/registration-token"], + createRemoveTokenForOrg: ["POST /orgs/{org}/actions/runners/remove-token"], + createRemoveTokenForRepo: ["POST /repos/{owner}/{repo}/actions/runners/remove-token"], + createWorkflowDispatch: ["POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches"], + deleteActionsCacheById: ["DELETE /repos/{owner}/{repo}/actions/caches/{cache_id}"], + deleteActionsCacheByKey: ["DELETE /repos/{owner}/{repo}/actions/caches{?key,ref}"], + deleteArtifact: ["DELETE /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"], + deleteEnvironmentSecret: ["DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"], + deleteOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}"], + deleteRepoSecret: ["DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}"], + deleteSelfHostedRunnerFromOrg: ["DELETE /orgs/{org}/actions/runners/{runner_id}"], + deleteSelfHostedRunnerFromRepo: ["DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}"], + deleteWorkflowRun: ["DELETE /repos/{owner}/{repo}/actions/runs/{run_id}"], + deleteWorkflowRunLogs: ["DELETE /repos/{owner}/{repo}/actions/runs/{run_id}/logs"], + disableSelectedRepositoryGithubActionsOrganization: ["DELETE /orgs/{org}/actions/permissions/repositories/{repository_id}"], + disableWorkflow: ["PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable"], + downloadArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}"], + downloadJobLogsForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs"], + downloadWorkflowRunAttemptLogs: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/logs"], + downloadWorkflowRunLogs: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/logs"], + enableSelectedRepositoryGithubActionsOrganization: ["PUT /orgs/{org}/actions/permissions/repositories/{repository_id}"], + enableWorkflow: ["PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/enable"], + getActionsCacheList: ["GET /repos/{owner}/{repo}/actions/caches"], + getActionsCacheUsage: ["GET /repos/{owner}/{repo}/actions/cache/usage"], + getActionsCacheUsageByRepoForOrg: ["GET /orgs/{org}/actions/cache/usage-by-repository"], + getActionsCacheUsageForEnterprise: ["GET /enterprises/{enterprise}/actions/cache/usage"], + getActionsCacheUsageForOrg: ["GET /orgs/{org}/actions/cache/usage"], + getAllowedActionsOrganization: ["GET /orgs/{org}/actions/permissions/selected-actions"], + getAllowedActionsRepository: ["GET /repos/{owner}/{repo}/actions/permissions/selected-actions"], + getArtifact: ["GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}"], + getEnvironmentPublicKey: ["GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key"], + getEnvironmentSecret: ["GET /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name}"], + getGithubActionsDefaultWorkflowPermissionsEnterprise: ["GET /enterprises/{enterprise}/actions/permissions/workflow"], + getGithubActionsDefaultWorkflowPermissionsOrganization: ["GET /orgs/{org}/actions/permissions/workflow"], + getGithubActionsDefaultWorkflowPermissionsRepository: ["GET /repos/{owner}/{repo}/actions/permissions/workflow"], + getGithubActionsPermissionsOrganization: ["GET /orgs/{org}/actions/permissions"], + getGithubActionsPermissionsRepository: ["GET /repos/{owner}/{repo}/actions/permissions"], + getJobForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/jobs/{job_id}"], + getOrgPublicKey: ["GET /orgs/{org}/actions/secrets/public-key"], + getOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}"], + getPendingDeploymentsForRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments"], + getRepoPermissions: ["GET /repos/{owner}/{repo}/actions/permissions", {}, { + renamed: ["actions", "getGithubActionsPermissionsRepository"] + }], + getRepoPublicKey: ["GET /repos/{owner}/{repo}/actions/secrets/public-key"], + getRepoSecret: ["GET /repos/{owner}/{repo}/actions/secrets/{secret_name}"], + getReviewsForRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/approvals"], + getSelfHostedRunnerForOrg: ["GET /orgs/{org}/actions/runners/{runner_id}"], + getSelfHostedRunnerForRepo: ["GET /repos/{owner}/{repo}/actions/runners/{runner_id}"], + getWorkflow: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}"], + getWorkflowAccessToRepository: ["GET /repos/{owner}/{repo}/actions/permissions/access"], + getWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}"], + getWorkflowRunAttempt: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}"], + getWorkflowRunUsage: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/timing"], + getWorkflowUsage: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/timing"], + listArtifactsForRepo: ["GET /repos/{owner}/{repo}/actions/artifacts"], + listEnvironmentSecrets: ["GET /repositories/{repository_id}/environments/{environment_name}/secrets"], + listJobsForWorkflowRun: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs"], + listJobsForWorkflowRunAttempt: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt_number}/jobs"], + listLabelsForSelfHostedRunnerForOrg: ["GET /orgs/{org}/actions/runners/{runner_id}/labels"], + listLabelsForSelfHostedRunnerForRepo: ["GET /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"], + listOrgSecrets: ["GET /orgs/{org}/actions/secrets"], + listRepoSecrets: ["GET /repos/{owner}/{repo}/actions/secrets"], + listRepoWorkflows: ["GET /repos/{owner}/{repo}/actions/workflows"], + listRunnerApplicationsForOrg: ["GET /orgs/{org}/actions/runners/downloads"], + listRunnerApplicationsForRepo: ["GET /repos/{owner}/{repo}/actions/runners/downloads"], + listSelectedReposForOrgSecret: ["GET /orgs/{org}/actions/secrets/{secret_name}/repositories"], + listSelectedRepositoriesEnabledGithubActionsOrganization: ["GET /orgs/{org}/actions/permissions/repositories"], + listSelfHostedRunnersForOrg: ["GET /orgs/{org}/actions/runners"], + listSelfHostedRunnersForRepo: ["GET /repos/{owner}/{repo}/actions/runners"], + listWorkflowRunArtifacts: ["GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts"], + listWorkflowRuns: ["GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs"], + listWorkflowRunsForRepo: ["GET /repos/{owner}/{repo}/actions/runs"], + reRunJobForWorkflowRun: ["POST /repos/{owner}/{repo}/actions/jobs/{job_id}/rerun"], + reRunWorkflow: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun"], + reRunWorkflowFailedJobs: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs"], + removeAllCustomLabelsFromSelfHostedRunnerForOrg: ["DELETE /orgs/{org}/actions/runners/{runner_id}/labels"], + removeAllCustomLabelsFromSelfHostedRunnerForRepo: ["DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"], + removeCustomLabelFromSelfHostedRunnerForOrg: ["DELETE /orgs/{org}/actions/runners/{runner_id}/labels/{name}"], + removeCustomLabelFromSelfHostedRunnerForRepo: ["DELETE /repos/{owner}/{repo}/actions/runners/{runner_id}/labels/{name}"], + removeSelectedRepoFromOrgSecret: ["DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id}"], + reviewPendingDeploymentsForRun: ["POST /repos/{owner}/{repo}/actions/runs/{run_id}/pending_deployments"], + setAllowedActionsOrganization: ["PUT /orgs/{org}/actions/permissions/selected-actions"], + setAllowedActionsRepository: ["PUT /repos/{owner}/{repo}/actions/permissions/selected-actions"], + setCustomLabelsForSelfHostedRunnerForOrg: ["PUT /orgs/{org}/actions/runners/{runner_id}/labels"], + setCustomLabelsForSelfHostedRunnerForRepo: ["PUT /repos/{owner}/{repo}/actions/runners/{runner_id}/labels"], + setGithubActionsDefaultWorkflowPermissionsEnterprise: ["PUT /enterprises/{enterprise}/actions/permissions/workflow"], + setGithubActionsDefaultWorkflowPermissionsOrganization: ["PUT /orgs/{org}/actions/permissions/workflow"], + setGithubActionsDefaultWorkflowPermissionsRepository: ["PUT /repos/{owner}/{repo}/actions/permissions/workflow"], + setGithubActionsPermissionsOrganization: ["PUT /orgs/{org}/actions/permissions"], + setGithubActionsPermissionsRepository: ["PUT /repos/{owner}/{repo}/actions/permissions"], + setSelectedReposForOrgSecret: ["PUT /orgs/{org}/actions/secrets/{secret_name}/repositories"], + setSelectedRepositoriesEnabledGithubActionsOrganization: ["PUT /orgs/{org}/actions/permissions/repositories"], + setWorkflowAccessToRepository: ["PUT /repos/{owner}/{repo}/actions/permissions/access"] + }, + activity: { + checkRepoIsStarredByAuthenticatedUser: ["GET /user/starred/{owner}/{repo}"], + deleteRepoSubscription: ["DELETE /repos/{owner}/{repo}/subscription"], + deleteThreadSubscription: ["DELETE /notifications/threads/{thread_id}/subscription"], + getFeeds: ["GET /feeds"], + getRepoSubscription: ["GET /repos/{owner}/{repo}/subscription"], + getThread: ["GET /notifications/threads/{thread_id}"], + getThreadSubscriptionForAuthenticatedUser: ["GET /notifications/threads/{thread_id}/subscription"], + listEventsForAuthenticatedUser: ["GET /users/{username}/events"], + listNotificationsForAuthenticatedUser: ["GET /notifications"], + listOrgEventsForAuthenticatedUser: ["GET /users/{username}/events/orgs/{org}"], + listPublicEvents: ["GET /events"], + listPublicEventsForRepoNetwork: ["GET /networks/{owner}/{repo}/events"], + listPublicEventsForUser: ["GET /users/{username}/events/public"], + listPublicOrgEvents: ["GET /orgs/{org}/events"], + listReceivedEventsForUser: ["GET /users/{username}/received_events"], + listReceivedPublicEventsForUser: ["GET /users/{username}/received_events/public"], + listRepoEvents: ["GET /repos/{owner}/{repo}/events"], + listRepoNotificationsForAuthenticatedUser: ["GET /repos/{owner}/{repo}/notifications"], + listReposStarredByAuthenticatedUser: ["GET /user/starred"], + listReposStarredByUser: ["GET /users/{username}/starred"], + listReposWatchedByUser: ["GET /users/{username}/subscriptions"], + listStargazersForRepo: ["GET /repos/{owner}/{repo}/stargazers"], + listWatchedReposForAuthenticatedUser: ["GET /user/subscriptions"], + listWatchersForRepo: ["GET /repos/{owner}/{repo}/subscribers"], + markNotificationsAsRead: ["PUT /notifications"], + markRepoNotificationsAsRead: ["PUT /repos/{owner}/{repo}/notifications"], + markThreadAsRead: ["PATCH /notifications/threads/{thread_id}"], + setRepoSubscription: ["PUT /repos/{owner}/{repo}/subscription"], + setThreadSubscription: ["PUT /notifications/threads/{thread_id}/subscription"], + starRepoForAuthenticatedUser: ["PUT /user/starred/{owner}/{repo}"], + unstarRepoForAuthenticatedUser: ["DELETE /user/starred/{owner}/{repo}"] + }, + apps: { + addRepoToInstallation: ["PUT /user/installations/{installation_id}/repositories/{repository_id}", {}, { + renamed: ["apps", "addRepoToInstallationForAuthenticatedUser"] + }], + addRepoToInstallationForAuthenticatedUser: ["PUT /user/installations/{installation_id}/repositories/{repository_id}"], + checkToken: ["POST /applications/{client_id}/token"], + createFromManifest: ["POST /app-manifests/{code}/conversions"], + createInstallationAccessToken: ["POST /app/installations/{installation_id}/access_tokens"], + deleteAuthorization: ["DELETE /applications/{client_id}/grant"], + deleteInstallation: ["DELETE /app/installations/{installation_id}"], + deleteToken: ["DELETE /applications/{client_id}/token"], + getAuthenticated: ["GET /app"], + getBySlug: ["GET /apps/{app_slug}"], + getInstallation: ["GET /app/installations/{installation_id}"], + getOrgInstallation: ["GET /orgs/{org}/installation"], + getRepoInstallation: ["GET /repos/{owner}/{repo}/installation"], + getSubscriptionPlanForAccount: ["GET /marketplace_listing/accounts/{account_id}"], + getSubscriptionPlanForAccountStubbed: ["GET /marketplace_listing/stubbed/accounts/{account_id}"], + getUserInstallation: ["GET /users/{username}/installation"], + getWebhookConfigForApp: ["GET /app/hook/config"], + getWebhookDelivery: ["GET /app/hook/deliveries/{delivery_id}"], + listAccountsForPlan: ["GET /marketplace_listing/plans/{plan_id}/accounts"], + listAccountsForPlanStubbed: ["GET /marketplace_listing/stubbed/plans/{plan_id}/accounts"], + listInstallationReposForAuthenticatedUser: ["GET /user/installations/{installation_id}/repositories"], + listInstallations: ["GET /app/installations"], + listInstallationsForAuthenticatedUser: ["GET /user/installations"], + listPlans: ["GET /marketplace_listing/plans"], + listPlansStubbed: ["GET /marketplace_listing/stubbed/plans"], + listReposAccessibleToInstallation: ["GET /installation/repositories"], + listSubscriptionsForAuthenticatedUser: ["GET /user/marketplace_purchases"], + listSubscriptionsForAuthenticatedUserStubbed: ["GET /user/marketplace_purchases/stubbed"], + listWebhookDeliveries: ["GET /app/hook/deliveries"], + redeliverWebhookDelivery: ["POST /app/hook/deliveries/{delivery_id}/attempts"], + removeRepoFromInstallation: ["DELETE /user/installations/{installation_id}/repositories/{repository_id}", {}, { + renamed: ["apps", "removeRepoFromInstallationForAuthenticatedUser"] + }], + removeRepoFromInstallationForAuthenticatedUser: ["DELETE /user/installations/{installation_id}/repositories/{repository_id}"], + resetToken: ["PATCH /applications/{client_id}/token"], + revokeInstallationAccessToken: ["DELETE /installation/token"], + scopeToken: ["POST /applications/{client_id}/token/scoped"], + suspendInstallation: ["PUT /app/installations/{installation_id}/suspended"], + unsuspendInstallation: ["DELETE /app/installations/{installation_id}/suspended"], + updateWebhookConfigForApp: ["PATCH /app/hook/config"] + }, + billing: { + getGithubActionsBillingOrg: ["GET /orgs/{org}/settings/billing/actions"], + getGithubActionsBillingUser: ["GET /users/{username}/settings/billing/actions"], + getGithubAdvancedSecurityBillingGhe: ["GET /enterprises/{enterprise}/settings/billing/advanced-security"], + getGithubAdvancedSecurityBillingOrg: ["GET /orgs/{org}/settings/billing/advanced-security"], + getGithubPackagesBillingOrg: ["GET /orgs/{org}/settings/billing/packages"], + getGithubPackagesBillingUser: ["GET /users/{username}/settings/billing/packages"], + getSharedStorageBillingOrg: ["GET /orgs/{org}/settings/billing/shared-storage"], + getSharedStorageBillingUser: ["GET /users/{username}/settings/billing/shared-storage"] + }, + checks: { + create: ["POST /repos/{owner}/{repo}/check-runs"], + createSuite: ["POST /repos/{owner}/{repo}/check-suites"], + get: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}"], + getSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}"], + listAnnotations: ["GET /repos/{owner}/{repo}/check-runs/{check_run_id}/annotations"], + listForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-runs"], + listForSuite: ["GET /repos/{owner}/{repo}/check-suites/{check_suite_id}/check-runs"], + listSuitesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/check-suites"], + rerequestRun: ["POST /repos/{owner}/{repo}/check-runs/{check_run_id}/rerequest"], + rerequestSuite: ["POST /repos/{owner}/{repo}/check-suites/{check_suite_id}/rerequest"], + setSuitesPreferences: ["PATCH /repos/{owner}/{repo}/check-suites/preferences"], + update: ["PATCH /repos/{owner}/{repo}/check-runs/{check_run_id}"] + }, + codeScanning: { + deleteAnalysis: ["DELETE /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}{?confirm_delete}"], + getAlert: ["GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}", {}, { + renamedParameters: { + alert_id: "alert_number" + } + }], + getAnalysis: ["GET /repos/{owner}/{repo}/code-scanning/analyses/{analysis_id}"], + getSarif: ["GET /repos/{owner}/{repo}/code-scanning/sarifs/{sarif_id}"], + listAlertInstances: ["GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances"], + listAlertsForOrg: ["GET /orgs/{org}/code-scanning/alerts"], + listAlertsForRepo: ["GET /repos/{owner}/{repo}/code-scanning/alerts"], + listAlertsInstances: ["GET /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}/instances", {}, { + renamed: ["codeScanning", "listAlertInstances"] + }], + listRecentAnalyses: ["GET /repos/{owner}/{repo}/code-scanning/analyses"], + updateAlert: ["PATCH /repos/{owner}/{repo}/code-scanning/alerts/{alert_number}"], + uploadSarif: ["POST /repos/{owner}/{repo}/code-scanning/sarifs"] + }, + codesOfConduct: { + getAllCodesOfConduct: ["GET /codes_of_conduct"], + getConductCode: ["GET /codes_of_conduct/{key}"] + }, + codespaces: { + addRepositoryForSecretForAuthenticatedUser: ["PUT /user/codespaces/secrets/{secret_name}/repositories/{repository_id}"], + codespaceMachinesForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}/machines"], + createForAuthenticatedUser: ["POST /user/codespaces"], + createOrUpdateRepoSecret: ["PUT /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"], + createOrUpdateSecretForAuthenticatedUser: ["PUT /user/codespaces/secrets/{secret_name}"], + createWithPrForAuthenticatedUser: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/codespaces"], + createWithRepoForAuthenticatedUser: ["POST /repos/{owner}/{repo}/codespaces"], + deleteForAuthenticatedUser: ["DELETE /user/codespaces/{codespace_name}"], + deleteFromOrganization: ["DELETE /orgs/{org}/members/{username}/codespaces/{codespace_name}"], + deleteRepoSecret: ["DELETE /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"], + deleteSecretForAuthenticatedUser: ["DELETE /user/codespaces/secrets/{secret_name}"], + exportForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/exports"], + getExportDetailsForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}/exports/{export_id}"], + getForAuthenticatedUser: ["GET /user/codespaces/{codespace_name}"], + getPublicKeyForAuthenticatedUser: ["GET /user/codespaces/secrets/public-key"], + getRepoPublicKey: ["GET /repos/{owner}/{repo}/codespaces/secrets/public-key"], + getRepoSecret: ["GET /repos/{owner}/{repo}/codespaces/secrets/{secret_name}"], + getSecretForAuthenticatedUser: ["GET /user/codespaces/secrets/{secret_name}"], + listDevcontainersInRepositoryForAuthenticatedUser: ["GET /repos/{owner}/{repo}/codespaces/devcontainers"], + listForAuthenticatedUser: ["GET /user/codespaces"], + listInOrganization: ["GET /orgs/{org}/codespaces", {}, { + renamedParameters: { + org_id: "org" + } + }], + listInRepositoryForAuthenticatedUser: ["GET /repos/{owner}/{repo}/codespaces"], + listRepoSecrets: ["GET /repos/{owner}/{repo}/codespaces/secrets"], + listRepositoriesForSecretForAuthenticatedUser: ["GET /user/codespaces/secrets/{secret_name}/repositories"], + listSecretsForAuthenticatedUser: ["GET /user/codespaces/secrets"], + removeRepositoryForSecretForAuthenticatedUser: ["DELETE /user/codespaces/secrets/{secret_name}/repositories/{repository_id}"], + repoMachinesForAuthenticatedUser: ["GET /repos/{owner}/{repo}/codespaces/machines"], + setRepositoriesForSecretForAuthenticatedUser: ["PUT /user/codespaces/secrets/{secret_name}/repositories"], + startForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/start"], + stopForAuthenticatedUser: ["POST /user/codespaces/{codespace_name}/stop"], + stopInOrganization: ["POST /orgs/{org}/members/{username}/codespaces/{codespace_name}/stop"], + updateForAuthenticatedUser: ["PATCH /user/codespaces/{codespace_name}"] + }, + dependabot: { + addSelectedRepoToOrgSecret: ["PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}"], + createOrUpdateOrgSecret: ["PUT /orgs/{org}/dependabot/secrets/{secret_name}"], + createOrUpdateRepoSecret: ["PUT /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"], + deleteOrgSecret: ["DELETE /orgs/{org}/dependabot/secrets/{secret_name}"], + deleteRepoSecret: ["DELETE /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"], + getOrgPublicKey: ["GET /orgs/{org}/dependabot/secrets/public-key"], + getOrgSecret: ["GET /orgs/{org}/dependabot/secrets/{secret_name}"], + getRepoPublicKey: ["GET /repos/{owner}/{repo}/dependabot/secrets/public-key"], + getRepoSecret: ["GET /repos/{owner}/{repo}/dependabot/secrets/{secret_name}"], + listOrgSecrets: ["GET /orgs/{org}/dependabot/secrets"], + listRepoSecrets: ["GET /repos/{owner}/{repo}/dependabot/secrets"], + listSelectedReposForOrgSecret: ["GET /orgs/{org}/dependabot/secrets/{secret_name}/repositories"], + removeSelectedRepoFromOrgSecret: ["DELETE /orgs/{org}/dependabot/secrets/{secret_name}/repositories/{repository_id}"], + setSelectedReposForOrgSecret: ["PUT /orgs/{org}/dependabot/secrets/{secret_name}/repositories"] + }, + dependencyGraph: { + createRepositorySnapshot: ["POST /repos/{owner}/{repo}/dependency-graph/snapshots"], + diffRange: ["GET /repos/{owner}/{repo}/dependency-graph/compare/{basehead}"] + }, + emojis: { + get: ["GET /emojis"] + }, + enterpriseAdmin: { + addCustomLabelsToSelfHostedRunnerForEnterprise: ["POST /enterprises/{enterprise}/actions/runners/{runner_id}/labels"], + disableSelectedOrganizationGithubActionsEnterprise: ["DELETE /enterprises/{enterprise}/actions/permissions/organizations/{org_id}"], + enableSelectedOrganizationGithubActionsEnterprise: ["PUT /enterprises/{enterprise}/actions/permissions/organizations/{org_id}"], + getAllowedActionsEnterprise: ["GET /enterprises/{enterprise}/actions/permissions/selected-actions"], + getGithubActionsPermissionsEnterprise: ["GET /enterprises/{enterprise}/actions/permissions"], + getServerStatistics: ["GET /enterprise-installation/{enterprise_or_org}/server-statistics"], + listLabelsForSelfHostedRunnerForEnterprise: ["GET /enterprises/{enterprise}/actions/runners/{runner_id}/labels"], + listSelectedOrganizationsEnabledGithubActionsEnterprise: ["GET /enterprises/{enterprise}/actions/permissions/organizations"], + removeAllCustomLabelsFromSelfHostedRunnerForEnterprise: ["DELETE /enterprises/{enterprise}/actions/runners/{runner_id}/labels"], + removeCustomLabelFromSelfHostedRunnerForEnterprise: ["DELETE /enterprises/{enterprise}/actions/runners/{runner_id}/labels/{name}"], + setAllowedActionsEnterprise: ["PUT /enterprises/{enterprise}/actions/permissions/selected-actions"], + setCustomLabelsForSelfHostedRunnerForEnterprise: ["PUT /enterprises/{enterprise}/actions/runners/{runner_id}/labels"], + setGithubActionsPermissionsEnterprise: ["PUT /enterprises/{enterprise}/actions/permissions"], + setSelectedOrganizationsEnabledGithubActionsEnterprise: ["PUT /enterprises/{enterprise}/actions/permissions/organizations"] + }, + gists: { + checkIsStarred: ["GET /gists/{gist_id}/star"], + create: ["POST /gists"], + createComment: ["POST /gists/{gist_id}/comments"], + delete: ["DELETE /gists/{gist_id}"], + deleteComment: ["DELETE /gists/{gist_id}/comments/{comment_id}"], + fork: ["POST /gists/{gist_id}/forks"], + get: ["GET /gists/{gist_id}"], + getComment: ["GET /gists/{gist_id}/comments/{comment_id}"], + getRevision: ["GET /gists/{gist_id}/{sha}"], + list: ["GET /gists"], + listComments: ["GET /gists/{gist_id}/comments"], + listCommits: ["GET /gists/{gist_id}/commits"], + listForUser: ["GET /users/{username}/gists"], + listForks: ["GET /gists/{gist_id}/forks"], + listPublic: ["GET /gists/public"], + listStarred: ["GET /gists/starred"], + star: ["PUT /gists/{gist_id}/star"], + unstar: ["DELETE /gists/{gist_id}/star"], + update: ["PATCH /gists/{gist_id}"], + updateComment: ["PATCH /gists/{gist_id}/comments/{comment_id}"] + }, + git: { + createBlob: ["POST /repos/{owner}/{repo}/git/blobs"], + createCommit: ["POST /repos/{owner}/{repo}/git/commits"], + createRef: ["POST /repos/{owner}/{repo}/git/refs"], + createTag: ["POST /repos/{owner}/{repo}/git/tags"], + createTree: ["POST /repos/{owner}/{repo}/git/trees"], + deleteRef: ["DELETE /repos/{owner}/{repo}/git/refs/{ref}"], + getBlob: ["GET /repos/{owner}/{repo}/git/blobs/{file_sha}"], + getCommit: ["GET /repos/{owner}/{repo}/git/commits/{commit_sha}"], + getRef: ["GET /repos/{owner}/{repo}/git/ref/{ref}"], + getTag: ["GET /repos/{owner}/{repo}/git/tags/{tag_sha}"], + getTree: ["GET /repos/{owner}/{repo}/git/trees/{tree_sha}"], + listMatchingRefs: ["GET /repos/{owner}/{repo}/git/matching-refs/{ref}"], + updateRef: ["PATCH /repos/{owner}/{repo}/git/refs/{ref}"] + }, + gitignore: { + getAllTemplates: ["GET /gitignore/templates"], + getTemplate: ["GET /gitignore/templates/{name}"] + }, + interactions: { + getRestrictionsForAuthenticatedUser: ["GET /user/interaction-limits"], + getRestrictionsForOrg: ["GET /orgs/{org}/interaction-limits"], + getRestrictionsForRepo: ["GET /repos/{owner}/{repo}/interaction-limits"], + getRestrictionsForYourPublicRepos: ["GET /user/interaction-limits", {}, { + renamed: ["interactions", "getRestrictionsForAuthenticatedUser"] + }], + removeRestrictionsForAuthenticatedUser: ["DELETE /user/interaction-limits"], + removeRestrictionsForOrg: ["DELETE /orgs/{org}/interaction-limits"], + removeRestrictionsForRepo: ["DELETE /repos/{owner}/{repo}/interaction-limits"], + removeRestrictionsForYourPublicRepos: ["DELETE /user/interaction-limits", {}, { + renamed: ["interactions", "removeRestrictionsForAuthenticatedUser"] + }], + setRestrictionsForAuthenticatedUser: ["PUT /user/interaction-limits"], + setRestrictionsForOrg: ["PUT /orgs/{org}/interaction-limits"], + setRestrictionsForRepo: ["PUT /repos/{owner}/{repo}/interaction-limits"], + setRestrictionsForYourPublicRepos: ["PUT /user/interaction-limits", {}, { + renamed: ["interactions", "setRestrictionsForAuthenticatedUser"] + }] + }, + issues: { + addAssignees: ["POST /repos/{owner}/{repo}/issues/{issue_number}/assignees"], + addLabels: ["POST /repos/{owner}/{repo}/issues/{issue_number}/labels"], + checkUserCanBeAssigned: ["GET /repos/{owner}/{repo}/assignees/{assignee}"], + create: ["POST /repos/{owner}/{repo}/issues"], + createComment: ["POST /repos/{owner}/{repo}/issues/{issue_number}/comments"], + createLabel: ["POST /repos/{owner}/{repo}/labels"], + createMilestone: ["POST /repos/{owner}/{repo}/milestones"], + deleteComment: ["DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}"], + deleteLabel: ["DELETE /repos/{owner}/{repo}/labels/{name}"], + deleteMilestone: ["DELETE /repos/{owner}/{repo}/milestones/{milestone_number}"], + get: ["GET /repos/{owner}/{repo}/issues/{issue_number}"], + getComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}"], + getEvent: ["GET /repos/{owner}/{repo}/issues/events/{event_id}"], + getLabel: ["GET /repos/{owner}/{repo}/labels/{name}"], + getMilestone: ["GET /repos/{owner}/{repo}/milestones/{milestone_number}"], + list: ["GET /issues"], + listAssignees: ["GET /repos/{owner}/{repo}/assignees"], + listComments: ["GET /repos/{owner}/{repo}/issues/{issue_number}/comments"], + listCommentsForRepo: ["GET /repos/{owner}/{repo}/issues/comments"], + listEvents: ["GET /repos/{owner}/{repo}/issues/{issue_number}/events"], + listEventsForRepo: ["GET /repos/{owner}/{repo}/issues/events"], + listEventsForTimeline: ["GET /repos/{owner}/{repo}/issues/{issue_number}/timeline"], + listForAuthenticatedUser: ["GET /user/issues"], + listForOrg: ["GET /orgs/{org}/issues"], + listForRepo: ["GET /repos/{owner}/{repo}/issues"], + listLabelsForMilestone: ["GET /repos/{owner}/{repo}/milestones/{milestone_number}/labels"], + listLabelsForRepo: ["GET /repos/{owner}/{repo}/labels"], + listLabelsOnIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/labels"], + listMilestones: ["GET /repos/{owner}/{repo}/milestones"], + lock: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/lock"], + removeAllLabels: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels"], + removeAssignees: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/assignees"], + removeLabel: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/{name}"], + setLabels: ["PUT /repos/{owner}/{repo}/issues/{issue_number}/labels"], + unlock: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock"], + update: ["PATCH /repos/{owner}/{repo}/issues/{issue_number}"], + updateComment: ["PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}"], + updateLabel: ["PATCH /repos/{owner}/{repo}/labels/{name}"], + updateMilestone: ["PATCH /repos/{owner}/{repo}/milestones/{milestone_number}"] + }, + licenses: { + get: ["GET /licenses/{license}"], + getAllCommonlyUsed: ["GET /licenses"], + getForRepo: ["GET /repos/{owner}/{repo}/license"] + }, + markdown: { + render: ["POST /markdown"], + renderRaw: ["POST /markdown/raw", { + headers: { + "content-type": "text/plain; charset=utf-8" + } + }] + }, + meta: { + get: ["GET /meta"], + getOctocat: ["GET /octocat"], + getZen: ["GET /zen"], + root: ["GET /"] + }, + migrations: { + cancelImport: ["DELETE /repos/{owner}/{repo}/import"], + deleteArchiveForAuthenticatedUser: ["DELETE /user/migrations/{migration_id}/archive"], + deleteArchiveForOrg: ["DELETE /orgs/{org}/migrations/{migration_id}/archive"], + downloadArchiveForOrg: ["GET /orgs/{org}/migrations/{migration_id}/archive"], + getArchiveForAuthenticatedUser: ["GET /user/migrations/{migration_id}/archive"], + getCommitAuthors: ["GET /repos/{owner}/{repo}/import/authors"], + getImportStatus: ["GET /repos/{owner}/{repo}/import"], + getLargeFiles: ["GET /repos/{owner}/{repo}/import/large_files"], + getStatusForAuthenticatedUser: ["GET /user/migrations/{migration_id}"], + getStatusForOrg: ["GET /orgs/{org}/migrations/{migration_id}"], + listForAuthenticatedUser: ["GET /user/migrations"], + listForOrg: ["GET /orgs/{org}/migrations"], + listReposForAuthenticatedUser: ["GET /user/migrations/{migration_id}/repositories"], + listReposForOrg: ["GET /orgs/{org}/migrations/{migration_id}/repositories"], + listReposForUser: ["GET /user/migrations/{migration_id}/repositories", {}, { + renamed: ["migrations", "listReposForAuthenticatedUser"] + }], + mapCommitAuthor: ["PATCH /repos/{owner}/{repo}/import/authors/{author_id}"], + setLfsPreference: ["PATCH /repos/{owner}/{repo}/import/lfs"], + startForAuthenticatedUser: ["POST /user/migrations"], + startForOrg: ["POST /orgs/{org}/migrations"], + startImport: ["PUT /repos/{owner}/{repo}/import"], + unlockRepoForAuthenticatedUser: ["DELETE /user/migrations/{migration_id}/repos/{repo_name}/lock"], + unlockRepoForOrg: ["DELETE /orgs/{org}/migrations/{migration_id}/repos/{repo_name}/lock"], + updateImport: ["PATCH /repos/{owner}/{repo}/import"] + }, + orgs: { + blockUser: ["PUT /orgs/{org}/blocks/{username}"], + cancelInvitation: ["DELETE /orgs/{org}/invitations/{invitation_id}"], + checkBlockedUser: ["GET /orgs/{org}/blocks/{username}"], + checkMembershipForUser: ["GET /orgs/{org}/members/{username}"], + checkPublicMembershipForUser: ["GET /orgs/{org}/public_members/{username}"], + convertMemberToOutsideCollaborator: ["PUT /orgs/{org}/outside_collaborators/{username}"], + createInvitation: ["POST /orgs/{org}/invitations"], + createWebhook: ["POST /orgs/{org}/hooks"], + deleteWebhook: ["DELETE /orgs/{org}/hooks/{hook_id}"], + get: ["GET /orgs/{org}"], + getMembershipForAuthenticatedUser: ["GET /user/memberships/orgs/{org}"], + getMembershipForUser: ["GET /orgs/{org}/memberships/{username}"], + getWebhook: ["GET /orgs/{org}/hooks/{hook_id}"], + getWebhookConfigForOrg: ["GET /orgs/{org}/hooks/{hook_id}/config"], + getWebhookDelivery: ["GET /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}"], + list: ["GET /organizations"], + listAppInstallations: ["GET /orgs/{org}/installations"], + listBlockedUsers: ["GET /orgs/{org}/blocks"], + listCustomRoles: ["GET /organizations/{organization_id}/custom_roles"], + listFailedInvitations: ["GET /orgs/{org}/failed_invitations"], + listForAuthenticatedUser: ["GET /user/orgs"], + listForUser: ["GET /users/{username}/orgs"], + listInvitationTeams: ["GET /orgs/{org}/invitations/{invitation_id}/teams"], + listMembers: ["GET /orgs/{org}/members"], + listMembershipsForAuthenticatedUser: ["GET /user/memberships/orgs"], + listOutsideCollaborators: ["GET /orgs/{org}/outside_collaborators"], + listPendingInvitations: ["GET /orgs/{org}/invitations"], + listPublicMembers: ["GET /orgs/{org}/public_members"], + listWebhookDeliveries: ["GET /orgs/{org}/hooks/{hook_id}/deliveries"], + listWebhooks: ["GET /orgs/{org}/hooks"], + pingWebhook: ["POST /orgs/{org}/hooks/{hook_id}/pings"], + redeliverWebhookDelivery: ["POST /orgs/{org}/hooks/{hook_id}/deliveries/{delivery_id}/attempts"], + removeMember: ["DELETE /orgs/{org}/members/{username}"], + removeMembershipForUser: ["DELETE /orgs/{org}/memberships/{username}"], + removeOutsideCollaborator: ["DELETE /orgs/{org}/outside_collaborators/{username}"], + removePublicMembershipForAuthenticatedUser: ["DELETE /orgs/{org}/public_members/{username}"], + setMembershipForUser: ["PUT /orgs/{org}/memberships/{username}"], + setPublicMembershipForAuthenticatedUser: ["PUT /orgs/{org}/public_members/{username}"], + unblockUser: ["DELETE /orgs/{org}/blocks/{username}"], + update: ["PATCH /orgs/{org}"], + updateMembershipForAuthenticatedUser: ["PATCH /user/memberships/orgs/{org}"], + updateWebhook: ["PATCH /orgs/{org}/hooks/{hook_id}"], + updateWebhookConfigForOrg: ["PATCH /orgs/{org}/hooks/{hook_id}/config"] + }, + packages: { + deletePackageForAuthenticatedUser: ["DELETE /user/packages/{package_type}/{package_name}"], + deletePackageForOrg: ["DELETE /orgs/{org}/packages/{package_type}/{package_name}"], + deletePackageForUser: ["DELETE /users/{username}/packages/{package_type}/{package_name}"], + deletePackageVersionForAuthenticatedUser: ["DELETE /user/packages/{package_type}/{package_name}/versions/{package_version_id}"], + deletePackageVersionForOrg: ["DELETE /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}"], + deletePackageVersionForUser: ["DELETE /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}"], + getAllPackageVersionsForAPackageOwnedByAnOrg: ["GET /orgs/{org}/packages/{package_type}/{package_name}/versions", {}, { + renamed: ["packages", "getAllPackageVersionsForPackageOwnedByOrg"] + }], + getAllPackageVersionsForAPackageOwnedByTheAuthenticatedUser: ["GET /user/packages/{package_type}/{package_name}/versions", {}, { + renamed: ["packages", "getAllPackageVersionsForPackageOwnedByAuthenticatedUser"] + }], + getAllPackageVersionsForPackageOwnedByAuthenticatedUser: ["GET /user/packages/{package_type}/{package_name}/versions"], + getAllPackageVersionsForPackageOwnedByOrg: ["GET /orgs/{org}/packages/{package_type}/{package_name}/versions"], + getAllPackageVersionsForPackageOwnedByUser: ["GET /users/{username}/packages/{package_type}/{package_name}/versions"], + getPackageForAuthenticatedUser: ["GET /user/packages/{package_type}/{package_name}"], + getPackageForOrganization: ["GET /orgs/{org}/packages/{package_type}/{package_name}"], + getPackageForUser: ["GET /users/{username}/packages/{package_type}/{package_name}"], + getPackageVersionForAuthenticatedUser: ["GET /user/packages/{package_type}/{package_name}/versions/{package_version_id}"], + getPackageVersionForOrganization: ["GET /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}"], + getPackageVersionForUser: ["GET /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}"], + listPackagesForAuthenticatedUser: ["GET /user/packages"], + listPackagesForOrganization: ["GET /orgs/{org}/packages"], + listPackagesForUser: ["GET /users/{username}/packages"], + restorePackageForAuthenticatedUser: ["POST /user/packages/{package_type}/{package_name}/restore{?token}"], + restorePackageForOrg: ["POST /orgs/{org}/packages/{package_type}/{package_name}/restore{?token}"], + restorePackageForUser: ["POST /users/{username}/packages/{package_type}/{package_name}/restore{?token}"], + restorePackageVersionForAuthenticatedUser: ["POST /user/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"], + restorePackageVersionForOrg: ["POST /orgs/{org}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"], + restorePackageVersionForUser: ["POST /users/{username}/packages/{package_type}/{package_name}/versions/{package_version_id}/restore"] + }, + projects: { + addCollaborator: ["PUT /projects/{project_id}/collaborators/{username}"], + createCard: ["POST /projects/columns/{column_id}/cards"], + createColumn: ["POST /projects/{project_id}/columns"], + createForAuthenticatedUser: ["POST /user/projects"], + createForOrg: ["POST /orgs/{org}/projects"], + createForRepo: ["POST /repos/{owner}/{repo}/projects"], + delete: ["DELETE /projects/{project_id}"], + deleteCard: ["DELETE /projects/columns/cards/{card_id}"], + deleteColumn: ["DELETE /projects/columns/{column_id}"], + get: ["GET /projects/{project_id}"], + getCard: ["GET /projects/columns/cards/{card_id}"], + getColumn: ["GET /projects/columns/{column_id}"], + getPermissionForUser: ["GET /projects/{project_id}/collaborators/{username}/permission"], + listCards: ["GET /projects/columns/{column_id}/cards"], + listCollaborators: ["GET /projects/{project_id}/collaborators"], + listColumns: ["GET /projects/{project_id}/columns"], + listForOrg: ["GET /orgs/{org}/projects"], + listForRepo: ["GET /repos/{owner}/{repo}/projects"], + listForUser: ["GET /users/{username}/projects"], + moveCard: ["POST /projects/columns/cards/{card_id}/moves"], + moveColumn: ["POST /projects/columns/{column_id}/moves"], + removeCollaborator: ["DELETE /projects/{project_id}/collaborators/{username}"], + update: ["PATCH /projects/{project_id}"], + updateCard: ["PATCH /projects/columns/cards/{card_id}"], + updateColumn: ["PATCH /projects/columns/{column_id}"] + }, + pulls: { + checkIfMerged: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/merge"], + create: ["POST /repos/{owner}/{repo}/pulls"], + createReplyForReviewComment: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies"], + createReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], + createReviewComment: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/comments"], + deletePendingReview: ["DELETE /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], + deleteReviewComment: ["DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}"], + dismissReview: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/dismissals"], + get: ["GET /repos/{owner}/{repo}/pulls/{pull_number}"], + getReview: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], + getReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}"], + list: ["GET /repos/{owner}/{repo}/pulls"], + listCommentsForReview: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/comments"], + listCommits: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/commits"], + listFiles: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/files"], + listRequestedReviewers: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], + listReviewComments: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/comments"], + listReviewCommentsForRepo: ["GET /repos/{owner}/{repo}/pulls/comments"], + listReviews: ["GET /repos/{owner}/{repo}/pulls/{pull_number}/reviews"], + merge: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge"], + removeRequestedReviewers: ["DELETE /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], + requestReviewers: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers"], + submitReview: ["POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}/events"], + update: ["PATCH /repos/{owner}/{repo}/pulls/{pull_number}"], + updateBranch: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/update-branch"], + updateReview: ["PUT /repos/{owner}/{repo}/pulls/{pull_number}/reviews/{review_id}"], + updateReviewComment: ["PATCH /repos/{owner}/{repo}/pulls/comments/{comment_id}"] + }, + rateLimit: { + get: ["GET /rate_limit"] + }, + reactions: { + createForCommitComment: ["POST /repos/{owner}/{repo}/comments/{comment_id}/reactions"], + createForIssue: ["POST /repos/{owner}/{repo}/issues/{issue_number}/reactions"], + createForIssueComment: ["POST /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"], + createForPullRequestReviewComment: ["POST /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions"], + createForRelease: ["POST /repos/{owner}/{repo}/releases/{release_id}/reactions"], + createForTeamDiscussionCommentInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions"], + createForTeamDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions"], + deleteForCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}/reactions/{reaction_id}"], + deleteForIssue: ["DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id}"], + deleteForIssueComment: ["DELETE /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions/{reaction_id}"], + deleteForPullRequestComment: ["DELETE /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions/{reaction_id}"], + deleteForRelease: ["DELETE /repos/{owner}/{repo}/releases/{release_id}/reactions/{reaction_id}"], + deleteForTeamDiscussion: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions/{reaction_id}"], + deleteForTeamDiscussionComment: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions/{reaction_id}"], + listForCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}/reactions"], + listForIssue: ["GET /repos/{owner}/{repo}/issues/{issue_number}/reactions"], + listForIssueComment: ["GET /repos/{owner}/{repo}/issues/comments/{comment_id}/reactions"], + listForPullRequestReviewComment: ["GET /repos/{owner}/{repo}/pulls/comments/{comment_id}/reactions"], + listForRelease: ["GET /repos/{owner}/{repo}/releases/{release_id}/reactions"], + listForTeamDiscussionCommentInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}/reactions"], + listForTeamDiscussionInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/reactions"] + }, + repos: { + acceptInvitation: ["PATCH /user/repository_invitations/{invitation_id}", {}, { + renamed: ["repos", "acceptInvitationForAuthenticatedUser"] + }], + acceptInvitationForAuthenticatedUser: ["PATCH /user/repository_invitations/{invitation_id}"], + addAppAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { + mapToData: "apps" + }], + addCollaborator: ["PUT /repos/{owner}/{repo}/collaborators/{username}"], + addStatusCheckContexts: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { + mapToData: "contexts" + }], + addTeamAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { + mapToData: "teams" + }], + addUserAccessRestrictions: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { + mapToData: "users" + }], + checkCollaborator: ["GET /repos/{owner}/{repo}/collaborators/{username}"], + checkVulnerabilityAlerts: ["GET /repos/{owner}/{repo}/vulnerability-alerts"], + codeownersErrors: ["GET /repos/{owner}/{repo}/codeowners/errors"], + compareCommits: ["GET /repos/{owner}/{repo}/compare/{base}...{head}"], + compareCommitsWithBasehead: ["GET /repos/{owner}/{repo}/compare/{basehead}"], + createAutolink: ["POST /repos/{owner}/{repo}/autolinks"], + createCommitComment: ["POST /repos/{owner}/{repo}/commits/{commit_sha}/comments"], + createCommitSignatureProtection: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"], + createCommitStatus: ["POST /repos/{owner}/{repo}/statuses/{sha}"], + createDeployKey: ["POST /repos/{owner}/{repo}/keys"], + createDeployment: ["POST /repos/{owner}/{repo}/deployments"], + createDeploymentStatus: ["POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses"], + createDispatchEvent: ["POST /repos/{owner}/{repo}/dispatches"], + createForAuthenticatedUser: ["POST /user/repos"], + createFork: ["POST /repos/{owner}/{repo}/forks"], + createInOrg: ["POST /orgs/{org}/repos"], + createOrUpdateEnvironment: ["PUT /repos/{owner}/{repo}/environments/{environment_name}"], + createOrUpdateFileContents: ["PUT /repos/{owner}/{repo}/contents/{path}"], + createPagesSite: ["POST /repos/{owner}/{repo}/pages"], + createRelease: ["POST /repos/{owner}/{repo}/releases"], + createTagProtection: ["POST /repos/{owner}/{repo}/tags/protection"], + createUsingTemplate: ["POST /repos/{template_owner}/{template_repo}/generate"], + createWebhook: ["POST /repos/{owner}/{repo}/hooks"], + declineInvitation: ["DELETE /user/repository_invitations/{invitation_id}", {}, { + renamed: ["repos", "declineInvitationForAuthenticatedUser"] + }], + declineInvitationForAuthenticatedUser: ["DELETE /user/repository_invitations/{invitation_id}"], + delete: ["DELETE /repos/{owner}/{repo}"], + deleteAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions"], + deleteAdminBranchProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], + deleteAnEnvironment: ["DELETE /repos/{owner}/{repo}/environments/{environment_name}"], + deleteAutolink: ["DELETE /repos/{owner}/{repo}/autolinks/{autolink_id}"], + deleteBranchProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection"], + deleteCommitComment: ["DELETE /repos/{owner}/{repo}/comments/{comment_id}"], + deleteCommitSignatureProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"], + deleteDeployKey: ["DELETE /repos/{owner}/{repo}/keys/{key_id}"], + deleteDeployment: ["DELETE /repos/{owner}/{repo}/deployments/{deployment_id}"], + deleteFile: ["DELETE /repos/{owner}/{repo}/contents/{path}"], + deleteInvitation: ["DELETE /repos/{owner}/{repo}/invitations/{invitation_id}"], + deletePagesSite: ["DELETE /repos/{owner}/{repo}/pages"], + deletePullRequestReviewProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + deleteRelease: ["DELETE /repos/{owner}/{repo}/releases/{release_id}"], + deleteReleaseAsset: ["DELETE /repos/{owner}/{repo}/releases/assets/{asset_id}"], + deleteTagProtection: ["DELETE /repos/{owner}/{repo}/tags/protection/{tag_protection_id}"], + deleteWebhook: ["DELETE /repos/{owner}/{repo}/hooks/{hook_id}"], + disableAutomatedSecurityFixes: ["DELETE /repos/{owner}/{repo}/automated-security-fixes"], + disableLfsForRepo: ["DELETE /repos/{owner}/{repo}/lfs"], + disableVulnerabilityAlerts: ["DELETE /repos/{owner}/{repo}/vulnerability-alerts"], + downloadArchive: ["GET /repos/{owner}/{repo}/zipball/{ref}", {}, { + renamed: ["repos", "downloadZipballArchive"] + }], + downloadTarballArchive: ["GET /repos/{owner}/{repo}/tarball/{ref}"], + downloadZipballArchive: ["GET /repos/{owner}/{repo}/zipball/{ref}"], + enableAutomatedSecurityFixes: ["PUT /repos/{owner}/{repo}/automated-security-fixes"], + enableLfsForRepo: ["PUT /repos/{owner}/{repo}/lfs"], + enableVulnerabilityAlerts: ["PUT /repos/{owner}/{repo}/vulnerability-alerts"], + generateReleaseNotes: ["POST /repos/{owner}/{repo}/releases/generate-notes"], + get: ["GET /repos/{owner}/{repo}"], + getAccessRestrictions: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions"], + getAdminBranchProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], + getAllEnvironments: ["GET /repos/{owner}/{repo}/environments"], + getAllStatusCheckContexts: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts"], + getAllTopics: ["GET /repos/{owner}/{repo}/topics"], + getAppsWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps"], + getAutolink: ["GET /repos/{owner}/{repo}/autolinks/{autolink_id}"], + getBranch: ["GET /repos/{owner}/{repo}/branches/{branch}"], + getBranchProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection"], + getClones: ["GET /repos/{owner}/{repo}/traffic/clones"], + getCodeFrequencyStats: ["GET /repos/{owner}/{repo}/stats/code_frequency"], + getCollaboratorPermissionLevel: ["GET /repos/{owner}/{repo}/collaborators/{username}/permission"], + getCombinedStatusForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/status"], + getCommit: ["GET /repos/{owner}/{repo}/commits/{ref}"], + getCommitActivityStats: ["GET /repos/{owner}/{repo}/stats/commit_activity"], + getCommitComment: ["GET /repos/{owner}/{repo}/comments/{comment_id}"], + getCommitSignatureProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_signatures"], + getCommunityProfileMetrics: ["GET /repos/{owner}/{repo}/community/profile"], + getContent: ["GET /repos/{owner}/{repo}/contents/{path}"], + getContributorsStats: ["GET /repos/{owner}/{repo}/stats/contributors"], + getDeployKey: ["GET /repos/{owner}/{repo}/keys/{key_id}"], + getDeployment: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}"], + getDeploymentStatus: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses/{status_id}"], + getEnvironment: ["GET /repos/{owner}/{repo}/environments/{environment_name}"], + getLatestPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/latest"], + getLatestRelease: ["GET /repos/{owner}/{repo}/releases/latest"], + getPages: ["GET /repos/{owner}/{repo}/pages"], + getPagesBuild: ["GET /repos/{owner}/{repo}/pages/builds/{build_id}"], + getPagesHealthCheck: ["GET /repos/{owner}/{repo}/pages/health"], + getParticipationStats: ["GET /repos/{owner}/{repo}/stats/participation"], + getPullRequestReviewProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + getPunchCardStats: ["GET /repos/{owner}/{repo}/stats/punch_card"], + getReadme: ["GET /repos/{owner}/{repo}/readme"], + getReadmeInDirectory: ["GET /repos/{owner}/{repo}/readme/{dir}"], + getRelease: ["GET /repos/{owner}/{repo}/releases/{release_id}"], + getReleaseAsset: ["GET /repos/{owner}/{repo}/releases/assets/{asset_id}"], + getReleaseByTag: ["GET /repos/{owner}/{repo}/releases/tags/{tag}"], + getStatusChecksProtection: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], + getTeamsWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams"], + getTopPaths: ["GET /repos/{owner}/{repo}/traffic/popular/paths"], + getTopReferrers: ["GET /repos/{owner}/{repo}/traffic/popular/referrers"], + getUsersWithAccessToProtectedBranch: ["GET /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users"], + getViews: ["GET /repos/{owner}/{repo}/traffic/views"], + getWebhook: ["GET /repos/{owner}/{repo}/hooks/{hook_id}"], + getWebhookConfigForRepo: ["GET /repos/{owner}/{repo}/hooks/{hook_id}/config"], + getWebhookDelivery: ["GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}"], + listAutolinks: ["GET /repos/{owner}/{repo}/autolinks"], + listBranches: ["GET /repos/{owner}/{repo}/branches"], + listBranchesForHeadCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/branches-where-head"], + listCollaborators: ["GET /repos/{owner}/{repo}/collaborators"], + listCommentsForCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/comments"], + listCommitCommentsForRepo: ["GET /repos/{owner}/{repo}/comments"], + listCommitStatusesForRef: ["GET /repos/{owner}/{repo}/commits/{ref}/statuses"], + listCommits: ["GET /repos/{owner}/{repo}/commits"], + listContributors: ["GET /repos/{owner}/{repo}/contributors"], + listDeployKeys: ["GET /repos/{owner}/{repo}/keys"], + listDeploymentStatuses: ["GET /repos/{owner}/{repo}/deployments/{deployment_id}/statuses"], + listDeployments: ["GET /repos/{owner}/{repo}/deployments"], + listForAuthenticatedUser: ["GET /user/repos"], + listForOrg: ["GET /orgs/{org}/repos"], + listForUser: ["GET /users/{username}/repos"], + listForks: ["GET /repos/{owner}/{repo}/forks"], + listInvitations: ["GET /repos/{owner}/{repo}/invitations"], + listInvitationsForAuthenticatedUser: ["GET /user/repository_invitations"], + listLanguages: ["GET /repos/{owner}/{repo}/languages"], + listPagesBuilds: ["GET /repos/{owner}/{repo}/pages/builds"], + listPublic: ["GET /repositories"], + listPullRequestsAssociatedWithCommit: ["GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls"], + listReleaseAssets: ["GET /repos/{owner}/{repo}/releases/{release_id}/assets"], + listReleases: ["GET /repos/{owner}/{repo}/releases"], + listTagProtection: ["GET /repos/{owner}/{repo}/tags/protection"], + listTags: ["GET /repos/{owner}/{repo}/tags"], + listTeams: ["GET /repos/{owner}/{repo}/teams"], + listWebhookDeliveries: ["GET /repos/{owner}/{repo}/hooks/{hook_id}/deliveries"], + listWebhooks: ["GET /repos/{owner}/{repo}/hooks"], + merge: ["POST /repos/{owner}/{repo}/merges"], + mergeUpstream: ["POST /repos/{owner}/{repo}/merge-upstream"], + pingWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/pings"], + redeliverWebhookDelivery: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/deliveries/{delivery_id}/attempts"], + removeAppAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { + mapToData: "apps" + }], + removeCollaborator: ["DELETE /repos/{owner}/{repo}/collaborators/{username}"], + removeStatusCheckContexts: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { + mapToData: "contexts" + }], + removeStatusCheckProtection: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], + removeTeamAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { + mapToData: "teams" + }], + removeUserAccessRestrictions: ["DELETE /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { + mapToData: "users" + }], + renameBranch: ["POST /repos/{owner}/{repo}/branches/{branch}/rename"], + replaceAllTopics: ["PUT /repos/{owner}/{repo}/topics"], + requestPagesBuild: ["POST /repos/{owner}/{repo}/pages/builds"], + setAdminBranchProtection: ["POST /repos/{owner}/{repo}/branches/{branch}/protection/enforce_admins"], + setAppAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/apps", {}, { + mapToData: "apps" + }], + setStatusCheckContexts: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks/contexts", {}, { + mapToData: "contexts" + }], + setTeamAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/teams", {}, { + mapToData: "teams" + }], + setUserAccessRestrictions: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection/restrictions/users", {}, { + mapToData: "users" + }], + testPushWebhook: ["POST /repos/{owner}/{repo}/hooks/{hook_id}/tests"], + transfer: ["POST /repos/{owner}/{repo}/transfer"], + update: ["PATCH /repos/{owner}/{repo}"], + updateBranchProtection: ["PUT /repos/{owner}/{repo}/branches/{branch}/protection"], + updateCommitComment: ["PATCH /repos/{owner}/{repo}/comments/{comment_id}"], + updateInformationAboutPagesSite: ["PUT /repos/{owner}/{repo}/pages"], + updateInvitation: ["PATCH /repos/{owner}/{repo}/invitations/{invitation_id}"], + updatePullRequestReviewProtection: ["PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_pull_request_reviews"], + updateRelease: ["PATCH /repos/{owner}/{repo}/releases/{release_id}"], + updateReleaseAsset: ["PATCH /repos/{owner}/{repo}/releases/assets/{asset_id}"], + updateStatusCheckPotection: ["PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks", {}, { + renamed: ["repos", "updateStatusCheckProtection"] + }], + updateStatusCheckProtection: ["PATCH /repos/{owner}/{repo}/branches/{branch}/protection/required_status_checks"], + updateWebhook: ["PATCH /repos/{owner}/{repo}/hooks/{hook_id}"], + updateWebhookConfigForRepo: ["PATCH /repos/{owner}/{repo}/hooks/{hook_id}/config"], + uploadReleaseAsset: ["POST /repos/{owner}/{repo}/releases/{release_id}/assets{?name,label}", { + baseUrl: "https://uploads.github.com" + }] + }, + search: { + code: ["GET /search/code"], + commits: ["GET /search/commits"], + issuesAndPullRequests: ["GET /search/issues"], + labels: ["GET /search/labels"], + repos: ["GET /search/repositories"], + topics: ["GET /search/topics"], + users: ["GET /search/users"] + }, + secretScanning: { + getAlert: ["GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}"], + listAlertsForEnterprise: ["GET /enterprises/{enterprise}/secret-scanning/alerts"], + listAlertsForOrg: ["GET /orgs/{org}/secret-scanning/alerts"], + listAlertsForRepo: ["GET /repos/{owner}/{repo}/secret-scanning/alerts"], + listLocationsForAlert: ["GET /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}/locations"], + updateAlert: ["PATCH /repos/{owner}/{repo}/secret-scanning/alerts/{alert_number}"] + }, + teams: { + addOrUpdateMembershipForUserInOrg: ["PUT /orgs/{org}/teams/{team_slug}/memberships/{username}"], + addOrUpdateProjectPermissionsInOrg: ["PUT /orgs/{org}/teams/{team_slug}/projects/{project_id}"], + addOrUpdateRepoPermissionsInOrg: ["PUT /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], + checkPermissionsForProjectInOrg: ["GET /orgs/{org}/teams/{team_slug}/projects/{project_id}"], + checkPermissionsForRepoInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], + create: ["POST /orgs/{org}/teams"], + createDiscussionCommentInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments"], + createDiscussionInOrg: ["POST /orgs/{org}/teams/{team_slug}/discussions"], + deleteDiscussionCommentInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], + deleteDiscussionInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], + deleteInOrg: ["DELETE /orgs/{org}/teams/{team_slug}"], + getByName: ["GET /orgs/{org}/teams/{team_slug}"], + getDiscussionCommentInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], + getDiscussionInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], + getMembershipForUserInOrg: ["GET /orgs/{org}/teams/{team_slug}/memberships/{username}"], + list: ["GET /orgs/{org}/teams"], + listChildInOrg: ["GET /orgs/{org}/teams/{team_slug}/teams"], + listDiscussionCommentsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments"], + listDiscussionsInOrg: ["GET /orgs/{org}/teams/{team_slug}/discussions"], + listForAuthenticatedUser: ["GET /user/teams"], + listMembersInOrg: ["GET /orgs/{org}/teams/{team_slug}/members"], + listPendingInvitationsInOrg: ["GET /orgs/{org}/teams/{team_slug}/invitations"], + listProjectsInOrg: ["GET /orgs/{org}/teams/{team_slug}/projects"], + listReposInOrg: ["GET /orgs/{org}/teams/{team_slug}/repos"], + removeMembershipForUserInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/memberships/{username}"], + removeProjectInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/projects/{project_id}"], + removeRepoInOrg: ["DELETE /orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}"], + updateDiscussionCommentInOrg: ["PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments/{comment_number}"], + updateDiscussionInOrg: ["PATCH /orgs/{org}/teams/{team_slug}/discussions/{discussion_number}"], + updateInOrg: ["PATCH /orgs/{org}/teams/{team_slug}"] + }, + users: { + addEmailForAuthenticated: ["POST /user/emails", {}, { + renamed: ["users", "addEmailForAuthenticatedUser"] + }], + addEmailForAuthenticatedUser: ["POST /user/emails"], + block: ["PUT /user/blocks/{username}"], + checkBlocked: ["GET /user/blocks/{username}"], + checkFollowingForUser: ["GET /users/{username}/following/{target_user}"], + checkPersonIsFollowedByAuthenticated: ["GET /user/following/{username}"], + createGpgKeyForAuthenticated: ["POST /user/gpg_keys", {}, { + renamed: ["users", "createGpgKeyForAuthenticatedUser"] + }], + createGpgKeyForAuthenticatedUser: ["POST /user/gpg_keys"], + createPublicSshKeyForAuthenticated: ["POST /user/keys", {}, { + renamed: ["users", "createPublicSshKeyForAuthenticatedUser"] + }], + createPublicSshKeyForAuthenticatedUser: ["POST /user/keys"], + deleteEmailForAuthenticated: ["DELETE /user/emails", {}, { + renamed: ["users", "deleteEmailForAuthenticatedUser"] + }], + deleteEmailForAuthenticatedUser: ["DELETE /user/emails"], + deleteGpgKeyForAuthenticated: ["DELETE /user/gpg_keys/{gpg_key_id}", {}, { + renamed: ["users", "deleteGpgKeyForAuthenticatedUser"] + }], + deleteGpgKeyForAuthenticatedUser: ["DELETE /user/gpg_keys/{gpg_key_id}"], + deletePublicSshKeyForAuthenticated: ["DELETE /user/keys/{key_id}", {}, { + renamed: ["users", "deletePublicSshKeyForAuthenticatedUser"] + }], + deletePublicSshKeyForAuthenticatedUser: ["DELETE /user/keys/{key_id}"], + follow: ["PUT /user/following/{username}"], + getAuthenticated: ["GET /user"], + getByUsername: ["GET /users/{username}"], + getContextForUser: ["GET /users/{username}/hovercard"], + getGpgKeyForAuthenticated: ["GET /user/gpg_keys/{gpg_key_id}", {}, { + renamed: ["users", "getGpgKeyForAuthenticatedUser"] + }], + getGpgKeyForAuthenticatedUser: ["GET /user/gpg_keys/{gpg_key_id}"], + getPublicSshKeyForAuthenticated: ["GET /user/keys/{key_id}", {}, { + renamed: ["users", "getPublicSshKeyForAuthenticatedUser"] + }], + getPublicSshKeyForAuthenticatedUser: ["GET /user/keys/{key_id}"], + list: ["GET /users"], + listBlockedByAuthenticated: ["GET /user/blocks", {}, { + renamed: ["users", "listBlockedByAuthenticatedUser"] + }], + listBlockedByAuthenticatedUser: ["GET /user/blocks"], + listEmailsForAuthenticated: ["GET /user/emails", {}, { + renamed: ["users", "listEmailsForAuthenticatedUser"] + }], + listEmailsForAuthenticatedUser: ["GET /user/emails"], + listFollowedByAuthenticated: ["GET /user/following", {}, { + renamed: ["users", "listFollowedByAuthenticatedUser"] + }], + listFollowedByAuthenticatedUser: ["GET /user/following"], + listFollowersForAuthenticatedUser: ["GET /user/followers"], + listFollowersForUser: ["GET /users/{username}/followers"], + listFollowingForUser: ["GET /users/{username}/following"], + listGpgKeysForAuthenticated: ["GET /user/gpg_keys", {}, { + renamed: ["users", "listGpgKeysForAuthenticatedUser"] + }], + listGpgKeysForAuthenticatedUser: ["GET /user/gpg_keys"], + listGpgKeysForUser: ["GET /users/{username}/gpg_keys"], + listPublicEmailsForAuthenticated: ["GET /user/public_emails", {}, { + renamed: ["users", "listPublicEmailsForAuthenticatedUser"] + }], + listPublicEmailsForAuthenticatedUser: ["GET /user/public_emails"], + listPublicKeysForUser: ["GET /users/{username}/keys"], + listPublicSshKeysForAuthenticated: ["GET /user/keys", {}, { + renamed: ["users", "listPublicSshKeysForAuthenticatedUser"] + }], + listPublicSshKeysForAuthenticatedUser: ["GET /user/keys"], + setPrimaryEmailVisibilityForAuthenticated: ["PATCH /user/email/visibility", {}, { + renamed: ["users", "setPrimaryEmailVisibilityForAuthenticatedUser"] + }], + setPrimaryEmailVisibilityForAuthenticatedUser: ["PATCH /user/email/visibility"], + unblock: ["DELETE /user/blocks/{username}"], + unfollow: ["DELETE /user/following/{username}"], + updateAuthenticated: ["PATCH /user"] + } +}; + +const VERSION = "5.16.2"; + +function endpointsToMethods(octokit, endpointsMap) { + const newMethods = {}; + + for (const [scope, endpoints] of Object.entries(endpointsMap)) { + for (const [methodName, endpoint] of Object.entries(endpoints)) { + const [route, defaults, decorations] = endpoint; + const [method, url] = route.split(/ /); + const endpointDefaults = Object.assign({ + method, + url + }, defaults); + + if (!newMethods[scope]) { + newMethods[scope] = {}; + } + + const scopeMethods = newMethods[scope]; + + if (decorations) { + scopeMethods[methodName] = decorate(octokit, scope, methodName, endpointDefaults, decorations); + continue; + } + + scopeMethods[methodName] = octokit.request.defaults(endpointDefaults); + } + } + + return newMethods; +} + +function decorate(octokit, scope, methodName, defaults, decorations) { + const requestWithDefaults = octokit.request.defaults(defaults); + /* istanbul ignore next */ + + function withDecorations(...args) { + // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 + let options = requestWithDefaults.endpoint.merge(...args); // There are currently no other decorations than `.mapToData` + + if (decorations.mapToData) { + options = Object.assign({}, options, { + data: options[decorations.mapToData], + [decorations.mapToData]: undefined + }); + return requestWithDefaults(options); + } + + if (decorations.renamed) { + const [newScope, newMethodName] = decorations.renamed; + octokit.log.warn(`octokit.${scope}.${methodName}() has been renamed to octokit.${newScope}.${newMethodName}()`); + } + + if (decorations.deprecated) { + octokit.log.warn(decorations.deprecated); + } + + if (decorations.renamedParameters) { + // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 + const options = requestWithDefaults.endpoint.merge(...args); + + for (const [name, alias] of Object.entries(decorations.renamedParameters)) { + if (name in options) { + octokit.log.warn(`"${name}" parameter is deprecated for "octokit.${scope}.${methodName}()". Use "${alias}" instead`); + + if (!(alias in options)) { + options[alias] = options[name]; + } + + delete options[name]; + } + } + + return requestWithDefaults(options); + } // @ts-ignore https://github.com/microsoft/TypeScript/issues/25488 + + + return requestWithDefaults(...args); + } + + return Object.assign(withDecorations, requestWithDefaults); +} + +function restEndpointMethods(octokit) { + const api = endpointsToMethods(octokit, Endpoints); + return { + rest: api + }; +} +restEndpointMethods.VERSION = VERSION; +function legacyRestEndpointMethods(octokit) { + const api = endpointsToMethods(octokit, Endpoints); + return _objectSpread2(_objectSpread2({}, api), {}, { + rest: api + }); +} +legacyRestEndpointMethods.VERSION = VERSION; + +exports.legacyRestEndpointMethods = legacyRestEndpointMethods; +exports.restEndpointMethods = restEndpointMethods; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 9968: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var BottleneckLight = _interopDefault(__nccwpck_require__(1174)); + +const VERSION = "4.1.0"; + +const noop = () => Promise.resolve(); // @ts-expect-error + + +function wrapRequest(state, request, options) { + return state.retryLimiter.schedule(doRequest, state, request, options); +} // @ts-expect-error + +async function doRequest(state, request, options) { + const isWrite = options.method !== "GET" && options.method !== "HEAD"; + const { + pathname + } = new URL(options.url, "http://github.test"); + const isSearch = options.method === "GET" && pathname.startsWith("/search/"); + const isGraphQL = pathname.startsWith("/graphql"); + const retryCount = ~~options.request.retryCount; + const jobOptions = retryCount > 0 ? { + priority: 0, + weight: 0 + } : {}; + + if (state.clustering) { + // Remove a job from Redis if it has not completed or failed within 60s + // Examples: Node process terminated, client disconnected, etc. + // @ts-expect-error + jobOptions.expiration = 1000 * 60; + } // Guarantee at least 1000ms between writes + // GraphQL can also trigger writes + + + if (isWrite || isGraphQL) { + await state.write.key(state.id).schedule(jobOptions, noop); + } // Guarantee at least 3000ms between requests that trigger notifications + + + if (isWrite && state.triggersNotification(pathname)) { + await state.notifications.key(state.id).schedule(jobOptions, noop); + } // Guarantee at least 2000ms between search requests + + + if (isSearch) { + await state.search.key(state.id).schedule(jobOptions, noop); + } + + const req = state.global.key(state.id).schedule(jobOptions, request, options); + + if (isGraphQL) { + const res = await req; + + if (res.data.errors != null && // @ts-expect-error + res.data.errors.some(error => error.type === "RATE_LIMITED")) { + const error = Object.assign(new Error("GraphQL Rate Limit Exceeded"), { + response: res, + data: res.data + }); + throw error; + } + } + + return req; +} + +var triggersNotificationPaths = ["/orgs/{org}/invitations", "/orgs/{org}/invitations/{invitation_id}", "/orgs/{org}/teams/{team_slug}/discussions", "/orgs/{org}/teams/{team_slug}/discussions/{discussion_number}/comments", "/repos/{owner}/{repo}/collaborators/{username}", "/repos/{owner}/{repo}/commits/{commit_sha}/comments", "/repos/{owner}/{repo}/issues", "/repos/{owner}/{repo}/issues/{issue_number}/comments", "/repos/{owner}/{repo}/pulls", "/repos/{owner}/{repo}/pulls/{pull_number}/comments", "/repos/{owner}/{repo}/pulls/{pull_number}/comments/{comment_id}/replies", "/repos/{owner}/{repo}/pulls/{pull_number}/merge", "/repos/{owner}/{repo}/pulls/{pull_number}/requested_reviewers", "/repos/{owner}/{repo}/pulls/{pull_number}/reviews", "/repos/{owner}/{repo}/releases", "/teams/{team_id}/discussions", "/teams/{team_id}/discussions/{discussion_number}/comments"]; + +function routeMatcher(paths) { + // EXAMPLE. For the following paths: + + /* [ + "/orgs/{org}/invitations", + "/repos/{owner}/{repo}/collaborators/{username}" + ] */ + const regexes = paths.map(path => path.split("/").map(c => c.startsWith("{") ? "(?:.+?)" : c).join("/")); // 'regexes' would contain: + + /* [ + '/orgs/(?:.+?)/invitations', + '/repos/(?:.+?)/(?:.+?)/collaborators/(?:.+?)' + ] */ + + const regex = `^(?:${regexes.map(r => `(?:${r})`).join("|")})[^/]*$`; // 'regex' would contain: + + /* + ^(?:(?:\/orgs\/(?:.+?)\/invitations)|(?:\/repos\/(?:.+?)\/(?:.+?)\/collaborators\/(?:.+?)))[^\/]*$ + It may look scary, but paste it into https://www.debuggex.com/ + and it will make a lot more sense! + */ + + return new RegExp(regex, "i"); +} + +// @ts-expect-error + +const regex = routeMatcher(triggersNotificationPaths); +const triggersNotification = regex.test.bind(regex); +const groups = {}; // @ts-expect-error + +const createGroups = function (Bottleneck, common) { + groups.global = new Bottleneck.Group({ + id: "octokit-global", + maxConcurrent: 10, + ...common + }); + groups.search = new Bottleneck.Group({ + id: "octokit-search", + maxConcurrent: 1, + minTime: 2000, + ...common + }); + groups.write = new Bottleneck.Group({ + id: "octokit-write", + maxConcurrent: 1, + minTime: 1000, + ...common + }); + groups.notifications = new Bottleneck.Group({ + id: "octokit-notifications", + maxConcurrent: 1, + minTime: 3000, + ...common + }); +}; + +function throttling(octokit, octokitOptions) { + const { + enabled = true, + Bottleneck = BottleneckLight, + id = "no-id", + timeout = 1000 * 60 * 2, + // Redis TTL: 2 minutes + connection + } = octokitOptions.throttle || {}; + + if (!enabled) { + return {}; + } + + const common = { + connection, + timeout + }; + + if (groups.global == null) { + createGroups(Bottleneck, common); + } + + const state = Object.assign({ + clustering: connection != null, + triggersNotification, + minimumSecondaryRateRetryAfter: 5, + retryAfterBaseValue: 1000, + retryLimiter: new Bottleneck(), + id, + ...groups + }, octokitOptions.throttle); + const isUsingDeprecatedOnAbuseLimitHandler = typeof state.onAbuseLimit === "function" && state.onAbuseLimit; + + if (typeof (isUsingDeprecatedOnAbuseLimitHandler ? state.onAbuseLimit : state.onSecondaryRateLimit) !== "function" || typeof state.onRateLimit !== "function") { + throw new Error(`octokit/plugin-throttling error: + You must pass the onSecondaryRateLimit and onRateLimit error handlers. + See https://github.com/octokit/rest.js#throttling + + const octokit = new Octokit({ + throttle: { + onSecondaryRateLimit: (retryAfter, options) => {/* ... */}, + onRateLimit: (retryAfter, options) => {/* ... */} + } + }) + `); + } + + const events = {}; + const emitter = new Bottleneck.Events(events); // @ts-expect-error + + events.on("secondary-limit", isUsingDeprecatedOnAbuseLimitHandler ? function (...args) { + octokit.log.warn("[@octokit/plugin-throttling] `onAbuseLimit()` is deprecated and will be removed in a future release of `@octokit/plugin-throttling`, please use the `onSecondaryRateLimit` handler instead"); + return state.onAbuseLimit(...args); + } : state.onSecondaryRateLimit); // @ts-expect-error + + events.on("rate-limit", state.onRateLimit); // @ts-expect-error + + events.on("error", e => octokit.log.warn("Error in throttling-plugin limit handler", e)); // @ts-expect-error + + state.retryLimiter.on("failed", async function (error, info) { + const options = info.args[info.args.length - 1]; + const { + pathname + } = new URL(options.url, "http://github.test"); + const shouldRetryGraphQL = pathname.startsWith("/graphql") && error.status !== 401; + + if (!(shouldRetryGraphQL || error.status === 403)) { + return; + } + + const retryCount = ~~options.request.retryCount; + options.request.retryCount = retryCount; + const { + wantRetry, + retryAfter = 0 + } = await async function () { + if (/\bsecondary rate\b/i.test(error.message)) { + // The user has hit the secondary rate limit. (REST and GraphQL) + // https://docs.github.com/en/rest/overview/resources-in-the-rest-api#secondary-rate-limits + // The Retry-After header can sometimes be blank when hitting a secondary rate limit, + // but is always present after 2-3s, so make sure to set `retryAfter` to at least 5s by default. + const retryAfter = Math.max(~~error.response.headers["retry-after"], state.minimumSecondaryRateRetryAfter); + const wantRetry = await emitter.trigger("secondary-limit", retryAfter, options, octokit); + return { + wantRetry, + retryAfter + }; + } + + if (error.response.headers != null && error.response.headers["x-ratelimit-remaining"] === "0") { + // The user has used all their allowed calls for the current time period (REST and GraphQL) + // https://docs.github.com/en/rest/reference/rate-limit (REST) + // https://docs.github.com/en/graphql/overview/resource-limitations#rate-limit (GraphQL) + const rateLimitReset = new Date(~~error.response.headers["x-ratelimit-reset"] * 1000).getTime(); + const retryAfter = Math.max(Math.ceil((rateLimitReset - Date.now()) / 1000), 0); + const wantRetry = await emitter.trigger("rate-limit", retryAfter, options, octokit); + return { + wantRetry, + retryAfter + }; + } + + return {}; + }(); + + if (wantRetry) { + options.request.retryCount++; + return retryAfter * state.retryAfterBaseValue; + } + }); + octokit.hook.wrap("request", wrapRequest.bind(null, state)); + return {}; +} +throttling.VERSION = VERSION; +throttling.triggersNotification = triggersNotification; + +exports.throttling = throttling; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 1659: +/***/ ((module, exports, __nccwpck_require__) => { + +"use strict"; +/** + * @author Toru Nagashima + * See LICENSE file in root directory for full license. + */ + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var eventTargetShim = __nccwpck_require__(4697); + +/** + * The signal class. + * @see https://dom.spec.whatwg.org/#abortsignal + */ +class AbortSignal extends eventTargetShim.EventTarget { + /** + * AbortSignal cannot be constructed directly. + */ + constructor() { + super(); + throw new TypeError("AbortSignal cannot be constructed directly"); + } + /** + * Returns `true` if this `AbortSignal`'s `AbortController` has signaled to abort, and `false` otherwise. + */ + get aborted() { + const aborted = abortedFlags.get(this); + if (typeof aborted !== "boolean") { + throw new TypeError(`Expected 'this' to be an 'AbortSignal' object, but got ${this === null ? "null" : typeof this}`); + } + return aborted; + } +} +eventTargetShim.defineEventAttribute(AbortSignal.prototype, "abort"); +/** + * Create an AbortSignal object. + */ +function createAbortSignal() { + const signal = Object.create(AbortSignal.prototype); + eventTargetShim.EventTarget.call(signal); + abortedFlags.set(signal, false); + return signal; +} +/** + * Abort a given signal. + */ +function abortSignal(signal) { + if (abortedFlags.get(signal) !== false) { + return; + } + abortedFlags.set(signal, true); + signal.dispatchEvent({ type: "abort" }); +} +/** + * Aborted flag for each instances. + */ +const abortedFlags = new WeakMap(); +// Properties should be enumerable. +Object.defineProperties(AbortSignal.prototype, { + aborted: { enumerable: true }, +}); +// `toString()` should return `"[object AbortSignal]"` +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortSignal.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortSignal", + }); +} + +/** + * The AbortController. + * @see https://dom.spec.whatwg.org/#abortcontroller + */ +class AbortController { + /** + * Initialize this controller. + */ + constructor() { + signals.set(this, createAbortSignal()); + } + /** + * Returns the `AbortSignal` object associated with this object. + */ + get signal() { + return getSignal(this); + } + /** + * Abort and signal to any observers that the associated activity is to be aborted. + */ + abort() { + abortSignal(getSignal(this)); + } +} +/** + * Associated signals. + */ +const signals = new WeakMap(); +/** + * Get the associated signal of a given controller. + */ +function getSignal(controller) { + const signal = signals.get(controller); + if (signal == null) { + throw new TypeError(`Expected 'this' to be an 'AbortController' object, but got ${controller === null ? "null" : typeof controller}`); + } + return signal; +} +// Properties should be enumerable. +Object.defineProperties(AbortController.prototype, { + signal: { enumerable: true }, + abort: { enumerable: true }, +}); +if (typeof Symbol === "function" && typeof Symbol.toStringTag === "symbol") { + Object.defineProperty(AbortController.prototype, Symbol.toStringTag, { + configurable: true, + value: "AbortController", + }); +} + +exports.AbortController = AbortController; +exports.AbortSignal = AbortSignal; +exports["default"] = AbortController; + +module.exports = AbortController +module.exports.AbortController = module.exports["default"] = AbortController +module.exports.AbortSignal = AbortSignal +//# sourceMappingURL=abort-controller.js.map + + +/***/ }), + +/***/ 4623: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +module.exports = __nccwpck_require__(5006); +module.exports.HttpsAgent = __nccwpck_require__(5500); +module.exports.constants = __nccwpck_require__(7757); + + +/***/ }), + +/***/ 5006: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const OriginalAgent = (__nccwpck_require__(3685).Agent); +const ms = __nccwpck_require__(845); +const debug = (__nccwpck_require__(3837).debuglog)('agentkeepalive'); +const { + INIT_SOCKET, + CURRENT_ID, + CREATE_ID, + SOCKET_CREATED_TIME, + SOCKET_NAME, + SOCKET_REQUEST_COUNT, + SOCKET_REQUEST_FINISHED_COUNT, +} = __nccwpck_require__(7757); + +// OriginalAgent come from +// - https://github.com/nodejs/node/blob/v8.12.0/lib/_http_agent.js +// - https://github.com/nodejs/node/blob/v10.12.0/lib/_http_agent.js + +// node <= 10 +let defaultTimeoutListenerCount = 1; +const majorVersion = parseInt(process.version.split('.', 1)[0].substring(1)); +if (majorVersion >= 11 && majorVersion <= 12) { + defaultTimeoutListenerCount = 2; +} else if (majorVersion >= 13) { + defaultTimeoutListenerCount = 3; +} + +function deprecate(message) { + console.log('[agentkeepalive:deprecated] %s', message); +} + +class Agent extends OriginalAgent { + constructor(options) { + options = options || {}; + options.keepAlive = options.keepAlive !== false; + // default is keep-alive and 4s free socket timeout + // see https://medium.com/ssense-tech/reduce-networking-errors-in-nodejs-23b4eb9f2d83 + if (options.freeSocketTimeout === undefined) { + options.freeSocketTimeout = 4000; + } + // Legacy API: keepAliveTimeout should be rename to `freeSocketTimeout` + if (options.keepAliveTimeout) { + deprecate('options.keepAliveTimeout is deprecated, please use options.freeSocketTimeout instead'); + options.freeSocketTimeout = options.keepAliveTimeout; + delete options.keepAliveTimeout; + } + // Legacy API: freeSocketKeepAliveTimeout should be rename to `freeSocketTimeout` + if (options.freeSocketKeepAliveTimeout) { + deprecate('options.freeSocketKeepAliveTimeout is deprecated, please use options.freeSocketTimeout instead'); + options.freeSocketTimeout = options.freeSocketKeepAliveTimeout; + delete options.freeSocketKeepAliveTimeout; + } + + // Sets the socket to timeout after timeout milliseconds of inactivity on the socket. + // By default is double free socket timeout. + if (options.timeout === undefined) { + // make sure socket default inactivity timeout >= 8s + options.timeout = Math.max(options.freeSocketTimeout * 2, 8000); + } + + // support humanize format + options.timeout = ms(options.timeout); + options.freeSocketTimeout = ms(options.freeSocketTimeout); + options.socketActiveTTL = options.socketActiveTTL ? ms(options.socketActiveTTL) : 0; + + super(options); + + this[CURRENT_ID] = 0; + + // create socket success counter + this.createSocketCount = 0; + this.createSocketCountLastCheck = 0; + + this.createSocketErrorCount = 0; + this.createSocketErrorCountLastCheck = 0; + + this.closeSocketCount = 0; + this.closeSocketCountLastCheck = 0; + + // socket error event count + this.errorSocketCount = 0; + this.errorSocketCountLastCheck = 0; + + // request finished counter + this.requestCount = 0; + this.requestCountLastCheck = 0; + + // including free socket timeout counter + this.timeoutSocketCount = 0; + this.timeoutSocketCountLastCheck = 0; + + this.on('free', socket => { + // https://github.com/nodejs/node/pull/32000 + // Node.js native agent will check socket timeout eqs agent.options.timeout. + // Use the ttl or freeSocketTimeout to overwrite. + const timeout = this.calcSocketTimeout(socket); + if (timeout > 0 && socket.timeout !== timeout) { + socket.setTimeout(timeout); + } + }); + } + + get freeSocketKeepAliveTimeout() { + deprecate('agent.freeSocketKeepAliveTimeout is deprecated, please use agent.options.freeSocketTimeout instead'); + return this.options.freeSocketTimeout; + } + + get timeout() { + deprecate('agent.timeout is deprecated, please use agent.options.timeout instead'); + return this.options.timeout; + } + + get socketActiveTTL() { + deprecate('agent.socketActiveTTL is deprecated, please use agent.options.socketActiveTTL instead'); + return this.options.socketActiveTTL; + } + + calcSocketTimeout(socket) { + /** + * return <= 0: should free socket + * return > 0: should update socket timeout + * return undefined: not find custom timeout + */ + let freeSocketTimeout = this.options.freeSocketTimeout; + const socketActiveTTL = this.options.socketActiveTTL; + if (socketActiveTTL) { + // check socketActiveTTL + const aliveTime = Date.now() - socket[SOCKET_CREATED_TIME]; + const diff = socketActiveTTL - aliveTime; + if (diff <= 0) { + return diff; + } + if (freeSocketTimeout && diff < freeSocketTimeout) { + freeSocketTimeout = diff; + } + } + // set freeSocketTimeout + if (freeSocketTimeout) { + // set free keepalive timer + // try to use socket custom freeSocketTimeout first, support headers['keep-alive'] + // https://github.com/node-modules/urllib/blob/b76053020923f4d99a1c93cf2e16e0c5ba10bacf/lib/urllib.js#L498 + const customFreeSocketTimeout = socket.freeSocketTimeout || socket.freeSocketKeepAliveTimeout; + return customFreeSocketTimeout || freeSocketTimeout; + } + } + + keepSocketAlive(socket) { + const result = super.keepSocketAlive(socket); + // should not keepAlive, do nothing + if (!result) return result; + + const customTimeout = this.calcSocketTimeout(socket); + if (typeof customTimeout === 'undefined') { + return true; + } + if (customTimeout <= 0) { + debug('%s(requests: %s, finished: %s) free but need to destroy by TTL, request count %s, diff is %s', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], customTimeout); + return false; + } + if (socket.timeout !== customTimeout) { + socket.setTimeout(customTimeout); + } + return true; + } + + // only call on addRequest + reuseSocket(...args) { + // reuseSocket(socket, req) + super.reuseSocket(...args); + const socket = args[0]; + const req = args[1]; + req.reusedSocket = true; + const agentTimeout = this.options.timeout; + if (getSocketTimeout(socket) !== agentTimeout) { + // reset timeout before use + socket.setTimeout(agentTimeout); + debug('%s reset timeout to %sms', socket[SOCKET_NAME], agentTimeout); + } + socket[SOCKET_REQUEST_COUNT]++; + debug('%s(requests: %s, finished: %s) reuse on addRequest, timeout %sms', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], + getSocketTimeout(socket)); + } + + [CREATE_ID]() { + const id = this[CURRENT_ID]++; + if (this[CURRENT_ID] === Number.MAX_SAFE_INTEGER) this[CURRENT_ID] = 0; + return id; + } + + [INIT_SOCKET](socket, options) { + // bugfix here. + // https on node 8, 10 won't set agent.options.timeout by default + // TODO: need to fix on node itself + if (options.timeout) { + const timeout = getSocketTimeout(socket); + if (!timeout) { + socket.setTimeout(options.timeout); + } + } + + if (this.options.keepAlive) { + // Disable Nagle's algorithm: http://blog.caustik.com/2012/04/08/scaling-node-js-to-100k-concurrent-connections/ + // https://fengmk2.com/benchmark/nagle-algorithm-delayed-ack-mock.html + socket.setNoDelay(true); + } + this.createSocketCount++; + if (this.options.socketActiveTTL) { + socket[SOCKET_CREATED_TIME] = Date.now(); + } + // don't show the hole '-----BEGIN CERTIFICATE----' key string + socket[SOCKET_NAME] = `sock[${this[CREATE_ID]()}#${options._agentKey}]`.split('-----BEGIN', 1)[0]; + socket[SOCKET_REQUEST_COUNT] = 1; + socket[SOCKET_REQUEST_FINISHED_COUNT] = 0; + installListeners(this, socket, options); + } + + createConnection(options, oncreate) { + let called = false; + const onNewCreate = (err, socket) => { + if (called) return; + called = true; + + if (err) { + this.createSocketErrorCount++; + return oncreate(err); + } + this[INIT_SOCKET](socket, options); + oncreate(err, socket); + }; + + const newSocket = super.createConnection(options, onNewCreate); + if (newSocket) onNewCreate(null, newSocket); + return newSocket; + } + + get statusChanged() { + const changed = this.createSocketCount !== this.createSocketCountLastCheck || + this.createSocketErrorCount !== this.createSocketErrorCountLastCheck || + this.closeSocketCount !== this.closeSocketCountLastCheck || + this.errorSocketCount !== this.errorSocketCountLastCheck || + this.timeoutSocketCount !== this.timeoutSocketCountLastCheck || + this.requestCount !== this.requestCountLastCheck; + if (changed) { + this.createSocketCountLastCheck = this.createSocketCount; + this.createSocketErrorCountLastCheck = this.createSocketErrorCount; + this.closeSocketCountLastCheck = this.closeSocketCount; + this.errorSocketCountLastCheck = this.errorSocketCount; + this.timeoutSocketCountLastCheck = this.timeoutSocketCount; + this.requestCountLastCheck = this.requestCount; + } + return changed; + } + + getCurrentStatus() { + return { + createSocketCount: this.createSocketCount, + createSocketErrorCount: this.createSocketErrorCount, + closeSocketCount: this.closeSocketCount, + errorSocketCount: this.errorSocketCount, + timeoutSocketCount: this.timeoutSocketCount, + requestCount: this.requestCount, + freeSockets: inspect(this.freeSockets), + sockets: inspect(this.sockets), + requests: inspect(this.requests), + }; + } +} + +// node 8 don't has timeout attribute on socket +// https://github.com/nodejs/node/pull/21204/files#diff-e6ef024c3775d787c38487a6309e491dR408 +function getSocketTimeout(socket) { + return socket.timeout || socket._idleTimeout; +} + +function installListeners(agent, socket, options) { + debug('%s create, timeout %sms', socket[SOCKET_NAME], getSocketTimeout(socket)); + + // listener socket events: close, timeout, error, free + function onFree() { + // create and socket.emit('free') logic + // https://github.com/nodejs/node/blob/master/lib/_http_agent.js#L311 + // no req on the socket, it should be the new socket + if (!socket._httpMessage && socket[SOCKET_REQUEST_COUNT] === 1) return; + + socket[SOCKET_REQUEST_FINISHED_COUNT]++; + agent.requestCount++; + debug('%s(requests: %s, finished: %s) free', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]); + + // should reuse on pedding requests? + const name = agent.getName(options); + if (socket.writable && agent.requests[name] && agent.requests[name].length) { + // will be reuse on agent free listener + socket[SOCKET_REQUEST_COUNT]++; + debug('%s(requests: %s, finished: %s) will be reuse on agent free event', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]); + } + } + socket.on('free', onFree); + + function onClose(isError) { + debug('%s(requests: %s, finished: %s) close, isError: %s', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], isError); + agent.closeSocketCount++; + } + socket.on('close', onClose); + + // start socket timeout handler + function onTimeout() { + // onTimeout and emitRequestTimeout(_http_client.js) + // https://github.com/nodejs/node/blob/v12.x/lib/_http_client.js#L711 + const listenerCount = socket.listeners('timeout').length; + // node <= 10, default listenerCount is 1, onTimeout + // 11 < node <= 12, default listenerCount is 2, onTimeout and emitRequestTimeout + // node >= 13, default listenerCount is 3, onTimeout, + // onTimeout(https://github.com/nodejs/node/pull/32000/files#diff-5f7fb0850412c6be189faeddea6c5359R333) + // and emitRequestTimeout + const timeout = getSocketTimeout(socket); + const req = socket._httpMessage; + const reqTimeoutListenerCount = req && req.listeners('timeout').length || 0; + debug('%s(requests: %s, finished: %s) timeout after %sms, listeners %s, defaultTimeoutListenerCount %s, hasHttpRequest %s, HttpRequest timeoutListenerCount %s', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], + timeout, listenerCount, defaultTimeoutListenerCount, !!req, reqTimeoutListenerCount); + if (debug.enabled) { + debug('timeout listeners: %s', socket.listeners('timeout').map(f => f.name).join(', ')); + } + agent.timeoutSocketCount++; + const name = agent.getName(options); + if (agent.freeSockets[name] && agent.freeSockets[name].indexOf(socket) !== -1) { + // free socket timeout, destroy quietly + socket.destroy(); + // Remove it from freeSockets list immediately to prevent new requests + // from being sent through this socket. + agent.removeSocket(socket, options); + debug('%s is free, destroy quietly', socket[SOCKET_NAME]); + } else { + // if there is no any request socket timeout handler, + // agent need to handle socket timeout itself. + // + // custom request socket timeout handle logic must follow these rules: + // 1. Destroy socket first + // 2. Must emit socket 'agentRemove' event tell agent remove socket + // from freeSockets list immediately. + // Otherise you may be get 'socket hang up' error when reuse + // free socket and timeout happen in the same time. + if (reqTimeoutListenerCount === 0) { + const error = new Error('Socket timeout'); + error.code = 'ERR_SOCKET_TIMEOUT'; + error.timeout = timeout; + // must manually call socket.end() or socket.destroy() to end the connection. + // https://nodejs.org/dist/latest-v10.x/docs/api/net.html#net_socket_settimeout_timeout_callback + socket.destroy(error); + agent.removeSocket(socket, options); + debug('%s destroy with timeout error', socket[SOCKET_NAME]); + } + } + } + socket.on('timeout', onTimeout); + + function onError(err) { + const listenerCount = socket.listeners('error').length; + debug('%s(requests: %s, finished: %s) error: %s, listenerCount: %s', + socket[SOCKET_NAME], socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT], + err, listenerCount); + agent.errorSocketCount++; + if (listenerCount === 1) { + // if socket don't contain error event handler, don't catch it, emit it again + debug('%s emit uncaught error event', socket[SOCKET_NAME]); + socket.removeListener('error', onError); + socket.emit('error', err); + } + } + socket.on('error', onError); + + function onRemove() { + debug('%s(requests: %s, finished: %s) agentRemove', + socket[SOCKET_NAME], + socket[SOCKET_REQUEST_COUNT], socket[SOCKET_REQUEST_FINISHED_COUNT]); + // We need this function for cases like HTTP 'upgrade' + // (defined by WebSockets) where we need to remove a socket from the + // pool because it'll be locked up indefinitely + socket.removeListener('close', onClose); + socket.removeListener('error', onError); + socket.removeListener('free', onFree); + socket.removeListener('timeout', onTimeout); + socket.removeListener('agentRemove', onRemove); + } + socket.on('agentRemove', onRemove); +} + +module.exports = Agent; + +function inspect(obj) { + const res = {}; + for (const key in obj) { + res[key] = obj[key].length; + } + return res; +} + + +/***/ }), + +/***/ 7757: +/***/ ((module) => { + +"use strict"; + + +module.exports = { + // agent + CURRENT_ID: Symbol('agentkeepalive#currentId'), + CREATE_ID: Symbol('agentkeepalive#createId'), + INIT_SOCKET: Symbol('agentkeepalive#initSocket'), + CREATE_HTTPS_CONNECTION: Symbol('agentkeepalive#createHttpsConnection'), + // socket + SOCKET_CREATED_TIME: Symbol('agentkeepalive#socketCreatedTime'), + SOCKET_NAME: Symbol('agentkeepalive#socketName'), + SOCKET_REQUEST_COUNT: Symbol('agentkeepalive#socketRequestCount'), + SOCKET_REQUEST_FINISHED_COUNT: Symbol('agentkeepalive#socketRequestFinishedCount'), +}; + + +/***/ }), + +/***/ 5500: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const OriginalHttpsAgent = (__nccwpck_require__(5687).Agent); +const HttpAgent = __nccwpck_require__(5006); +const { + INIT_SOCKET, + CREATE_HTTPS_CONNECTION, +} = __nccwpck_require__(7757); + +class HttpsAgent extends HttpAgent { + constructor(options) { + super(options); + + this.defaultPort = 443; + this.protocol = 'https:'; + this.maxCachedSessions = this.options.maxCachedSessions; + /* istanbul ignore next */ + if (this.maxCachedSessions === undefined) { + this.maxCachedSessions = 100; + } + + this._sessionCache = { + map: {}, + list: [], + }; + } + + createConnection(options, oncreate) { + const socket = this[CREATE_HTTPS_CONNECTION](options, oncreate); + this[INIT_SOCKET](socket, options); + return socket; + } +} + +// https://github.com/nodejs/node/blob/master/lib/https.js#L89 +HttpsAgent.prototype[CREATE_HTTPS_CONNECTION] = OriginalHttpsAgent.prototype.createConnection; + +[ + 'getName', + '_getSession', + '_cacheSession', + // https://github.com/nodejs/node/pull/4982 + '_evictSession', +].forEach(function(method) { + /* istanbul ignore next */ + if (typeof OriginalHttpsAgent.prototype[method] === 'function') { + HttpsAgent.prototype[method] = OriginalHttpsAgent.prototype[method]; + } +}); + +module.exports = HttpsAgent; + + +/***/ }), + +/***/ 3682: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var register = __nccwpck_require__(4670) +var addHook = __nccwpck_require__(5549) +var removeHook = __nccwpck_require__(6819) + +// bind with array of arguments: https://stackoverflow.com/a/21792913 +var bind = Function.bind +var bindable = bind.bind(bind) + +function bindApi (hook, state, name) { + var removeHookRef = bindable(removeHook, null).apply(null, name ? [state, name] : [state]) + hook.api = { remove: removeHookRef } + hook.remove = removeHookRef + + ;['before', 'error', 'after', 'wrap'].forEach(function (kind) { + var args = name ? [state, kind, name] : [state, kind] + hook[kind] = hook.api[kind] = bindable(addHook, null).apply(null, args) + }) +} + +function HookSingular () { + var singularHookName = 'h' + var singularHookState = { + registry: {} + } + var singularHook = register.bind(null, singularHookState, singularHookName) + bindApi(singularHook, singularHookState, singularHookName) + return singularHook +} + +function HookCollection () { + var state = { + registry: {} + } + + var hook = register.bind(null, state) + bindApi(hook, state) + + return hook +} + +var collectionHookDeprecationMessageDisplayed = false +function Hook () { + if (!collectionHookDeprecationMessageDisplayed) { + console.warn('[before-after-hook]: "Hook()" repurposing warning, use "Hook.Collection()". Read more: https://git.io/upgrade-before-after-hook-to-1.4') + collectionHookDeprecationMessageDisplayed = true + } + return HookCollection() +} + +Hook.Singular = HookSingular.bind() +Hook.Collection = HookCollection.bind() + +module.exports = Hook +// expose constructors as a named property for TypeScript +module.exports.Hook = Hook +module.exports.Singular = Hook.Singular +module.exports.Collection = Hook.Collection + + +/***/ }), + +/***/ 5549: +/***/ ((module) => { + +module.exports = addHook; + +function addHook(state, kind, name, hook) { + var orig = hook; + if (!state.registry[name]) { + state.registry[name] = []; + } + + if (kind === "before") { + hook = function (method, options) { + return Promise.resolve() + .then(orig.bind(null, options)) + .then(method.bind(null, options)); + }; + } + + if (kind === "after") { + hook = function (method, options) { + var result; + return Promise.resolve() + .then(method.bind(null, options)) + .then(function (result_) { + result = result_; + return orig(result, options); + }) + .then(function () { + return result; + }); + }; + } + + if (kind === "error") { + hook = function (method, options) { + return Promise.resolve() + .then(method.bind(null, options)) + .catch(function (error) { + return orig(error, options); + }); + }; + } + + state.registry[name].push({ + hook: hook, + orig: orig, + }); +} + + +/***/ }), + +/***/ 4670: +/***/ ((module) => { + +module.exports = register; + +function register(state, name, method, options) { + if (typeof method !== "function") { + throw new Error("method for before hook must be a function"); + } + + if (!options) { + options = {}; + } + + if (Array.isArray(name)) { + return name.reverse().reduce(function (callback, name) { + return register.bind(null, state, name, callback, options); + }, method)(); + } + + return Promise.resolve().then(function () { + if (!state.registry[name]) { + return method(options); + } + + return state.registry[name].reduce(function (method, registered) { + return registered.hook.bind(null, method, options); + }, method)(); + }); +} + + +/***/ }), + +/***/ 6819: +/***/ ((module) => { + +module.exports = removeHook; + +function removeHook(state, name, method) { + if (!state.registry[name]) { + return; + } + + var index = state.registry[name] + .map(function (registered) { + return registered.orig; + }) + .indexOf(method); + + if (index === -1) { + return; + } + + state.registry[name].splice(index, 1); +} + + +/***/ }), + +/***/ 1174: +/***/ (function(module) { + +/** + * This file contains the Bottleneck library (MIT), compiled to ES2017, and without Clustering support. + * https://github.com/SGrondin/bottleneck + */ +(function (global, factory) { + true ? module.exports = factory() : + 0; +}(this, (function () { 'use strict'; + + var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; + + function getCjsExportFromNamespace (n) { + return n && n['default'] || n; + } + + var load = function(received, defaults, onto = {}) { + var k, ref, v; + for (k in defaults) { + v = defaults[k]; + onto[k] = (ref = received[k]) != null ? ref : v; + } + return onto; + }; + + var overwrite = function(received, defaults, onto = {}) { + var k, v; + for (k in received) { + v = received[k]; + if (defaults[k] !== void 0) { + onto[k] = v; + } + } + return onto; + }; + + var parser = { + load: load, + overwrite: overwrite + }; + + var DLList; + + DLList = class DLList { + constructor(incr, decr) { + this.incr = incr; + this.decr = decr; + this._first = null; + this._last = null; + this.length = 0; + } + + push(value) { + var node; + this.length++; + if (typeof this.incr === "function") { + this.incr(); + } + node = { + value, + prev: this._last, + next: null + }; + if (this._last != null) { + this._last.next = node; + this._last = node; + } else { + this._first = this._last = node; + } + return void 0; + } + + shift() { + var value; + if (this._first == null) { + return; + } else { + this.length--; + if (typeof this.decr === "function") { + this.decr(); + } + } + value = this._first.value; + if ((this._first = this._first.next) != null) { + this._first.prev = null; + } else { + this._last = null; + } + return value; + } + + first() { + if (this._first != null) { + return this._first.value; + } + } + + getArray() { + var node, ref, results; + node = this._first; + results = []; + while (node != null) { + results.push((ref = node, node = node.next, ref.value)); + } + return results; + } + + forEachShift(cb) { + var node; + node = this.shift(); + while (node != null) { + (cb(node), node = this.shift()); + } + return void 0; + } + + debug() { + var node, ref, ref1, ref2, results; + node = this._first; + results = []; + while (node != null) { + results.push((ref = node, node = node.next, { + value: ref.value, + prev: (ref1 = ref.prev) != null ? ref1.value : void 0, + next: (ref2 = ref.next) != null ? ref2.value : void 0 + })); + } + return results; + } + + }; + + var DLList_1 = DLList; + + var Events; + + Events = class Events { + constructor(instance) { + this.instance = instance; + this._events = {}; + if ((this.instance.on != null) || (this.instance.once != null) || (this.instance.removeAllListeners != null)) { + throw new Error("An Emitter already exists for this object"); + } + this.instance.on = (name, cb) => { + return this._addListener(name, "many", cb); + }; + this.instance.once = (name, cb) => { + return this._addListener(name, "once", cb); + }; + this.instance.removeAllListeners = (name = null) => { + if (name != null) { + return delete this._events[name]; + } else { + return this._events = {}; + } + }; + } + + _addListener(name, status, cb) { + var base; + if ((base = this._events)[name] == null) { + base[name] = []; + } + this._events[name].push({cb, status}); + return this.instance; + } + + listenerCount(name) { + if (this._events[name] != null) { + return this._events[name].length; + } else { + return 0; + } + } + + async trigger(name, ...args) { + var e, promises; + try { + if (name !== "debug") { + this.trigger("debug", `Event triggered: ${name}`, args); + } + if (this._events[name] == null) { + return; + } + this._events[name] = this._events[name].filter(function(listener) { + return listener.status !== "none"; + }); + promises = this._events[name].map(async(listener) => { + var e, returned; + if (listener.status === "none") { + return; + } + if (listener.status === "once") { + listener.status = "none"; + } + try { + returned = typeof listener.cb === "function" ? listener.cb(...args) : void 0; + if (typeof (returned != null ? returned.then : void 0) === "function") { + return (await returned); + } else { + return returned; + } + } catch (error) { + e = error; + { + this.trigger("error", e); + } + return null; + } + }); + return ((await Promise.all(promises))).find(function(x) { + return x != null; + }); + } catch (error) { + e = error; + { + this.trigger("error", e); + } + return null; + } + } + + }; + + var Events_1 = Events; + + var DLList$1, Events$1, Queues; + + DLList$1 = DLList_1; + + Events$1 = Events_1; + + Queues = class Queues { + constructor(num_priorities) { + var i; + this.Events = new Events$1(this); + this._length = 0; + this._lists = (function() { + var j, ref, results; + results = []; + for (i = j = 1, ref = num_priorities; (1 <= ref ? j <= ref : j >= ref); i = 1 <= ref ? ++j : --j) { + results.push(new DLList$1((() => { + return this.incr(); + }), (() => { + return this.decr(); + }))); + } + return results; + }).call(this); + } + + incr() { + if (this._length++ === 0) { + return this.Events.trigger("leftzero"); + } + } + + decr() { + if (--this._length === 0) { + return this.Events.trigger("zero"); + } + } + + push(job) { + return this._lists[job.options.priority].push(job); + } + + queued(priority) { + if (priority != null) { + return this._lists[priority].length; + } else { + return this._length; + } + } + + shiftAll(fn) { + return this._lists.forEach(function(list) { + return list.forEachShift(fn); + }); + } + + getFirst(arr = this._lists) { + var j, len, list; + for (j = 0, len = arr.length; j < len; j++) { + list = arr[j]; + if (list.length > 0) { + return list; + } + } + return []; + } + + shiftLastFrom(priority) { + return this.getFirst(this._lists.slice(priority).reverse()).shift(); + } + + }; + + var Queues_1 = Queues; + + var BottleneckError; + + BottleneckError = class BottleneckError extends Error {}; + + var BottleneckError_1 = BottleneckError; + + var BottleneckError$1, DEFAULT_PRIORITY, Job, NUM_PRIORITIES, parser$1; + + NUM_PRIORITIES = 10; + + DEFAULT_PRIORITY = 5; + + parser$1 = parser; + + BottleneckError$1 = BottleneckError_1; + + Job = class Job { + constructor(task, args, options, jobDefaults, rejectOnDrop, Events, _states, Promise) { + this.task = task; + this.args = args; + this.rejectOnDrop = rejectOnDrop; + this.Events = Events; + this._states = _states; + this.Promise = Promise; + this.options = parser$1.load(options, jobDefaults); + this.options.priority = this._sanitizePriority(this.options.priority); + if (this.options.id === jobDefaults.id) { + this.options.id = `${this.options.id}-${this._randomIndex()}`; + } + this.promise = new this.Promise((_resolve, _reject) => { + this._resolve = _resolve; + this._reject = _reject; + }); + this.retryCount = 0; + } + + _sanitizePriority(priority) { + var sProperty; + sProperty = ~~priority !== priority ? DEFAULT_PRIORITY : priority; + if (sProperty < 0) { + return 0; + } else if (sProperty > NUM_PRIORITIES - 1) { + return NUM_PRIORITIES - 1; + } else { + return sProperty; + } + } + + _randomIndex() { + return Math.random().toString(36).slice(2); + } + + doDrop({error, message = "This job has been dropped by Bottleneck"} = {}) { + if (this._states.remove(this.options.id)) { + if (this.rejectOnDrop) { + this._reject(error != null ? error : new BottleneckError$1(message)); + } + this.Events.trigger("dropped", {args: this.args, options: this.options, task: this.task, promise: this.promise}); + return true; + } else { + return false; + } + } + + _assertStatus(expected) { + var status; + status = this._states.jobStatus(this.options.id); + if (!(status === expected || (expected === "DONE" && status === null))) { + throw new BottleneckError$1(`Invalid job status ${status}, expected ${expected}. Please open an issue at https://github.com/SGrondin/bottleneck/issues`); + } + } + + doReceive() { + this._states.start(this.options.id); + return this.Events.trigger("received", {args: this.args, options: this.options}); + } + + doQueue(reachedHWM, blocked) { + this._assertStatus("RECEIVED"); + this._states.next(this.options.id); + return this.Events.trigger("queued", {args: this.args, options: this.options, reachedHWM, blocked}); + } + + doRun() { + if (this.retryCount === 0) { + this._assertStatus("QUEUED"); + this._states.next(this.options.id); + } else { + this._assertStatus("EXECUTING"); + } + return this.Events.trigger("scheduled", {args: this.args, options: this.options}); + } + + async doExecute(chained, clearGlobalState, run, free) { + var error, eventInfo, passed; + if (this.retryCount === 0) { + this._assertStatus("RUNNING"); + this._states.next(this.options.id); + } else { + this._assertStatus("EXECUTING"); + } + eventInfo = {args: this.args, options: this.options, retryCount: this.retryCount}; + this.Events.trigger("executing", eventInfo); + try { + passed = (await (chained != null ? chained.schedule(this.options, this.task, ...this.args) : this.task(...this.args))); + if (clearGlobalState()) { + this.doDone(eventInfo); + await free(this.options, eventInfo); + this._assertStatus("DONE"); + return this._resolve(passed); + } + } catch (error1) { + error = error1; + return this._onFailure(error, eventInfo, clearGlobalState, run, free); + } + } + + doExpire(clearGlobalState, run, free) { + var error, eventInfo; + if (this._states.jobStatus(this.options.id === "RUNNING")) { + this._states.next(this.options.id); + } + this._assertStatus("EXECUTING"); + eventInfo = {args: this.args, options: this.options, retryCount: this.retryCount}; + error = new BottleneckError$1(`This job timed out after ${this.options.expiration} ms.`); + return this._onFailure(error, eventInfo, clearGlobalState, run, free); + } + + async _onFailure(error, eventInfo, clearGlobalState, run, free) { + var retry, retryAfter; + if (clearGlobalState()) { + retry = (await this.Events.trigger("failed", error, eventInfo)); + if (retry != null) { + retryAfter = ~~retry; + this.Events.trigger("retry", `Retrying ${this.options.id} after ${retryAfter} ms`, eventInfo); + this.retryCount++; + return run(retryAfter); + } else { + this.doDone(eventInfo); + await free(this.options, eventInfo); + this._assertStatus("DONE"); + return this._reject(error); + } + } + } + + doDone(eventInfo) { + this._assertStatus("EXECUTING"); + this._states.next(this.options.id); + return this.Events.trigger("done", eventInfo); + } + + }; + + var Job_1 = Job; + + var BottleneckError$2, LocalDatastore, parser$2; + + parser$2 = parser; + + BottleneckError$2 = BottleneckError_1; + + LocalDatastore = class LocalDatastore { + constructor(instance, storeOptions, storeInstanceOptions) { + this.instance = instance; + this.storeOptions = storeOptions; + this.clientId = this.instance._randomIndex(); + parser$2.load(storeInstanceOptions, storeInstanceOptions, this); + this._nextRequest = this._lastReservoirRefresh = this._lastReservoirIncrease = Date.now(); + this._running = 0; + this._done = 0; + this._unblockTime = 0; + this.ready = this.Promise.resolve(); + this.clients = {}; + this._startHeartbeat(); + } + + _startHeartbeat() { + var base; + if ((this.heartbeat == null) && (((this.storeOptions.reservoirRefreshInterval != null) && (this.storeOptions.reservoirRefreshAmount != null)) || ((this.storeOptions.reservoirIncreaseInterval != null) && (this.storeOptions.reservoirIncreaseAmount != null)))) { + return typeof (base = (this.heartbeat = setInterval(() => { + var amount, incr, maximum, now, reservoir; + now = Date.now(); + if ((this.storeOptions.reservoirRefreshInterval != null) && now >= this._lastReservoirRefresh + this.storeOptions.reservoirRefreshInterval) { + this._lastReservoirRefresh = now; + this.storeOptions.reservoir = this.storeOptions.reservoirRefreshAmount; + this.instance._drainAll(this.computeCapacity()); + } + if ((this.storeOptions.reservoirIncreaseInterval != null) && now >= this._lastReservoirIncrease + this.storeOptions.reservoirIncreaseInterval) { + ({ + reservoirIncreaseAmount: amount, + reservoirIncreaseMaximum: maximum, + reservoir + } = this.storeOptions); + this._lastReservoirIncrease = now; + incr = maximum != null ? Math.min(amount, maximum - reservoir) : amount; + if (incr > 0) { + this.storeOptions.reservoir += incr; + return this.instance._drainAll(this.computeCapacity()); + } + } + }, this.heartbeatInterval))).unref === "function" ? base.unref() : void 0; + } else { + return clearInterval(this.heartbeat); + } + } + + async __publish__(message) { + await this.yieldLoop(); + return this.instance.Events.trigger("message", message.toString()); + } + + async __disconnect__(flush) { + await this.yieldLoop(); + clearInterval(this.heartbeat); + return this.Promise.resolve(); + } + + yieldLoop(t = 0) { + return new this.Promise(function(resolve, reject) { + return setTimeout(resolve, t); + }); + } + + computePenalty() { + var ref; + return (ref = this.storeOptions.penalty) != null ? ref : (15 * this.storeOptions.minTime) || 5000; + } + + async __updateSettings__(options) { + await this.yieldLoop(); + parser$2.overwrite(options, options, this.storeOptions); + this._startHeartbeat(); + this.instance._drainAll(this.computeCapacity()); + return true; + } + + async __running__() { + await this.yieldLoop(); + return this._running; + } + + async __queued__() { + await this.yieldLoop(); + return this.instance.queued(); + } + + async __done__() { + await this.yieldLoop(); + return this._done; + } + + async __groupCheck__(time) { + await this.yieldLoop(); + return (this._nextRequest + this.timeout) < time; + } + + computeCapacity() { + var maxConcurrent, reservoir; + ({maxConcurrent, reservoir} = this.storeOptions); + if ((maxConcurrent != null) && (reservoir != null)) { + return Math.min(maxConcurrent - this._running, reservoir); + } else if (maxConcurrent != null) { + return maxConcurrent - this._running; + } else if (reservoir != null) { + return reservoir; + } else { + return null; + } + } + + conditionsCheck(weight) { + var capacity; + capacity = this.computeCapacity(); + return (capacity == null) || weight <= capacity; + } + + async __incrementReservoir__(incr) { + var reservoir; + await this.yieldLoop(); + reservoir = this.storeOptions.reservoir += incr; + this.instance._drainAll(this.computeCapacity()); + return reservoir; + } + + async __currentReservoir__() { + await this.yieldLoop(); + return this.storeOptions.reservoir; + } + + isBlocked(now) { + return this._unblockTime >= now; + } + + check(weight, now) { + return this.conditionsCheck(weight) && (this._nextRequest - now) <= 0; + } + + async __check__(weight) { + var now; + await this.yieldLoop(); + now = Date.now(); + return this.check(weight, now); + } + + async __register__(index, weight, expiration) { + var now, wait; + await this.yieldLoop(); + now = Date.now(); + if (this.conditionsCheck(weight)) { + this._running += weight; + if (this.storeOptions.reservoir != null) { + this.storeOptions.reservoir -= weight; + } + wait = Math.max(this._nextRequest - now, 0); + this._nextRequest = now + wait + this.storeOptions.minTime; + return { + success: true, + wait, + reservoir: this.storeOptions.reservoir + }; + } else { + return { + success: false + }; + } + } + + strategyIsBlock() { + return this.storeOptions.strategy === 3; + } + + async __submit__(queueLength, weight) { + var blocked, now, reachedHWM; + await this.yieldLoop(); + if ((this.storeOptions.maxConcurrent != null) && weight > this.storeOptions.maxConcurrent) { + throw new BottleneckError$2(`Impossible to add a job having a weight of ${weight} to a limiter having a maxConcurrent setting of ${this.storeOptions.maxConcurrent}`); + } + now = Date.now(); + reachedHWM = (this.storeOptions.highWater != null) && queueLength === this.storeOptions.highWater && !this.check(weight, now); + blocked = this.strategyIsBlock() && (reachedHWM || this.isBlocked(now)); + if (blocked) { + this._unblockTime = now + this.computePenalty(); + this._nextRequest = this._unblockTime + this.storeOptions.minTime; + this.instance._dropAllQueued(); + } + return { + reachedHWM, + blocked, + strategy: this.storeOptions.strategy + }; + } + + async __free__(index, weight) { + await this.yieldLoop(); + this._running -= weight; + this._done += weight; + this.instance._drainAll(this.computeCapacity()); + return { + running: this._running + }; + } + + }; + + var LocalDatastore_1 = LocalDatastore; + + var BottleneckError$3, States; + + BottleneckError$3 = BottleneckError_1; + + States = class States { + constructor(status1) { + this.status = status1; + this._jobs = {}; + this.counts = this.status.map(function() { + return 0; + }); + } + + next(id) { + var current, next; + current = this._jobs[id]; + next = current + 1; + if ((current != null) && next < this.status.length) { + this.counts[current]--; + this.counts[next]++; + return this._jobs[id]++; + } else if (current != null) { + this.counts[current]--; + return delete this._jobs[id]; + } + } + + start(id) { + var initial; + initial = 0; + this._jobs[id] = initial; + return this.counts[initial]++; + } + + remove(id) { + var current; + current = this._jobs[id]; + if (current != null) { + this.counts[current]--; + delete this._jobs[id]; + } + return current != null; + } + + jobStatus(id) { + var ref; + return (ref = this.status[this._jobs[id]]) != null ? ref : null; + } + + statusJobs(status) { + var k, pos, ref, results, v; + if (status != null) { + pos = this.status.indexOf(status); + if (pos < 0) { + throw new BottleneckError$3(`status must be one of ${this.status.join(', ')}`); + } + ref = this._jobs; + results = []; + for (k in ref) { + v = ref[k]; + if (v === pos) { + results.push(k); + } + } + return results; + } else { + return Object.keys(this._jobs); + } + } + + statusCounts() { + return this.counts.reduce(((acc, v, i) => { + acc[this.status[i]] = v; + return acc; + }), {}); + } + + }; + + var States_1 = States; + + var DLList$2, Sync; + + DLList$2 = DLList_1; + + Sync = class Sync { + constructor(name, Promise) { + this.schedule = this.schedule.bind(this); + this.name = name; + this.Promise = Promise; + this._running = 0; + this._queue = new DLList$2(); + } + + isEmpty() { + return this._queue.length === 0; + } + + async _tryToRun() { + var args, cb, error, reject, resolve, returned, task; + if ((this._running < 1) && this._queue.length > 0) { + this._running++; + ({task, args, resolve, reject} = this._queue.shift()); + cb = (await (async function() { + try { + returned = (await task(...args)); + return function() { + return resolve(returned); + }; + } catch (error1) { + error = error1; + return function() { + return reject(error); + }; + } + })()); + this._running--; + this._tryToRun(); + return cb(); + } + } + + schedule(task, ...args) { + var promise, reject, resolve; + resolve = reject = null; + promise = new this.Promise(function(_resolve, _reject) { + resolve = _resolve; + return reject = _reject; + }); + this._queue.push({task, args, resolve, reject}); + this._tryToRun(); + return promise; + } + + }; + + var Sync_1 = Sync; + + var version = "2.19.5"; + var version$1 = { + version: version + }; + + var version$2 = /*#__PURE__*/Object.freeze({ + version: version, + default: version$1 + }); + + var require$$2 = () => console.log('You must import the full version of Bottleneck in order to use this feature.'); + + var require$$3 = () => console.log('You must import the full version of Bottleneck in order to use this feature.'); + + var require$$4 = () => console.log('You must import the full version of Bottleneck in order to use this feature.'); + + var Events$2, Group, IORedisConnection$1, RedisConnection$1, Scripts$1, parser$3; + + parser$3 = parser; + + Events$2 = Events_1; + + RedisConnection$1 = require$$2; + + IORedisConnection$1 = require$$3; + + Scripts$1 = require$$4; + + Group = (function() { + class Group { + constructor(limiterOptions = {}) { + this.deleteKey = this.deleteKey.bind(this); + this.limiterOptions = limiterOptions; + parser$3.load(this.limiterOptions, this.defaults, this); + this.Events = new Events$2(this); + this.instances = {}; + this.Bottleneck = Bottleneck_1; + this._startAutoCleanup(); + this.sharedConnection = this.connection != null; + if (this.connection == null) { + if (this.limiterOptions.datastore === "redis") { + this.connection = new RedisConnection$1(Object.assign({}, this.limiterOptions, {Events: this.Events})); + } else if (this.limiterOptions.datastore === "ioredis") { + this.connection = new IORedisConnection$1(Object.assign({}, this.limiterOptions, {Events: this.Events})); + } + } + } + + key(key = "") { + var ref; + return (ref = this.instances[key]) != null ? ref : (() => { + var limiter; + limiter = this.instances[key] = new this.Bottleneck(Object.assign(this.limiterOptions, { + id: `${this.id}-${key}`, + timeout: this.timeout, + connection: this.connection + })); + this.Events.trigger("created", limiter, key); + return limiter; + })(); + } + + async deleteKey(key = "") { + var deleted, instance; + instance = this.instances[key]; + if (this.connection) { + deleted = (await this.connection.__runCommand__(['del', ...Scripts$1.allKeys(`${this.id}-${key}`)])); + } + if (instance != null) { + delete this.instances[key]; + await instance.disconnect(); + } + return (instance != null) || deleted > 0; + } + + limiters() { + var k, ref, results, v; + ref = this.instances; + results = []; + for (k in ref) { + v = ref[k]; + results.push({ + key: k, + limiter: v + }); + } + return results; + } + + keys() { + return Object.keys(this.instances); + } + + async clusterKeys() { + var cursor, end, found, i, k, keys, len, next, start; + if (this.connection == null) { + return this.Promise.resolve(this.keys()); + } + keys = []; + cursor = null; + start = `b_${this.id}-`.length; + end = "_settings".length; + while (cursor !== 0) { + [next, found] = (await this.connection.__runCommand__(["scan", cursor != null ? cursor : 0, "match", `b_${this.id}-*_settings`, "count", 10000])); + cursor = ~~next; + for (i = 0, len = found.length; i < len; i++) { + k = found[i]; + keys.push(k.slice(start, -end)); + } + } + return keys; + } + + _startAutoCleanup() { + var base; + clearInterval(this.interval); + return typeof (base = (this.interval = setInterval(async() => { + var e, k, ref, results, time, v; + time = Date.now(); + ref = this.instances; + results = []; + for (k in ref) { + v = ref[k]; + try { + if ((await v._store.__groupCheck__(time))) { + results.push(this.deleteKey(k)); + } else { + results.push(void 0); + } + } catch (error) { + e = error; + results.push(v.Events.trigger("error", e)); + } + } + return results; + }, this.timeout / 2))).unref === "function" ? base.unref() : void 0; + } + + updateSettings(options = {}) { + parser$3.overwrite(options, this.defaults, this); + parser$3.overwrite(options, options, this.limiterOptions); + if (options.timeout != null) { + return this._startAutoCleanup(); + } + } + + disconnect(flush = true) { + var ref; + if (!this.sharedConnection) { + return (ref = this.connection) != null ? ref.disconnect(flush) : void 0; + } + } + + } + Group.prototype.defaults = { + timeout: 1000 * 60 * 5, + connection: null, + Promise: Promise, + id: "group-key" + }; + + return Group; + + }).call(commonjsGlobal); + + var Group_1 = Group; + + var Batcher, Events$3, parser$4; + + parser$4 = parser; + + Events$3 = Events_1; + + Batcher = (function() { + class Batcher { + constructor(options = {}) { + this.options = options; + parser$4.load(this.options, this.defaults, this); + this.Events = new Events$3(this); + this._arr = []; + this._resetPromise(); + this._lastFlush = Date.now(); + } + + _resetPromise() { + return this._promise = new this.Promise((res, rej) => { + return this._resolve = res; + }); + } + + _flush() { + clearTimeout(this._timeout); + this._lastFlush = Date.now(); + this._resolve(); + this.Events.trigger("batch", this._arr); + this._arr = []; + return this._resetPromise(); + } + + add(data) { + var ret; + this._arr.push(data); + ret = this._promise; + if (this._arr.length === this.maxSize) { + this._flush(); + } else if ((this.maxTime != null) && this._arr.length === 1) { + this._timeout = setTimeout(() => { + return this._flush(); + }, this.maxTime); + } + return ret; + } + + } + Batcher.prototype.defaults = { + maxTime: null, + maxSize: null, + Promise: Promise + }; + + return Batcher; + + }).call(commonjsGlobal); + + var Batcher_1 = Batcher; + + var require$$4$1 = () => console.log('You must import the full version of Bottleneck in order to use this feature.'); + + var require$$8 = getCjsExportFromNamespace(version$2); + + var Bottleneck, DEFAULT_PRIORITY$1, Events$4, Job$1, LocalDatastore$1, NUM_PRIORITIES$1, Queues$1, RedisDatastore$1, States$1, Sync$1, parser$5, + splice = [].splice; + + NUM_PRIORITIES$1 = 10; + + DEFAULT_PRIORITY$1 = 5; + + parser$5 = parser; + + Queues$1 = Queues_1; + + Job$1 = Job_1; + + LocalDatastore$1 = LocalDatastore_1; + + RedisDatastore$1 = require$$4$1; + + Events$4 = Events_1; + + States$1 = States_1; + + Sync$1 = Sync_1; + + Bottleneck = (function() { + class Bottleneck { + constructor(options = {}, ...invalid) { + var storeInstanceOptions, storeOptions; + this._addToQueue = this._addToQueue.bind(this); + this._validateOptions(options, invalid); + parser$5.load(options, this.instanceDefaults, this); + this._queues = new Queues$1(NUM_PRIORITIES$1); + this._scheduled = {}; + this._states = new States$1(["RECEIVED", "QUEUED", "RUNNING", "EXECUTING"].concat(this.trackDoneStatus ? ["DONE"] : [])); + this._limiter = null; + this.Events = new Events$4(this); + this._submitLock = new Sync$1("submit", this.Promise); + this._registerLock = new Sync$1("register", this.Promise); + storeOptions = parser$5.load(options, this.storeDefaults, {}); + this._store = (function() { + if (this.datastore === "redis" || this.datastore === "ioredis" || (this.connection != null)) { + storeInstanceOptions = parser$5.load(options, this.redisStoreDefaults, {}); + return new RedisDatastore$1(this, storeOptions, storeInstanceOptions); + } else if (this.datastore === "local") { + storeInstanceOptions = parser$5.load(options, this.localStoreDefaults, {}); + return new LocalDatastore$1(this, storeOptions, storeInstanceOptions); + } else { + throw new Bottleneck.prototype.BottleneckError(`Invalid datastore type: ${this.datastore}`); + } + }).call(this); + this._queues.on("leftzero", () => { + var ref; + return (ref = this._store.heartbeat) != null ? typeof ref.ref === "function" ? ref.ref() : void 0 : void 0; + }); + this._queues.on("zero", () => { + var ref; + return (ref = this._store.heartbeat) != null ? typeof ref.unref === "function" ? ref.unref() : void 0 : void 0; + }); + } + + _validateOptions(options, invalid) { + if (!((options != null) && typeof options === "object" && invalid.length === 0)) { + throw new Bottleneck.prototype.BottleneckError("Bottleneck v2 takes a single object argument. Refer to https://github.com/SGrondin/bottleneck#upgrading-to-v2 if you're upgrading from Bottleneck v1."); + } + } + + ready() { + return this._store.ready; + } + + clients() { + return this._store.clients; + } + + channel() { + return `b_${this.id}`; + } + + channel_client() { + return `b_${this.id}_${this._store.clientId}`; + } + + publish(message) { + return this._store.__publish__(message); + } + + disconnect(flush = true) { + return this._store.__disconnect__(flush); + } + + chain(_limiter) { + this._limiter = _limiter; + return this; + } + + queued(priority) { + return this._queues.queued(priority); + } + + clusterQueued() { + return this._store.__queued__(); + } + + empty() { + return this.queued() === 0 && this._submitLock.isEmpty(); + } + + running() { + return this._store.__running__(); + } + + done() { + return this._store.__done__(); + } + + jobStatus(id) { + return this._states.jobStatus(id); + } + + jobs(status) { + return this._states.statusJobs(status); + } + + counts() { + return this._states.statusCounts(); + } + + _randomIndex() { + return Math.random().toString(36).slice(2); + } + + check(weight = 1) { + return this._store.__check__(weight); + } + + _clearGlobalState(index) { + if (this._scheduled[index] != null) { + clearTimeout(this._scheduled[index].expiration); + delete this._scheduled[index]; + return true; + } else { + return false; + } + } + + async _free(index, job, options, eventInfo) { + var e, running; + try { + ({running} = (await this._store.__free__(index, options.weight))); + this.Events.trigger("debug", `Freed ${options.id}`, eventInfo); + if (running === 0 && this.empty()) { + return this.Events.trigger("idle"); + } + } catch (error1) { + e = error1; + return this.Events.trigger("error", e); + } + } + + _run(index, job, wait) { + var clearGlobalState, free, run; + job.doRun(); + clearGlobalState = this._clearGlobalState.bind(this, index); + run = this._run.bind(this, index, job); + free = this._free.bind(this, index, job); + return this._scheduled[index] = { + timeout: setTimeout(() => { + return job.doExecute(this._limiter, clearGlobalState, run, free); + }, wait), + expiration: job.options.expiration != null ? setTimeout(function() { + return job.doExpire(clearGlobalState, run, free); + }, wait + job.options.expiration) : void 0, + job: job + }; + } + + _drainOne(capacity) { + return this._registerLock.schedule(() => { + var args, index, next, options, queue; + if (this.queued() === 0) { + return this.Promise.resolve(null); + } + queue = this._queues.getFirst(); + ({options, args} = next = queue.first()); + if ((capacity != null) && options.weight > capacity) { + return this.Promise.resolve(null); + } + this.Events.trigger("debug", `Draining ${options.id}`, {args, options}); + index = this._randomIndex(); + return this._store.__register__(index, options.weight, options.expiration).then(({success, wait, reservoir}) => { + var empty; + this.Events.trigger("debug", `Drained ${options.id}`, {success, args, options}); + if (success) { + queue.shift(); + empty = this.empty(); + if (empty) { + this.Events.trigger("empty"); + } + if (reservoir === 0) { + this.Events.trigger("depleted", empty); + } + this._run(index, next, wait); + return this.Promise.resolve(options.weight); + } else { + return this.Promise.resolve(null); + } + }); + }); + } + + _drainAll(capacity, total = 0) { + return this._drainOne(capacity).then((drained) => { + var newCapacity; + if (drained != null) { + newCapacity = capacity != null ? capacity - drained : capacity; + return this._drainAll(newCapacity, total + drained); + } else { + return this.Promise.resolve(total); + } + }).catch((e) => { + return this.Events.trigger("error", e); + }); + } + + _dropAllQueued(message) { + return this._queues.shiftAll(function(job) { + return job.doDrop({message}); + }); + } + + stop(options = {}) { + var done, waitForExecuting; + options = parser$5.load(options, this.stopDefaults); + waitForExecuting = (at) => { + var finished; + finished = () => { + var counts; + counts = this._states.counts; + return (counts[0] + counts[1] + counts[2] + counts[3]) === at; + }; + return new this.Promise((resolve, reject) => { + if (finished()) { + return resolve(); + } else { + return this.on("done", () => { + if (finished()) { + this.removeAllListeners("done"); + return resolve(); + } + }); + } + }); + }; + done = options.dropWaitingJobs ? (this._run = function(index, next) { + return next.doDrop({ + message: options.dropErrorMessage + }); + }, this._drainOne = () => { + return this.Promise.resolve(null); + }, this._registerLock.schedule(() => { + return this._submitLock.schedule(() => { + var k, ref, v; + ref = this._scheduled; + for (k in ref) { + v = ref[k]; + if (this.jobStatus(v.job.options.id) === "RUNNING") { + clearTimeout(v.timeout); + clearTimeout(v.expiration); + v.job.doDrop({ + message: options.dropErrorMessage + }); + } + } + this._dropAllQueued(options.dropErrorMessage); + return waitForExecuting(0); + }); + })) : this.schedule({ + priority: NUM_PRIORITIES$1 - 1, + weight: 0 + }, () => { + return waitForExecuting(1); + }); + this._receive = function(job) { + return job._reject(new Bottleneck.prototype.BottleneckError(options.enqueueErrorMessage)); + }; + this.stop = () => { + return this.Promise.reject(new Bottleneck.prototype.BottleneckError("stop() has already been called")); + }; + return done; + } + + async _addToQueue(job) { + var args, blocked, error, options, reachedHWM, shifted, strategy; + ({args, options} = job); + try { + ({reachedHWM, blocked, strategy} = (await this._store.__submit__(this.queued(), options.weight))); + } catch (error1) { + error = error1; + this.Events.trigger("debug", `Could not queue ${options.id}`, {args, options, error}); + job.doDrop({error}); + return false; + } + if (blocked) { + job.doDrop(); + return true; + } else if (reachedHWM) { + shifted = strategy === Bottleneck.prototype.strategy.LEAK ? this._queues.shiftLastFrom(options.priority) : strategy === Bottleneck.prototype.strategy.OVERFLOW_PRIORITY ? this._queues.shiftLastFrom(options.priority + 1) : strategy === Bottleneck.prototype.strategy.OVERFLOW ? job : void 0; + if (shifted != null) { + shifted.doDrop(); + } + if ((shifted == null) || strategy === Bottleneck.prototype.strategy.OVERFLOW) { + if (shifted == null) { + job.doDrop(); + } + return reachedHWM; + } + } + job.doQueue(reachedHWM, blocked); + this._queues.push(job); + await this._drainAll(); + return reachedHWM; + } + + _receive(job) { + if (this._states.jobStatus(job.options.id) != null) { + job._reject(new Bottleneck.prototype.BottleneckError(`A job with the same id already exists (id=${job.options.id})`)); + return false; + } else { + job.doReceive(); + return this._submitLock.schedule(this._addToQueue, job); + } + } + + submit(...args) { + var cb, fn, job, options, ref, ref1, task; + if (typeof args[0] === "function") { + ref = args, [fn, ...args] = ref, [cb] = splice.call(args, -1); + options = parser$5.load({}, this.jobDefaults); + } else { + ref1 = args, [options, fn, ...args] = ref1, [cb] = splice.call(args, -1); + options = parser$5.load(options, this.jobDefaults); + } + task = (...args) => { + return new this.Promise(function(resolve, reject) { + return fn(...args, function(...args) { + return (args[0] != null ? reject : resolve)(args); + }); + }); + }; + job = new Job$1(task, args, options, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise); + job.promise.then(function(args) { + return typeof cb === "function" ? cb(...args) : void 0; + }).catch(function(args) { + if (Array.isArray(args)) { + return typeof cb === "function" ? cb(...args) : void 0; + } else { + return typeof cb === "function" ? cb(args) : void 0; + } + }); + return this._receive(job); + } + + schedule(...args) { + var job, options, task; + if (typeof args[0] === "function") { + [task, ...args] = args; + options = {}; + } else { + [options, task, ...args] = args; + } + job = new Job$1(task, args, options, this.jobDefaults, this.rejectOnDrop, this.Events, this._states, this.Promise); + this._receive(job); + return job.promise; + } + + wrap(fn) { + var schedule, wrapped; + schedule = this.schedule.bind(this); + wrapped = function(...args) { + return schedule(fn.bind(this), ...args); + }; + wrapped.withOptions = function(options, ...args) { + return schedule(options, fn, ...args); + }; + return wrapped; + } + + async updateSettings(options = {}) { + await this._store.__updateSettings__(parser$5.overwrite(options, this.storeDefaults)); + parser$5.overwrite(options, this.instanceDefaults, this); + return this; + } + + currentReservoir() { + return this._store.__currentReservoir__(); + } + + incrementReservoir(incr = 0) { + return this._store.__incrementReservoir__(incr); + } + + } + Bottleneck.default = Bottleneck; + + Bottleneck.Events = Events$4; + + Bottleneck.version = Bottleneck.prototype.version = require$$8.version; + + Bottleneck.strategy = Bottleneck.prototype.strategy = { + LEAK: 1, + OVERFLOW: 2, + OVERFLOW_PRIORITY: 4, + BLOCK: 3 + }; + + Bottleneck.BottleneckError = Bottleneck.prototype.BottleneckError = BottleneckError_1; + + Bottleneck.Group = Bottleneck.prototype.Group = Group_1; + + Bottleneck.RedisConnection = Bottleneck.prototype.RedisConnection = require$$2; + + Bottleneck.IORedisConnection = Bottleneck.prototype.IORedisConnection = require$$3; + + Bottleneck.Batcher = Bottleneck.prototype.Batcher = Batcher_1; + + Bottleneck.prototype.jobDefaults = { + priority: DEFAULT_PRIORITY$1, + weight: 1, + expiration: null, + id: "" + }; + + Bottleneck.prototype.storeDefaults = { + maxConcurrent: null, + minTime: 0, + highWater: null, + strategy: Bottleneck.prototype.strategy.LEAK, + penalty: null, + reservoir: null, + reservoirRefreshInterval: null, + reservoirRefreshAmount: null, + reservoirIncreaseInterval: null, + reservoirIncreaseAmount: null, + reservoirIncreaseMaximum: null + }; + + Bottleneck.prototype.localStoreDefaults = { + Promise: Promise, + timeout: null, + heartbeatInterval: 250 + }; + + Bottleneck.prototype.redisStoreDefaults = { + Promise: Promise, + timeout: null, + heartbeatInterval: 5000, + clientTimeout: 10000, + Redis: null, + clientOptions: {}, + clusterNodes: null, + clearDatastore: false, + connection: null + }; + + Bottleneck.prototype.instanceDefaults = { + datastore: "local", + connection: null, + id: "", + rejectOnDrop: true, + trackDoneStatus: false, + Promise: Promise + }; + + Bottleneck.prototype.stopDefaults = { + enqueueErrorMessage: "This limiter has been stopped and cannot accept new jobs.", + dropWaitingJobs: true, + dropErrorMessage: "This limiter has been stopped." + }; + + return Bottleneck; + + }).call(commonjsGlobal); + + var Bottleneck_1 = Bottleneck; + + var lib = Bottleneck_1; + + return lib; + +}))); + + +/***/ }), + +/***/ 8932: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +class Deprecation extends Error { + constructor(message) { + super(message); // Maintains proper stack trace (only available on V8) + + /* istanbul ignore next */ + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + + this.name = 'Deprecation'; + } + +} + +exports.Deprecation = Deprecation; + + +/***/ }), + +/***/ 4697: +/***/ ((module, exports) => { + +"use strict"; +/** + * @author Toru Nagashima + * @copyright 2015 Toru Nagashima. All rights reserved. + * See LICENSE file in root directory for full license. + */ + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +/** + * @typedef {object} PrivateData + * @property {EventTarget} eventTarget The event target. + * @property {{type:string}} event The original event object. + * @property {number} eventPhase The current event phase. + * @property {EventTarget|null} currentTarget The current event target. + * @property {boolean} canceled The flag to prevent default. + * @property {boolean} stopped The flag to stop propagation. + * @property {boolean} immediateStopped The flag to stop propagation immediately. + * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null. + * @property {number} timeStamp The unix time. + * @private + */ + +/** + * Private data for event wrappers. + * @type {WeakMap} + * @private + */ +const privateData = new WeakMap(); + +/** + * Cache for wrapper classes. + * @type {WeakMap} + * @private + */ +const wrappers = new WeakMap(); + +/** + * Get private data. + * @param {Event} event The event object to get private data. + * @returns {PrivateData} The private data of the event. + * @private + */ +function pd(event) { + const retv = privateData.get(event); + console.assert( + retv != null, + "'this' is expected an Event object, but got", + event + ); + return retv +} + +/** + * https://dom.spec.whatwg.org/#set-the-canceled-flag + * @param data {PrivateData} private data. + */ +function setCancelFlag(data) { + if (data.passiveListener != null) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error( + "Unable to preventDefault inside passive event listener invocation.", + data.passiveListener + ); + } + return + } + if (!data.event.cancelable) { + return + } + + data.canceled = true; + if (typeof data.event.preventDefault === "function") { + data.event.preventDefault(); + } +} + +/** + * @see https://dom.spec.whatwg.org/#interface-event + * @private + */ +/** + * The event wrapper. + * @constructor + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Event|{type:string}} event The original event to wrap. + */ +function Event(eventTarget, event) { + privateData.set(this, { + eventTarget, + event, + eventPhase: 2, + currentTarget: eventTarget, + canceled: false, + stopped: false, + immediateStopped: false, + passiveListener: null, + timeStamp: event.timeStamp || Date.now(), + }); + + // https://heycam.github.io/webidl/#Unforgeable + Object.defineProperty(this, "isTrusted", { value: false, enumerable: true }); + + // Define accessors + const keys = Object.keys(event); + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in this)) { + Object.defineProperty(this, key, defineRedirectDescriptor(key)); + } + } +} + +// Should be enumerable, but class methods are not enumerable. +Event.prototype = { + /** + * The type of this event. + * @type {string} + */ + get type() { + return pd(this).event.type + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get target() { + return pd(this).eventTarget + }, + + /** + * The target of this event. + * @type {EventTarget} + */ + get currentTarget() { + return pd(this).currentTarget + }, + + /** + * @returns {EventTarget[]} The composed path of this event. + */ + composedPath() { + const currentTarget = pd(this).currentTarget; + if (currentTarget == null) { + return [] + } + return [currentTarget] + }, + + /** + * Constant of NONE. + * @type {number} + */ + get NONE() { + return 0 + }, + + /** + * Constant of CAPTURING_PHASE. + * @type {number} + */ + get CAPTURING_PHASE() { + return 1 + }, + + /** + * Constant of AT_TARGET. + * @type {number} + */ + get AT_TARGET() { + return 2 + }, + + /** + * Constant of BUBBLING_PHASE. + * @type {number} + */ + get BUBBLING_PHASE() { + return 3 + }, + + /** + * The target of this event. + * @type {number} + */ + get eventPhase() { + return pd(this).eventPhase + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopPropagation() { + const data = pd(this); + + data.stopped = true; + if (typeof data.event.stopPropagation === "function") { + data.event.stopPropagation(); + } + }, + + /** + * Stop event bubbling. + * @returns {void} + */ + stopImmediatePropagation() { + const data = pd(this); + + data.stopped = true; + data.immediateStopped = true; + if (typeof data.event.stopImmediatePropagation === "function") { + data.event.stopImmediatePropagation(); + } + }, + + /** + * The flag to be bubbling. + * @type {boolean} + */ + get bubbles() { + return Boolean(pd(this).event.bubbles) + }, + + /** + * The flag to be cancelable. + * @type {boolean} + */ + get cancelable() { + return Boolean(pd(this).event.cancelable) + }, + + /** + * Cancel this event. + * @returns {void} + */ + preventDefault() { + setCancelFlag(pd(this)); + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + */ + get defaultPrevented() { + return pd(this).canceled + }, + + /** + * The flag to be composed. + * @type {boolean} + */ + get composed() { + return Boolean(pd(this).event.composed) + }, + + /** + * The unix time of this event. + * @type {number} + */ + get timeStamp() { + return pd(this).timeStamp + }, + + /** + * The target of this event. + * @type {EventTarget} + * @deprecated + */ + get srcElement() { + return pd(this).eventTarget + }, + + /** + * The flag to stop event bubbling. + * @type {boolean} + * @deprecated + */ + get cancelBubble() { + return pd(this).stopped + }, + set cancelBubble(value) { + if (!value) { + return + } + const data = pd(this); + + data.stopped = true; + if (typeof data.event.cancelBubble === "boolean") { + data.event.cancelBubble = true; + } + }, + + /** + * The flag to indicate cancellation state. + * @type {boolean} + * @deprecated + */ + get returnValue() { + return !pd(this).canceled + }, + set returnValue(value) { + if (!value) { + setCancelFlag(pd(this)); + } + }, + + /** + * Initialize this event object. But do nothing under event dispatching. + * @param {string} type The event type. + * @param {boolean} [bubbles=false] The flag to be possible to bubble up. + * @param {boolean} [cancelable=false] The flag to be possible to cancel. + * @deprecated + */ + initEvent() { + // Do nothing. + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(Event.prototype, "constructor", { + value: Event, + configurable: true, + writable: true, +}); + +// Ensure `event instanceof window.Event` is `true`. +if (typeof window !== "undefined" && typeof window.Event !== "undefined") { + Object.setPrototypeOf(Event.prototype, window.Event.prototype); + + // Make association for wrappers. + wrappers.set(window.Event.prototype, Event); +} + +/** + * Get the property descriptor to redirect a given property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to redirect the property. + * @private + */ +function defineRedirectDescriptor(key) { + return { + get() { + return pd(this).event[key] + }, + set(value) { + pd(this).event[key] = value; + }, + configurable: true, + enumerable: true, + } +} + +/** + * Get the property descriptor to call a given method property. + * @param {string} key Property name to define property descriptor. + * @returns {PropertyDescriptor} The property descriptor to call the method property. + * @private + */ +function defineCallDescriptor(key) { + return { + value() { + const event = pd(this).event; + return event[key].apply(event, arguments) + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define new wrapper class. + * @param {Function} BaseEvent The base wrapper class. + * @param {Object} proto The prototype of the original event. + * @returns {Function} The defined wrapper class. + * @private + */ +function defineWrapper(BaseEvent, proto) { + const keys = Object.keys(proto); + if (keys.length === 0) { + return BaseEvent + } + + /** CustomEvent */ + function CustomEvent(eventTarget, event) { + BaseEvent.call(this, eventTarget, event); + } + + CustomEvent.prototype = Object.create(BaseEvent.prototype, { + constructor: { value: CustomEvent, configurable: true, writable: true }, + }); + + // Define accessors. + for (let i = 0; i < keys.length; ++i) { + const key = keys[i]; + if (!(key in BaseEvent.prototype)) { + const descriptor = Object.getOwnPropertyDescriptor(proto, key); + const isFunc = typeof descriptor.value === "function"; + Object.defineProperty( + CustomEvent.prototype, + key, + isFunc + ? defineCallDescriptor(key) + : defineRedirectDescriptor(key) + ); + } + } + + return CustomEvent +} + +/** + * Get the wrapper class of a given prototype. + * @param {Object} proto The prototype of the original event to get its wrapper. + * @returns {Function} The wrapper class. + * @private + */ +function getWrapper(proto) { + if (proto == null || proto === Object.prototype) { + return Event + } + + let wrapper = wrappers.get(proto); + if (wrapper == null) { + wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto); + wrappers.set(proto, wrapper); + } + return wrapper +} + +/** + * Wrap a given event to management a dispatching. + * @param {EventTarget} eventTarget The event target of this dispatching. + * @param {Object} event The event to wrap. + * @returns {Event} The wrapper instance. + * @private + */ +function wrapEvent(eventTarget, event) { + const Wrapper = getWrapper(Object.getPrototypeOf(event)); + return new Wrapper(eventTarget, event) +} + +/** + * Get the immediateStopped flag of a given event. + * @param {Event} event The event to get. + * @returns {boolean} The flag to stop propagation immediately. + * @private + */ +function isStopped(event) { + return pd(event).immediateStopped +} + +/** + * Set the current event phase of a given event. + * @param {Event} event The event to set current target. + * @param {number} eventPhase New event phase. + * @returns {void} + * @private + */ +function setEventPhase(event, eventPhase) { + pd(event).eventPhase = eventPhase; +} + +/** + * Set the current target of a given event. + * @param {Event} event The event to set current target. + * @param {EventTarget|null} currentTarget New current target. + * @returns {void} + * @private + */ +function setCurrentTarget(event, currentTarget) { + pd(event).currentTarget = currentTarget; +} + +/** + * Set a passive listener of a given event. + * @param {Event} event The event to set current target. + * @param {Function|null} passiveListener New passive listener. + * @returns {void} + * @private + */ +function setPassiveListener(event, passiveListener) { + pd(event).passiveListener = passiveListener; +} + +/** + * @typedef {object} ListenerNode + * @property {Function} listener + * @property {1|2|3} listenerType + * @property {boolean} passive + * @property {boolean} once + * @property {ListenerNode|null} next + * @private + */ + +/** + * @type {WeakMap>} + * @private + */ +const listenersMap = new WeakMap(); + +// Listener types +const CAPTURE = 1; +const BUBBLE = 2; +const ATTRIBUTE = 3; + +/** + * Check whether a given value is an object or not. + * @param {any} x The value to check. + * @returns {boolean} `true` if the value is an object. + */ +function isObject(x) { + return x !== null && typeof x === "object" //eslint-disable-line no-restricted-syntax +} + +/** + * Get listeners. + * @param {EventTarget} eventTarget The event target to get. + * @returns {Map} The listeners. + * @private + */ +function getListeners(eventTarget) { + const listeners = listenersMap.get(eventTarget); + if (listeners == null) { + throw new TypeError( + "'this' is expected an EventTarget object, but got another value." + ) + } + return listeners +} + +/** + * Get the property descriptor for the event attribute of a given event. + * @param {string} eventName The event name to get property descriptor. + * @returns {PropertyDescriptor} The property descriptor. + * @private + */ +function defineEventAttributeDescriptor(eventName) { + return { + get() { + const listeners = getListeners(this); + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + return node.listener + } + node = node.next; + } + return null + }, + + set(listener) { + if (typeof listener !== "function" && !isObject(listener)) { + listener = null; // eslint-disable-line no-param-reassign + } + const listeners = getListeners(this); + + // Traverse to the tail while removing old value. + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if (node.listenerType === ATTRIBUTE) { + // Remove old value. + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + node = node.next; + } + + // Add new value. + if (listener !== null) { + const newNode = { + listener, + listenerType: ATTRIBUTE, + passive: false, + once: false, + next: null, + }; + if (prev === null) { + listeners.set(eventName, newNode); + } else { + prev.next = newNode; + } + } + }, + configurable: true, + enumerable: true, + } +} + +/** + * Define an event attribute (e.g. `eventTarget.onclick`). + * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite. + * @param {string} eventName The event name to define. + * @returns {void} + */ +function defineEventAttribute(eventTargetPrototype, eventName) { + Object.defineProperty( + eventTargetPrototype, + `on${eventName}`, + defineEventAttributeDescriptor(eventName) + ); +} + +/** + * Define a custom EventTarget with event attributes. + * @param {string[]} eventNames Event names for event attributes. + * @returns {EventTarget} The custom EventTarget. + * @private + */ +function defineCustomEventTarget(eventNames) { + /** CustomEventTarget */ + function CustomEventTarget() { + EventTarget.call(this); + } + + CustomEventTarget.prototype = Object.create(EventTarget.prototype, { + constructor: { + value: CustomEventTarget, + configurable: true, + writable: true, + }, + }); + + for (let i = 0; i < eventNames.length; ++i) { + defineEventAttribute(CustomEventTarget.prototype, eventNames[i]); + } + + return CustomEventTarget +} + +/** + * EventTarget. + * + * - This is constructor if no arguments. + * - This is a function which returns a CustomEventTarget constructor if there are arguments. + * + * For example: + * + * class A extends EventTarget {} + * class B extends EventTarget("message") {} + * class C extends EventTarget("message", "error") {} + * class D extends EventTarget(["message", "error"]) {} + */ +function EventTarget() { + /*eslint-disable consistent-return */ + if (this instanceof EventTarget) { + listenersMap.set(this, new Map()); + return + } + if (arguments.length === 1 && Array.isArray(arguments[0])) { + return defineCustomEventTarget(arguments[0]) + } + if (arguments.length > 0) { + const types = new Array(arguments.length); + for (let i = 0; i < arguments.length; ++i) { + types[i] = arguments[i]; + } + return defineCustomEventTarget(types) + } + throw new TypeError("Cannot call a class as a function") + /*eslint-enable consistent-return */ +} + +// Should be enumerable, but class methods are not enumerable. +EventTarget.prototype = { + /** + * Add a given listener to this event target. + * @param {string} eventName The event name to add. + * @param {Function} listener The listener to add. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + addEventListener(eventName, listener, options) { + if (listener == null) { + return + } + if (typeof listener !== "function" && !isObject(listener)) { + throw new TypeError("'listener' should be a function or an object.") + } + + const listeners = getListeners(this); + const optionsIsObj = isObject(options); + const capture = optionsIsObj + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + const newNode = { + listener, + listenerType, + passive: optionsIsObj && Boolean(options.passive), + once: optionsIsObj && Boolean(options.once), + next: null, + }; + + // Set it as the first node if the first node is null. + let node = listeners.get(eventName); + if (node === undefined) { + listeners.set(eventName, newNode); + return + } + + // Traverse to the tail while checking duplication.. + let prev = null; + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + // Should ignore duplication. + return + } + prev = node; + node = node.next; + } + + // Add it. + prev.next = newNode; + }, + + /** + * Remove a given listener from this event target. + * @param {string} eventName The event name to remove. + * @param {Function} listener The listener to remove. + * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener. + * @returns {void} + */ + removeEventListener(eventName, listener, options) { + if (listener == null) { + return + } + + const listeners = getListeners(this); + const capture = isObject(options) + ? Boolean(options.capture) + : Boolean(options); + const listenerType = capture ? CAPTURE : BUBBLE; + + let prev = null; + let node = listeners.get(eventName); + while (node != null) { + if ( + node.listener === listener && + node.listenerType === listenerType + ) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + return + } + + prev = node; + node = node.next; + } + }, + + /** + * Dispatch a given event. + * @param {Event|{type:string}} event The event to dispatch. + * @returns {boolean} `false` if canceled. + */ + dispatchEvent(event) { + if (event == null || typeof event.type !== "string") { + throw new TypeError('"event.type" should be a string.') + } + + // If listeners aren't registered, terminate. + const listeners = getListeners(this); + const eventName = event.type; + let node = listeners.get(eventName); + if (node == null) { + return true + } + + // Since we cannot rewrite several properties, so wrap object. + const wrappedEvent = wrapEvent(this, event); + + // This doesn't process capturing phase and bubbling phase. + // This isn't participating in a tree. + let prev = null; + while (node != null) { + // Remove this listener if it's once + if (node.once) { + if (prev !== null) { + prev.next = node.next; + } else if (node.next !== null) { + listeners.set(eventName, node.next); + } else { + listeners.delete(eventName); + } + } else { + prev = node; + } + + // Call this listener + setPassiveListener( + wrappedEvent, + node.passive ? node.listener : null + ); + if (typeof node.listener === "function") { + try { + node.listener.call(this, wrappedEvent); + } catch (err) { + if ( + typeof console !== "undefined" && + typeof console.error === "function" + ) { + console.error(err); + } + } + } else if ( + node.listenerType !== ATTRIBUTE && + typeof node.listener.handleEvent === "function" + ) { + node.listener.handleEvent(wrappedEvent); + } + + // Break if `event.stopImmediatePropagation` was called. + if (isStopped(wrappedEvent)) { + break + } + + node = node.next; + } + setPassiveListener(wrappedEvent, null); + setEventPhase(wrappedEvent, 0); + setCurrentTarget(wrappedEvent, null); + + return !wrappedEvent.defaultPrevented + }, +}; + +// `constructor` is not enumerable. +Object.defineProperty(EventTarget.prototype, "constructor", { + value: EventTarget, + configurable: true, + writable: true, +}); + +// Ensure `eventTarget instanceof window.EventTarget` is `true`. +if ( + typeof window !== "undefined" && + typeof window.EventTarget !== "undefined" +) { + Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype); +} + +exports.defineEventAttribute = defineEventAttribute; +exports.EventTarget = EventTarget; +exports["default"] = EventTarget; + +module.exports = EventTarget +module.exports.EventTarget = module.exports["default"] = EventTarget +module.exports.defineEventAttribute = defineEventAttribute +//# sourceMappingURL=event-target-shim.js.map + + +/***/ }), + +/***/ 6993: +/***/ (function(__unused_webpack_module, exports) { + +/** + * @license + * web-streams-polyfill v4.0.0-beta.3 + * Copyright 2021 Mattias Buelens, Diwank Singh Tomer and other contributors. + * This code is released under the MIT license. + * SPDX-License-Identifier: MIT + */ +!function(e,t){ true?t(exports):0}(this,(function(e){"use strict";const t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?Symbol:e=>`Symbol(${e})`;function r(){}function o(e){return"object"==typeof e&&null!==e||"function"==typeof e}const n=r;function a(e,t){try{Object.defineProperty(e,"name",{value:t,configurable:!0})}catch(e){}}const i=Promise,l=Promise.prototype.then,s=Promise.resolve.bind(i),u=Promise.reject.bind(i);function c(e){return new i(e)}function d(e){return s(e)}function f(e){return u(e)}function b(e,t,r){return l.call(e,t,r)}function h(e,t,r){b(b(e,t,r),void 0,n)}function _(e,t){h(e,t)}function p(e,t){h(e,void 0,t)}function m(e,t,r){return b(e,t,r)}function y(e){b(e,void 0,n)}let g=e=>{if("function"==typeof queueMicrotask)g=queueMicrotask;else{const e=d(void 0);g=t=>b(e,t)}return g(e)};function S(e,t,r){if("function"!=typeof e)throw new TypeError("Argument is not a function");return Function.prototype.apply.call(e,t,r)}function w(e,t,r){try{return d(S(e,t,r))}catch(e){return f(e)}}class v{constructor(){this._cursor=0,this._size=0,this._front={_elements:[],_next:void 0},this._back=this._front,this._cursor=0,this._size=0}get length(){return this._size}push(e){const t=this._back;let r=t;16383===t._elements.length&&(r={_elements:[],_next:void 0}),t._elements.push(e),r!==t&&(this._back=r,t._next=r),++this._size}shift(){const e=this._front;let t=e;const r=this._cursor;let o=r+1;const n=e._elements,a=n[r];return 16384===o&&(t=e._next,o=0),--this._size,this._cursor=o,e!==t&&(this._front=t),n[r]=void 0,a}forEach(e){let t=this._cursor,r=this._front,o=r._elements;for(;!(t===o.length&&void 0===r._next||t===o.length&&(r=r._next,o=r._elements,t=0,0===o.length));)e(o[t]),++t}peek(){const e=this._front,t=this._cursor;return e._elements[t]}}const R=t("[[AbortSteps]]"),T=t("[[ErrorSteps]]"),q=t("[[CancelSteps]]"),C=t("[[PullSteps]]"),P=t("[[ReleaseSteps]]");function E(e,t){e._ownerReadableStream=t,t._reader=e,"readable"===t._state?B(e):"closed"===t._state?function(e){B(e),z(e)}(e):A(e,t._storedError)}function W(e,t){return Xt(e._ownerReadableStream,t)}function O(e){const t=e._ownerReadableStream;"readable"===t._state?j(e,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")):function(e,t){A(e,t)}(e,new TypeError("Reader was released and can no longer be used to monitor the stream's closedness")),t._readableStreamController[P](),t._reader=void 0,e._ownerReadableStream=void 0}function k(e){return new TypeError("Cannot "+e+" a stream using a released reader")}function B(e){e._closedPromise=c(((t,r)=>{e._closedPromise_resolve=t,e._closedPromise_reject=r}))}function A(e,t){B(e),j(e,t)}function j(e,t){void 0!==e._closedPromise_reject&&(y(e._closedPromise),e._closedPromise_reject(t),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0)}function z(e){void 0!==e._closedPromise_resolve&&(e._closedPromise_resolve(void 0),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0)}const L=Number.isFinite||function(e){return"number"==typeof e&&isFinite(e)},F=Math.trunc||function(e){return e<0?Math.ceil(e):Math.floor(e)};function D(e,t){if(void 0!==e&&("object"!=typeof(r=e)&&"function"!=typeof r))throw new TypeError(`${t} is not an object.`);var r}function I(e,t){if("function"!=typeof e)throw new TypeError(`${t} is not a function.`)}function $(e,t){if(!function(e){return"object"==typeof e&&null!==e||"function"==typeof e}(e))throw new TypeError(`${t} is not an object.`)}function M(e,t,r){if(void 0===e)throw new TypeError(`Parameter ${t} is required in '${r}'.`)}function Y(e,t,r){if(void 0===e)throw new TypeError(`${t} is required in '${r}'.`)}function Q(e){return Number(e)}function N(e){return 0===e?0:e}function x(e,t){const r=Number.MAX_SAFE_INTEGER;let o=Number(e);if(o=N(o),!L(o))throw new TypeError(`${t} is not a finite number`);if(o=function(e){return N(F(e))}(o),o<0||o>r)throw new TypeError(`${t} is outside the accepted range of 0 to ${r}, inclusive`);return L(o)&&0!==o?o:0}function H(e){if(!o(e))return!1;if("function"!=typeof e.getReader)return!1;try{return"boolean"==typeof e.locked}catch(e){return!1}}function V(e){if(!o(e))return!1;if("function"!=typeof e.getWriter)return!1;try{return"boolean"==typeof e.locked}catch(e){return!1}}function U(e,t){if(!Ut(e))throw new TypeError(`${t} is not a ReadableStream.`)}function G(e,t){e._reader._readRequests.push(t)}function X(e,t,r){const o=e._reader._readRequests.shift();r?o._closeSteps():o._chunkSteps(t)}function J(e){return e._reader._readRequests.length}function K(e){const t=e._reader;return void 0!==t&&!!Z(t)}class ReadableStreamDefaultReader{constructor(e){if(M(e,1,"ReadableStreamDefaultReader"),U(e,"First parameter"),Gt(e))throw new TypeError("This stream has already been locked for exclusive reading by another reader");E(this,e),this._readRequests=new v}get closed(){return Z(this)?this._closedPromise:f(te("closed"))}cancel(e){return Z(this)?void 0===this._ownerReadableStream?f(k("cancel")):W(this,e):f(te("cancel"))}read(){if(!Z(this))return f(te("read"));if(void 0===this._ownerReadableStream)return f(k("read from"));let e,t;const r=c(((r,o)=>{e=r,t=o}));return function(e,t){const r=e._ownerReadableStream;r._disturbed=!0,"closed"===r._state?t._closeSteps():"errored"===r._state?t._errorSteps(r._storedError):r._readableStreamController[C](t)}(this,{_chunkSteps:t=>e({value:t,done:!1}),_closeSteps:()=>e({value:void 0,done:!0}),_errorSteps:e=>t(e)}),r}releaseLock(){if(!Z(this))throw te("releaseLock");void 0!==this._ownerReadableStream&&function(e){O(e);const t=new TypeError("Reader was released");ee(e,t)}(this)}}function Z(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_readRequests")&&e instanceof ReadableStreamDefaultReader)}function ee(e,t){const r=e._readRequests;e._readRequests=new v,r.forEach((e=>{e._errorSteps(t)}))}function te(e){return new TypeError(`ReadableStreamDefaultReader.prototype.${e} can only be used on a ReadableStreamDefaultReader`)}Object.defineProperties(ReadableStreamDefaultReader.prototype,{cancel:{enumerable:!0},read:{enumerable:!0},releaseLock:{enumerable:!0},closed:{enumerable:!0}}),a(ReadableStreamDefaultReader.prototype.cancel,"cancel"),a(ReadableStreamDefaultReader.prototype.read,"read"),a(ReadableStreamDefaultReader.prototype.releaseLock,"releaseLock"),"symbol"==typeof t.toStringTag&&Object.defineProperty(ReadableStreamDefaultReader.prototype,t.toStringTag,{value:"ReadableStreamDefaultReader",configurable:!0});class re{constructor(e,t){this._ongoingPromise=void 0,this._isFinished=!1,this._reader=e,this._preventCancel=t}next(){const e=()=>this._nextSteps();return this._ongoingPromise=this._ongoingPromise?m(this._ongoingPromise,e,e):e(),this._ongoingPromise}return(e){const t=()=>this._returnSteps(e);return this._ongoingPromise?m(this._ongoingPromise,t,t):t()}_nextSteps(){if(this._isFinished)return Promise.resolve({value:void 0,done:!0});const e=this._reader;return void 0===e?f(k("iterate")):b(e.read(),(e=>{var t;return this._ongoingPromise=void 0,e.done&&(this._isFinished=!0,null===(t=this._reader)||void 0===t||t.releaseLock(),this._reader=void 0),e}),(e=>{var t;throw this._ongoingPromise=void 0,this._isFinished=!0,null===(t=this._reader)||void 0===t||t.releaseLock(),this._reader=void 0,e}))}_returnSteps(e){if(this._isFinished)return Promise.resolve({value:e,done:!0});this._isFinished=!0;const t=this._reader;if(void 0===t)return f(k("finish iterating"));if(this._reader=void 0,!this._preventCancel){const r=t.cancel(e);return t.releaseLock(),m(r,(()=>({value:e,done:!0})))}return t.releaseLock(),d({value:e,done:!0})}}const oe={next(){return ne(this)?this._asyncIteratorImpl.next():f(ae("next"))},return(e){return ne(this)?this._asyncIteratorImpl.return(e):f(ae("return"))}};function ne(e){if(!o(e))return!1;if(!Object.prototype.hasOwnProperty.call(e,"_asyncIteratorImpl"))return!1;try{return e._asyncIteratorImpl instanceof re}catch(e){return!1}}function ae(e){return new TypeError(`ReadableStreamAsyncIterator.${e} can only be used on a ReadableSteamAsyncIterator`)}"symbol"==typeof t.asyncIterator&&Object.defineProperty(oe,t.asyncIterator,{value(){return this},writable:!0,configurable:!0});const ie=Number.isNaN||function(e){return e!=e};function le(e,t,r,o,n){new Uint8Array(e).set(new Uint8Array(r,o,n),t)}function se(e){const t=function(e,t,r){if(e.slice)return e.slice(t,r);const o=r-t,n=new ArrayBuffer(o);return le(n,0,e,t,o),n}(e.buffer,e.byteOffset,e.byteOffset+e.byteLength);return new Uint8Array(t)}function ue(e){const t=e._queue.shift();return e._queueTotalSize-=t.size,e._queueTotalSize<0&&(e._queueTotalSize=0),t.value}function ce(e,t,r){if("number"!=typeof(o=r)||ie(o)||o<0||r===1/0)throw new RangeError("Size must be a finite, non-NaN, non-negative number.");var o;e._queue.push({value:t,size:r}),e._queueTotalSize+=r}function de(e){e._queue=new v,e._queueTotalSize=0}class ReadableStreamBYOBRequest{constructor(){throw new TypeError("Illegal constructor")}get view(){if(!be(this))throw Ae("view");return this._view}respond(e){if(!be(this))throw Ae("respond");if(M(e,1,"respond"),e=x(e,"First parameter"),void 0===this._associatedReadableByteStreamController)throw new TypeError("This BYOB request has been invalidated");this._view.buffer,function(e,t){const r=e._pendingPullIntos.peek();if("closed"===e._controlledReadableByteStream._state){if(0!==t)throw new TypeError("bytesWritten must be 0 when calling respond() on a closed stream")}else{if(0===t)throw new TypeError("bytesWritten must be greater than 0 when calling respond() on a readable stream");if(r.bytesFilled+t>r.byteLength)throw new RangeError("bytesWritten out of range")}r.buffer=r.buffer,Ce(e,t)}(this._associatedReadableByteStreamController,e)}respondWithNewView(e){if(!be(this))throw Ae("respondWithNewView");if(M(e,1,"respondWithNewView"),!ArrayBuffer.isView(e))throw new TypeError("You can only respond with array buffer views");if(void 0===this._associatedReadableByteStreamController)throw new TypeError("This BYOB request has been invalidated");e.buffer,function(e,t){const r=e._pendingPullIntos.peek();if("closed"===e._controlledReadableByteStream._state){if(0!==t.byteLength)throw new TypeError("The view's length must be 0 when calling respondWithNewView() on a closed stream")}else if(0===t.byteLength)throw new TypeError("The view's length must be greater than 0 when calling respondWithNewView() on a readable stream");if(r.byteOffset+r.bytesFilled!==t.byteOffset)throw new RangeError("The region specified by view does not match byobRequest");if(r.bufferByteLength!==t.buffer.byteLength)throw new RangeError("The buffer of view has different capacity than byobRequest");if(r.bytesFilled+t.byteLength>r.byteLength)throw new RangeError("The region specified by view is larger than byobRequest");const o=t.byteLength;r.buffer=t.buffer,Ce(e,o)}(this._associatedReadableByteStreamController,e)}}Object.defineProperties(ReadableStreamBYOBRequest.prototype,{respond:{enumerable:!0},respondWithNewView:{enumerable:!0},view:{enumerable:!0}}),a(ReadableStreamBYOBRequest.prototype.respond,"respond"),a(ReadableStreamBYOBRequest.prototype.respondWithNewView,"respondWithNewView"),"symbol"==typeof t.toStringTag&&Object.defineProperty(ReadableStreamBYOBRequest.prototype,t.toStringTag,{value:"ReadableStreamBYOBRequest",configurable:!0});class ReadableByteStreamController{constructor(){throw new TypeError("Illegal constructor")}get byobRequest(){if(!fe(this))throw je("byobRequest");return function(e){if(null===e._byobRequest&&e._pendingPullIntos.length>0){const t=e._pendingPullIntos.peek(),r=new Uint8Array(t.buffer,t.byteOffset+t.bytesFilled,t.byteLength-t.bytesFilled),o=Object.create(ReadableStreamBYOBRequest.prototype);!function(e,t,r){e._associatedReadableByteStreamController=t,e._view=r}(o,e,r),e._byobRequest=o}return e._byobRequest}(this)}get desiredSize(){if(!fe(this))throw je("desiredSize");return ke(this)}close(){if(!fe(this))throw je("close");if(this._closeRequested)throw new TypeError("The stream has already been closed; do not close it again!");const e=this._controlledReadableByteStream._state;if("readable"!==e)throw new TypeError(`The stream (in ${e} state) is not in the readable state and cannot be closed`);!function(e){const t=e._controlledReadableByteStream;if(e._closeRequested||"readable"!==t._state)return;if(e._queueTotalSize>0)return void(e._closeRequested=!0);if(e._pendingPullIntos.length>0){if(e._pendingPullIntos.peek().bytesFilled>0){const t=new TypeError("Insufficient bytes to fill elements in the given buffer");throw We(e,t),t}}Ee(e),Jt(t)}(this)}enqueue(e){if(!fe(this))throw je("enqueue");if(M(e,1,"enqueue"),!ArrayBuffer.isView(e))throw new TypeError("chunk must be an array buffer view");if(0===e.byteLength)throw new TypeError("chunk must have non-zero byteLength");if(0===e.buffer.byteLength)throw new TypeError("chunk's buffer must have non-zero byteLength");if(this._closeRequested)throw new TypeError("stream is closed or draining");const t=this._controlledReadableByteStream._state;if("readable"!==t)throw new TypeError(`The stream (in ${t} state) is not in the readable state and cannot be enqueued to`);!function(e,t){const r=e._controlledReadableByteStream;if(e._closeRequested||"readable"!==r._state)return;const o=t.buffer,n=t.byteOffset,a=t.byteLength,i=o;if(e._pendingPullIntos.length>0){const t=e._pendingPullIntos.peek();t.buffer,0,Te(e),t.buffer=t.buffer,"none"===t.readerType&&Se(e,t)}if(K(r))if(function(e){const t=e._controlledReadableByteStream._reader;for(;t._readRequests.length>0;){if(0===e._queueTotalSize)return;Oe(e,t._readRequests.shift())}}(e),0===J(r))ye(e,i,n,a);else{e._pendingPullIntos.length>0&&Pe(e);X(r,new Uint8Array(i,n,a),!1)}else Fe(r)?(ye(e,i,n,a),qe(e)):ye(e,i,n,a);he(e)}(this,e)}error(e){if(!fe(this))throw je("error");We(this,e)}[q](e){_e(this),de(this);const t=this._cancelAlgorithm(e);return Ee(this),t}[C](e){const t=this._controlledReadableByteStream;if(this._queueTotalSize>0)return void Oe(this,e);const r=this._autoAllocateChunkSize;if(void 0!==r){let t;try{t=new ArrayBuffer(r)}catch(t){return void e._errorSteps(t)}const o={buffer:t,bufferByteLength:r,byteOffset:0,byteLength:r,bytesFilled:0,elementSize:1,viewConstructor:Uint8Array,readerType:"default"};this._pendingPullIntos.push(o)}G(t,e),he(this)}[P](){if(this._pendingPullIntos.length>0){const e=this._pendingPullIntos.peek();e.readerType="none",this._pendingPullIntos=new v,this._pendingPullIntos.push(e)}}}function fe(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_controlledReadableByteStream")&&e instanceof ReadableByteStreamController)}function be(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_associatedReadableByteStreamController")&&e instanceof ReadableStreamBYOBRequest)}function he(e){const t=function(e){const t=e._controlledReadableByteStream;if("readable"!==t._state)return!1;if(e._closeRequested)return!1;if(!e._started)return!1;if(K(t)&&J(t)>0)return!0;if(Fe(t)&&Le(t)>0)return!0;if(ke(e)>0)return!0;return!1}(e);if(!t)return;if(e._pulling)return void(e._pullAgain=!0);e._pulling=!0;h(e._pullAlgorithm(),(()=>(e._pulling=!1,e._pullAgain&&(e._pullAgain=!1,he(e)),null)),(t=>(We(e,t),null)))}function _e(e){Te(e),e._pendingPullIntos=new v}function pe(e,t){let r=!1;"closed"===e._state&&(r=!0);const o=me(t);"default"===t.readerType?X(e,o,r):function(e,t,r){const o=e._reader._readIntoRequests.shift();r?o._closeSteps(t):o._chunkSteps(t)}(e,o,r)}function me(e){const t=e.bytesFilled,r=e.elementSize;return new e.viewConstructor(e.buffer,e.byteOffset,t/r)}function ye(e,t,r,o){e._queue.push({buffer:t,byteOffset:r,byteLength:o}),e._queueTotalSize+=o}function ge(e,t,r,o){let n;try{n=t.slice(r,r+o)}catch(t){throw We(e,t),t}ye(e,n,0,o)}function Se(e,t){t.bytesFilled>0&&ge(e,t.buffer,t.byteOffset,t.bytesFilled),Pe(e)}function we(e,t){const r=t.elementSize,o=t.bytesFilled-t.bytesFilled%r,n=Math.min(e._queueTotalSize,t.byteLength-t.bytesFilled),a=t.bytesFilled+n,i=a-a%r;let l=n,s=!1;i>o&&(l=i-t.bytesFilled,s=!0);const u=e._queue;for(;l>0;){const r=u.peek(),o=Math.min(l,r.byteLength),n=t.byteOffset+t.bytesFilled;le(t.buffer,n,r.buffer,r.byteOffset,o),r.byteLength===o?u.shift():(r.byteOffset+=o,r.byteLength-=o),e._queueTotalSize-=o,ve(e,o,t),l-=o}return s}function ve(e,t,r){r.bytesFilled+=t}function Re(e){0===e._queueTotalSize&&e._closeRequested?(Ee(e),Jt(e._controlledReadableByteStream)):he(e)}function Te(e){null!==e._byobRequest&&(e._byobRequest._associatedReadableByteStreamController=void 0,e._byobRequest._view=null,e._byobRequest=null)}function qe(e){for(;e._pendingPullIntos.length>0;){if(0===e._queueTotalSize)return;const t=e._pendingPullIntos.peek();we(e,t)&&(Pe(e),pe(e._controlledReadableByteStream,t))}}function Ce(e,t){const r=e._pendingPullIntos.peek();Te(e);"closed"===e._controlledReadableByteStream._state?function(e,t){"none"===t.readerType&&Pe(e);const r=e._controlledReadableByteStream;if(Fe(r))for(;Le(r)>0;)pe(r,Pe(e))}(e,r):function(e,t,r){if(ve(0,t,r),"none"===r.readerType)return Se(e,r),void qe(e);if(r.bytesFilled0){const t=r.byteOffset+r.bytesFilled;ge(e,r.buffer,t-o,o)}r.bytesFilled-=o,pe(e._controlledReadableByteStream,r),qe(e)}(e,t,r),he(e)}function Pe(e){return e._pendingPullIntos.shift()}function Ee(e){e._pullAlgorithm=void 0,e._cancelAlgorithm=void 0}function We(e,t){const r=e._controlledReadableByteStream;"readable"===r._state&&(_e(e),de(e),Ee(e),Kt(r,t))}function Oe(e,t){const r=e._queue.shift();e._queueTotalSize-=r.byteLength,Re(e);const o=new Uint8Array(r.buffer,r.byteOffset,r.byteLength);t._chunkSteps(o)}function ke(e){const t=e._controlledReadableByteStream._state;return"errored"===t?null:"closed"===t?0:e._strategyHWM-e._queueTotalSize}function Be(e,t,r){const o=Object.create(ReadableByteStreamController.prototype);let n,a,i;n=void 0!==t.start?()=>t.start(o):()=>{},a=void 0!==t.pull?()=>t.pull(o):()=>d(void 0),i=void 0!==t.cancel?e=>t.cancel(e):()=>d(void 0);const l=t.autoAllocateChunkSize;if(0===l)throw new TypeError("autoAllocateChunkSize must be greater than 0");!function(e,t,r,o,n,a,i){t._controlledReadableByteStream=e,t._pullAgain=!1,t._pulling=!1,t._byobRequest=null,t._queue=t._queueTotalSize=void 0,de(t),t._closeRequested=!1,t._started=!1,t._strategyHWM=a,t._pullAlgorithm=o,t._cancelAlgorithm=n,t._autoAllocateChunkSize=i,t._pendingPullIntos=new v,e._readableStreamController=t,h(d(r()),(()=>(t._started=!0,he(t),null)),(e=>(We(t,e),null)))}(e,o,n,a,i,r,l)}function Ae(e){return new TypeError(`ReadableStreamBYOBRequest.prototype.${e} can only be used on a ReadableStreamBYOBRequest`)}function je(e){return new TypeError(`ReadableByteStreamController.prototype.${e} can only be used on a ReadableByteStreamController`)}function ze(e,t){e._reader._readIntoRequests.push(t)}function Le(e){return e._reader._readIntoRequests.length}function Fe(e){const t=e._reader;return void 0!==t&&!!De(t)}Object.defineProperties(ReadableByteStreamController.prototype,{close:{enumerable:!0},enqueue:{enumerable:!0},error:{enumerable:!0},byobRequest:{enumerable:!0},desiredSize:{enumerable:!0}}),a(ReadableByteStreamController.prototype.close,"close"),a(ReadableByteStreamController.prototype.enqueue,"enqueue"),a(ReadableByteStreamController.prototype.error,"error"),"symbol"==typeof t.toStringTag&&Object.defineProperty(ReadableByteStreamController.prototype,t.toStringTag,{value:"ReadableByteStreamController",configurable:!0});class ReadableStreamBYOBReader{constructor(e){if(M(e,1,"ReadableStreamBYOBReader"),U(e,"First parameter"),Gt(e))throw new TypeError("This stream has already been locked for exclusive reading by another reader");if(!fe(e._readableStreamController))throw new TypeError("Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte source");E(this,e),this._readIntoRequests=new v}get closed(){return De(this)?this._closedPromise:f($e("closed"))}cancel(e){return De(this)?void 0===this._ownerReadableStream?f(k("cancel")):W(this,e):f($e("cancel"))}read(e){if(!De(this))return f($e("read"));if(!ArrayBuffer.isView(e))return f(new TypeError("view must be an array buffer view"));if(0===e.byteLength)return f(new TypeError("view must have non-zero byteLength"));if(0===e.buffer.byteLength)return f(new TypeError("view's buffer must have non-zero byteLength"));if(e.buffer,void 0===this._ownerReadableStream)return f(k("read from"));let t,r;const o=c(((e,o)=>{t=e,r=o}));return function(e,t,r){const o=e._ownerReadableStream;o._disturbed=!0,"errored"===o._state?r._errorSteps(o._storedError):function(e,t,r){const o=e._controlledReadableByteStream;let n=1;t.constructor!==DataView&&(n=t.constructor.BYTES_PER_ELEMENT);const a=t.constructor,i=t.buffer,l={buffer:i,bufferByteLength:i.byteLength,byteOffset:t.byteOffset,byteLength:t.byteLength,bytesFilled:0,elementSize:n,viewConstructor:a,readerType:"byob"};if(e._pendingPullIntos.length>0)return e._pendingPullIntos.push(l),void ze(o,r);if("closed"!==o._state){if(e._queueTotalSize>0){if(we(e,l)){const t=me(l);return Re(e),void r._chunkSteps(t)}if(e._closeRequested){const t=new TypeError("Insufficient bytes to fill elements in the given buffer");return We(e,t),void r._errorSteps(t)}}e._pendingPullIntos.push(l),ze(o,r),he(e)}else{const e=new a(l.buffer,l.byteOffset,0);r._closeSteps(e)}}(o._readableStreamController,t,r)}(this,e,{_chunkSteps:e=>t({value:e,done:!1}),_closeSteps:e=>t({value:e,done:!0}),_errorSteps:e=>r(e)}),o}releaseLock(){if(!De(this))throw $e("releaseLock");void 0!==this._ownerReadableStream&&function(e){O(e);const t=new TypeError("Reader was released");Ie(e,t)}(this)}}function De(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_readIntoRequests")&&e instanceof ReadableStreamBYOBReader)}function Ie(e,t){const r=e._readIntoRequests;e._readIntoRequests=new v,r.forEach((e=>{e._errorSteps(t)}))}function $e(e){return new TypeError(`ReadableStreamBYOBReader.prototype.${e} can only be used on a ReadableStreamBYOBReader`)}function Me(e,t){const{highWaterMark:r}=e;if(void 0===r)return t;if(ie(r)||r<0)throw new RangeError("Invalid highWaterMark");return r}function Ye(e){const{size:t}=e;return t||(()=>1)}function Qe(e,t){D(e,t);const r=null==e?void 0:e.highWaterMark,o=null==e?void 0:e.size;return{highWaterMark:void 0===r?void 0:Q(r),size:void 0===o?void 0:Ne(o,`${t} has member 'size' that`)}}function Ne(e,t){return I(e,t),t=>Q(e(t))}function xe(e,t,r){return I(e,r),r=>w(e,t,[r])}function He(e,t,r){return I(e,r),()=>w(e,t,[])}function Ve(e,t,r){return I(e,r),r=>S(e,t,[r])}function Ue(e,t,r){return I(e,r),(r,o)=>w(e,t,[r,o])}Object.defineProperties(ReadableStreamBYOBReader.prototype,{cancel:{enumerable:!0},read:{enumerable:!0},releaseLock:{enumerable:!0},closed:{enumerable:!0}}),a(ReadableStreamBYOBReader.prototype.cancel,"cancel"),a(ReadableStreamBYOBReader.prototype.read,"read"),a(ReadableStreamBYOBReader.prototype.releaseLock,"releaseLock"),"symbol"==typeof t.toStringTag&&Object.defineProperty(ReadableStreamBYOBReader.prototype,t.toStringTag,{value:"ReadableStreamBYOBReader",configurable:!0});const Ge="function"==typeof AbortController;class WritableStream{constructor(e={},t={}){void 0===e?e=null:$(e,"First parameter");const r=Qe(t,"Second parameter"),o=function(e,t){D(e,t);const r=null==e?void 0:e.abort,o=null==e?void 0:e.close,n=null==e?void 0:e.start,a=null==e?void 0:e.type,i=null==e?void 0:e.write;return{abort:void 0===r?void 0:xe(r,e,`${t} has member 'abort' that`),close:void 0===o?void 0:He(o,e,`${t} has member 'close' that`),start:void 0===n?void 0:Ve(n,e,`${t} has member 'start' that`),write:void 0===i?void 0:Ue(i,e,`${t} has member 'write' that`),type:a}}(e,"First parameter");var n;(n=this)._state="writable",n._storedError=void 0,n._writer=void 0,n._writableStreamController=void 0,n._writeRequests=new v,n._inFlightWriteRequest=void 0,n._closeRequest=void 0,n._inFlightCloseRequest=void 0,n._pendingAbortRequest=void 0,n._backpressure=!1;if(void 0!==o.type)throw new RangeError("Invalid type is specified");const a=Ye(r);!function(e,t,r,o){const n=Object.create(WritableStreamDefaultController.prototype);let a,i,l,s;a=void 0!==t.start?()=>t.start(n):()=>{};i=void 0!==t.write?e=>t.write(e,n):()=>d(void 0);l=void 0!==t.close?()=>t.close():()=>d(void 0);s=void 0!==t.abort?e=>t.abort(e):()=>d(void 0);!function(e,t,r,o,n,a,i,l){t._controlledWritableStream=e,e._writableStreamController=t,t._queue=void 0,t._queueTotalSize=void 0,de(t),t._abortReason=void 0,t._abortController=function(){if(Ge)return new AbortController}(),t._started=!1,t._strategySizeAlgorithm=l,t._strategyHWM=i,t._writeAlgorithm=o,t._closeAlgorithm=n,t._abortAlgorithm=a;const s=ht(t);at(e,s);const u=r();h(d(u),(()=>(t._started=!0,ft(t),null)),(r=>(t._started=!0,et(e,r),null)))}(e,n,a,i,l,s,r,o)}(this,o,Me(r,1),a)}get locked(){if(!Xe(this))throw pt("locked");return Je(this)}abort(e){return Xe(this)?Je(this)?f(new TypeError("Cannot abort a stream that already has a writer")):Ke(this,e):f(pt("abort"))}close(){return Xe(this)?Je(this)?f(new TypeError("Cannot close a stream that already has a writer")):ot(this)?f(new TypeError("Cannot close an already-closing stream")):Ze(this):f(pt("close"))}getWriter(){if(!Xe(this))throw pt("getWriter");return new WritableStreamDefaultWriter(this)}}function Xe(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_writableStreamController")&&e instanceof WritableStream)}function Je(e){return void 0!==e._writer}function Ke(e,t){var r;if("closed"===e._state||"errored"===e._state)return d(void 0);e._writableStreamController._abortReason=t,null===(r=e._writableStreamController._abortController)||void 0===r||r.abort(t);const o=e._state;if("closed"===o||"errored"===o)return d(void 0);if(void 0!==e._pendingAbortRequest)return e._pendingAbortRequest._promise;let n=!1;"erroring"===o&&(n=!0,t=void 0);const a=c(((r,o)=>{e._pendingAbortRequest={_promise:void 0,_resolve:r,_reject:o,_reason:t,_wasAlreadyErroring:n}}));return e._pendingAbortRequest._promise=a,n||tt(e,t),a}function Ze(e){const t=e._state;if("closed"===t||"errored"===t)return f(new TypeError(`The stream (in ${t} state) is not in the writable state and cannot be closed`));const r=c(((t,r)=>{const o={_resolve:t,_reject:r};e._closeRequest=o})),o=e._writer;var n;return void 0!==o&&e._backpressure&&"writable"===t&&Et(o),ce(n=e._writableStreamController,st,0),ft(n),r}function et(e,t){"writable"!==e._state?rt(e):tt(e,t)}function tt(e,t){const r=e._writableStreamController;e._state="erroring",e._storedError=t;const o=e._writer;void 0!==o&<(o,t),!function(e){if(void 0===e._inFlightWriteRequest&&void 0===e._inFlightCloseRequest)return!1;return!0}(e)&&r._started&&rt(e)}function rt(e){e._state="errored",e._writableStreamController[T]();const t=e._storedError;if(e._writeRequests.forEach((e=>{e._reject(t)})),e._writeRequests=new v,void 0===e._pendingAbortRequest)return void nt(e);const r=e._pendingAbortRequest;if(e._pendingAbortRequest=void 0,r._wasAlreadyErroring)return r._reject(t),void nt(e);h(e._writableStreamController[R](r._reason),(()=>(r._resolve(),nt(e),null)),(t=>(r._reject(t),nt(e),null)))}function ot(e){return void 0!==e._closeRequest||void 0!==e._inFlightCloseRequest}function nt(e){void 0!==e._closeRequest&&(e._closeRequest._reject(e._storedError),e._closeRequest=void 0);const t=e._writer;void 0!==t&&vt(t,e._storedError)}function at(e,t){const r=e._writer;void 0!==r&&t!==e._backpressure&&(t?function(e){Tt(e)}(r):Et(r)),e._backpressure=t}Object.defineProperties(WritableStream.prototype,{abort:{enumerable:!0},close:{enumerable:!0},getWriter:{enumerable:!0},locked:{enumerable:!0}}),a(WritableStream.prototype.abort,"abort"),a(WritableStream.prototype.close,"close"),a(WritableStream.prototype.getWriter,"getWriter"),"symbol"==typeof t.toStringTag&&Object.defineProperty(WritableStream.prototype,t.toStringTag,{value:"WritableStream",configurable:!0});class WritableStreamDefaultWriter{constructor(e){if(M(e,1,"WritableStreamDefaultWriter"),function(e,t){if(!Xe(e))throw new TypeError(`${t} is not a WritableStream.`)}(e,"First parameter"),Je(e))throw new TypeError("This stream has already been locked for exclusive writing by another writer");this._ownerWritableStream=e,e._writer=this;const t=e._state;if("writable"===t)!ot(e)&&e._backpressure?Tt(this):Ct(this),St(this);else if("erroring"===t)qt(this,e._storedError),St(this);else if("closed"===t)Ct(this),St(r=this),Rt(r);else{const t=e._storedError;qt(this,t),wt(this,t)}var r}get closed(){return it(this)?this._closedPromise:f(yt("closed"))}get desiredSize(){if(!it(this))throw yt("desiredSize");if(void 0===this._ownerWritableStream)throw gt("desiredSize");return function(e){const t=e._ownerWritableStream,r=t._state;if("errored"===r||"erroring"===r)return null;if("closed"===r)return 0;return dt(t._writableStreamController)}(this)}get ready(){return it(this)?this._readyPromise:f(yt("ready"))}abort(e){return it(this)?void 0===this._ownerWritableStream?f(gt("abort")):function(e,t){return Ke(e._ownerWritableStream,t)}(this,e):f(yt("abort"))}close(){if(!it(this))return f(yt("close"));const e=this._ownerWritableStream;return void 0===e?f(gt("close")):ot(e)?f(new TypeError("Cannot close an already-closing stream")):Ze(this._ownerWritableStream)}releaseLock(){if(!it(this))throw yt("releaseLock");void 0!==this._ownerWritableStream&&function(e){const t=e._ownerWritableStream,r=new TypeError("Writer was released and can no longer be used to monitor the stream's closedness");lt(e,r),function(e,t){"pending"===e._closedPromiseState?vt(e,t):function(e,t){wt(e,t)}(e,t)}(e,r),t._writer=void 0,e._ownerWritableStream=void 0}(this)}write(e){return it(this)?void 0===this._ownerWritableStream?f(gt("write to")):function(e,t){const r=e._ownerWritableStream,o=r._writableStreamController,n=function(e,t){try{return e._strategySizeAlgorithm(t)}catch(t){return bt(e,t),1}}(o,t);if(r!==e._ownerWritableStream)return f(gt("write to"));const a=r._state;if("errored"===a)return f(r._storedError);if(ot(r)||"closed"===a)return f(new TypeError("The stream is closing or closed and cannot be written to"));if("erroring"===a)return f(r._storedError);const i=function(e){return c(((t,r)=>{const o={_resolve:t,_reject:r};e._writeRequests.push(o)}))}(r);return function(e,t,r){try{ce(e,t,r)}catch(t){return void bt(e,t)}const o=e._controlledWritableStream;if(!ot(o)&&"writable"===o._state){at(o,ht(e))}ft(e)}(o,t,n),i}(this,e):f(yt("write"))}}function it(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_ownerWritableStream")&&e instanceof WritableStreamDefaultWriter)}function lt(e,t){"pending"===e._readyPromiseState?Pt(e,t):function(e,t){qt(e,t)}(e,t)}Object.defineProperties(WritableStreamDefaultWriter.prototype,{abort:{enumerable:!0},close:{enumerable:!0},releaseLock:{enumerable:!0},write:{enumerable:!0},closed:{enumerable:!0},desiredSize:{enumerable:!0},ready:{enumerable:!0}}),a(WritableStreamDefaultWriter.prototype.abort,"abort"),a(WritableStreamDefaultWriter.prototype.close,"close"),a(WritableStreamDefaultWriter.prototype.releaseLock,"releaseLock"),a(WritableStreamDefaultWriter.prototype.write,"write"),"symbol"==typeof t.toStringTag&&Object.defineProperty(WritableStreamDefaultWriter.prototype,t.toStringTag,{value:"WritableStreamDefaultWriter",configurable:!0});const st={};class WritableStreamDefaultController{constructor(){throw new TypeError("Illegal constructor")}get abortReason(){if(!ut(this))throw mt("abortReason");return this._abortReason}get signal(){if(!ut(this))throw mt("signal");if(void 0===this._abortController)throw new TypeError("WritableStreamDefaultController.prototype.signal is not supported");return this._abortController.signal}error(e){if(!ut(this))throw mt("error");"writable"===this._controlledWritableStream._state&&_t(this,e)}[R](e){const t=this._abortAlgorithm(e);return ct(this),t}[T](){de(this)}}function ut(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_controlledWritableStream")&&e instanceof WritableStreamDefaultController)}function ct(e){e._writeAlgorithm=void 0,e._closeAlgorithm=void 0,e._abortAlgorithm=void 0,e._strategySizeAlgorithm=void 0}function dt(e){return e._strategyHWM-e._queueTotalSize}function ft(e){const t=e._controlledWritableStream;if(!e._started)return;if(void 0!==t._inFlightWriteRequest)return;if("erroring"===t._state)return void rt(t);if(0===e._queue.length)return;const r=e._queue.peek().value;r===st?function(e){const t=e._controlledWritableStream;(function(e){e._inFlightCloseRequest=e._closeRequest,e._closeRequest=void 0})(t),ue(e);const r=e._closeAlgorithm();ct(e),h(r,(()=>(function(e){e._inFlightCloseRequest._resolve(void 0),e._inFlightCloseRequest=void 0,"erroring"===e._state&&(e._storedError=void 0,void 0!==e._pendingAbortRequest&&(e._pendingAbortRequest._resolve(),e._pendingAbortRequest=void 0)),e._state="closed";const t=e._writer;void 0!==t&&Rt(t)}(t),null)),(e=>(function(e,t){e._inFlightCloseRequest._reject(t),e._inFlightCloseRequest=void 0,void 0!==e._pendingAbortRequest&&(e._pendingAbortRequest._reject(t),e._pendingAbortRequest=void 0),et(e,t)}(t,e),null)))}(e):function(e,t){const r=e._controlledWritableStream;!function(e){e._inFlightWriteRequest=e._writeRequests.shift()}(r);h(e._writeAlgorithm(t),(()=>{!function(e){e._inFlightWriteRequest._resolve(void 0),e._inFlightWriteRequest=void 0}(r);const t=r._state;if(ue(e),!ot(r)&&"writable"===t){const t=ht(e);at(r,t)}return ft(e),null}),(t=>("writable"===r._state&&ct(e),function(e,t){e._inFlightWriteRequest._reject(t),e._inFlightWriteRequest=void 0,et(e,t)}(r,t),null)))}(e,r)}function bt(e,t){"writable"===e._controlledWritableStream._state&&_t(e,t)}function ht(e){return dt(e)<=0}function _t(e,t){const r=e._controlledWritableStream;ct(e),tt(r,t)}function pt(e){return new TypeError(`WritableStream.prototype.${e} can only be used on a WritableStream`)}function mt(e){return new TypeError(`WritableStreamDefaultController.prototype.${e} can only be used on a WritableStreamDefaultController`)}function yt(e){return new TypeError(`WritableStreamDefaultWriter.prototype.${e} can only be used on a WritableStreamDefaultWriter`)}function gt(e){return new TypeError("Cannot "+e+" a stream using a released writer")}function St(e){e._closedPromise=c(((t,r)=>{e._closedPromise_resolve=t,e._closedPromise_reject=r,e._closedPromiseState="pending"}))}function wt(e,t){St(e),vt(e,t)}function vt(e,t){void 0!==e._closedPromise_reject&&(y(e._closedPromise),e._closedPromise_reject(t),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0,e._closedPromiseState="rejected")}function Rt(e){void 0!==e._closedPromise_resolve&&(e._closedPromise_resolve(void 0),e._closedPromise_resolve=void 0,e._closedPromise_reject=void 0,e._closedPromiseState="resolved")}function Tt(e){e._readyPromise=c(((t,r)=>{e._readyPromise_resolve=t,e._readyPromise_reject=r})),e._readyPromiseState="pending"}function qt(e,t){Tt(e),Pt(e,t)}function Ct(e){Tt(e),Et(e)}function Pt(e,t){void 0!==e._readyPromise_reject&&(y(e._readyPromise),e._readyPromise_reject(t),e._readyPromise_resolve=void 0,e._readyPromise_reject=void 0,e._readyPromiseState="rejected")}function Et(e){void 0!==e._readyPromise_resolve&&(e._readyPromise_resolve(void 0),e._readyPromise_resolve=void 0,e._readyPromise_reject=void 0,e._readyPromiseState="fulfilled")}Object.defineProperties(WritableStreamDefaultController.prototype,{abortReason:{enumerable:!0},signal:{enumerable:!0},error:{enumerable:!0}}),"symbol"==typeof t.toStringTag&&Object.defineProperty(WritableStreamDefaultController.prototype,t.toStringTag,{value:"WritableStreamDefaultController",configurable:!0});const Wt="undefined"!=typeof DOMException?DOMException:void 0;const Ot=function(e){if("function"!=typeof e&&"object"!=typeof e)return!1;try{return new e,!0}catch(e){return!1}}(Wt)?Wt:function(){const e=function(e,t){this.message=e||"",this.name=t||"Error",Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)};return e.prototype=Object.create(Error.prototype),Object.defineProperty(e.prototype,"constructor",{value:e,writable:!0,configurable:!0}),e}();function kt(e,t,r,o,n,a){const i=e.getReader(),l=t.getWriter();Ut(e)&&(e._disturbed=!0);let s,u,p,S=!1,w=!1,v="readable",R="writable",T=!1,q=!1;const C=c((e=>{p=e}));let P=Promise.resolve(void 0);return c(((E,W)=>{let O;function k(){if(S)return;const e=c(((e,t)=>{!function r(o){o?e():b(function(){if(S)return d(!0);return b(l.ready,(()=>b(i.read(),(e=>!!e.done||(P=l.write(e.value),y(P),!1)))))}(),r,t)}(!1)}));y(e)}function B(){return v="closed",r?L():z((()=>(Xe(t)&&(T=ot(t),R=t._state),T||"closed"===R?d(void 0):"erroring"===R||"errored"===R?f(u):(T=!0,l.close()))),!1,void 0),null}function A(e){return S||(v="errored",s=e,o?L(!0,e):z((()=>l.abort(e)),!0,e)),null}function j(e){return w||(R="errored",u=e,n?L(!0,e):z((()=>i.cancel(e)),!0,e)),null}if(void 0!==a&&(O=()=>{const e=void 0!==a.reason?a.reason:new Ot("Aborted","AbortError"),t=[];o||t.push((()=>"writable"===R?l.abort(e):d(void 0))),n||t.push((()=>"readable"===v?i.cancel(e):d(void 0))),z((()=>Promise.all(t.map((e=>e())))),!0,e)},a.aborted?O():a.addEventListener("abort",O)),Ut(e)&&(v=e._state,s=e._storedError),Xe(t)&&(R=t._state,u=t._storedError,T=ot(t)),Ut(e)&&Xe(t)&&(q=!0,p()),"errored"===v)A(s);else if("erroring"===R||"errored"===R)j(u);else if("closed"===v)B();else if(T||"closed"===R){const e=new TypeError("the destination writable stream closed before all data could be piped to it");n?L(!0,e):z((()=>i.cancel(e)),!0,e)}function z(e,t,r){function o(){return"writable"!==R||T?n():_(function(){let e;return d(function t(){if(e!==P)return e=P,m(P,t,t)}())}(),n),null}function n(){return e?h(e(),(()=>F(t,r)),(e=>F(!0,e))):F(t,r),null}S||(S=!0,q?o():_(C,o))}function L(e,t){z(void 0,e,t)}function F(e,t){return w=!0,l.releaseLock(),i.releaseLock(),void 0!==a&&a.removeEventListener("abort",O),e?W(t):E(void 0),null}S||(h(i.closed,B,A),h(l.closed,(function(){return w||(R="closed"),null}),j)),q?k():g((()=>{q=!0,p(),k()}))}))}function Bt(e,t){return function(e){try{return e.getReader({mode:"byob"}).releaseLock(),!0}catch(e){return!1}}(e)?function(e){let t,r,o,n,a,i=e.getReader(),l=!1,s=!1,u=!1,f=!1,b=!1,_=!1;const m=c((e=>{a=e}));function y(e){p(e.closed,(t=>(e!==i||(o.error(t),n.error(t),b&&_||a(void 0)),null)))}function g(){l&&(i.releaseLock(),i=e.getReader(),y(i),l=!1),h(i.read(),(e=>{var t,r;if(u=!1,f=!1,e.done)return b||o.close(),_||n.close(),null===(t=o.byobRequest)||void 0===t||t.respond(0),null===(r=n.byobRequest)||void 0===r||r.respond(0),b&&_||a(void 0),null;const l=e.value,c=l;let d=l;if(!b&&!_)try{d=se(l)}catch(e){return o.error(e),n.error(e),a(i.cancel(e)),null}return b||o.enqueue(c),_||n.enqueue(d),s=!1,u?w():f&&v(),null}),(()=>(s=!1,null)))}function S(t,r){l||(i.releaseLock(),i=e.getReader({mode:"byob"}),y(i),l=!0);const c=r?n:o,d=r?o:n;h(i.read(t),(e=>{var t;u=!1,f=!1;const o=r?_:b,n=r?b:_;if(e.done){o||c.close(),n||d.close();const r=e.value;return void 0!==r&&(o||c.byobRequest.respondWithNewView(r),n||null===(t=d.byobRequest)||void 0===t||t.respond(0)),o&&n||a(void 0),null}const l=e.value;if(n)o||c.byobRequest.respondWithNewView(l);else{let e;try{e=se(l)}catch(e){return c.error(e),d.error(e),a(i.cancel(e)),null}o||c.byobRequest.respondWithNewView(l),d.enqueue(e)}return s=!1,u?w():f&&v(),null}),(()=>(s=!1,null)))}function w(){if(s)return u=!0,d(void 0);s=!0;const e=o.byobRequest;return null===e?g():S(e.view,!1),d(void 0)}function v(){if(s)return f=!0,d(void 0);s=!0;const e=n.byobRequest;return null===e?g():S(e.view,!0),d(void 0)}function R(e){if(b=!0,t=e,_){const e=[t,r],o=i.cancel(e);a(o)}return m}function T(e){if(_=!0,r=e,b){const e=[t,r],o=i.cancel(e);a(o)}return m}const q=new ReadableStream({type:"bytes",start(e){o=e},pull:w,cancel:R}),C=new ReadableStream({type:"bytes",start(e){n=e},pull:v,cancel:T});return y(i),[q,C]}(e):function(e,t){const r=e.getReader();let o,n,a,i,l,s=!1,u=!1,f=!1,b=!1;const _=c((e=>{l=e}));function m(){return s?(u=!0,d(void 0)):(s=!0,h(r.read(),(e=>{if(u=!1,e.done)return f||a.close(),b||i.close(),f&&b||l(void 0),null;const t=e.value,r=t,o=t;return f||a.enqueue(r),b||i.enqueue(o),s=!1,u&&m(),null}),(()=>(s=!1,null))),d(void 0))}function y(e){if(f=!0,o=e,b){const e=[o,n],t=r.cancel(e);l(t)}return _}function g(e){if(b=!0,n=e,f){const e=[o,n],t=r.cancel(e);l(t)}return _}const S=new ReadableStream({start(e){a=e},pull:m,cancel:y}),w=new ReadableStream({start(e){i=e},pull:m,cancel:g});return p(r.closed,(e=>(a.error(e),i.error(e),f&&b||l(void 0),null))),[S,w]}(e)}class ReadableStreamDefaultController{constructor(){throw new TypeError("Illegal constructor")}get desiredSize(){if(!At(this))throw $t("desiredSize");return Ft(this)}close(){if(!At(this))throw $t("close");if(!Dt(this))throw new TypeError("The stream is not in a state that permits close");!function(e){if(!Dt(e))return;const t=e._controlledReadableStream;e._closeRequested=!0,0===e._queue.length&&(zt(e),Jt(t))}(this)}enqueue(e){if(!At(this))throw $t("enqueue");if(!Dt(this))throw new TypeError("The stream is not in a state that permits enqueue");return function(e,t){if(!Dt(e))return;const r=e._controlledReadableStream;if(Gt(r)&&J(r)>0)X(r,t,!1);else{let r;try{r=e._strategySizeAlgorithm(t)}catch(t){throw Lt(e,t),t}try{ce(e,t,r)}catch(t){throw Lt(e,t),t}}jt(e)}(this,e)}error(e){if(!At(this))throw $t("error");Lt(this,e)}[q](e){de(this);const t=this._cancelAlgorithm(e);return zt(this),t}[C](e){const t=this._controlledReadableStream;if(this._queue.length>0){const r=ue(this);this._closeRequested&&0===this._queue.length?(zt(this),Jt(t)):jt(this),e._chunkSteps(r)}else G(t,e),jt(this)}[P](){}}function At(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_controlledReadableStream")&&e instanceof ReadableStreamDefaultController)}function jt(e){const t=function(e){const t=e._controlledReadableStream;if(!Dt(e))return!1;if(!e._started)return!1;if(Gt(t)&&J(t)>0)return!0;if(Ft(e)>0)return!0;return!1}(e);if(!t)return;if(e._pulling)return void(e._pullAgain=!0);e._pulling=!0;h(e._pullAlgorithm(),(()=>(e._pulling=!1,e._pullAgain&&(e._pullAgain=!1,jt(e)),null)),(t=>(Lt(e,t),null)))}function zt(e){e._pullAlgorithm=void 0,e._cancelAlgorithm=void 0,e._strategySizeAlgorithm=void 0}function Lt(e,t){const r=e._controlledReadableStream;"readable"===r._state&&(de(e),zt(e),Kt(r,t))}function Ft(e){const t=e._controlledReadableStream._state;return"errored"===t?null:"closed"===t?0:e._strategyHWM-e._queueTotalSize}function Dt(e){return!e._closeRequested&&"readable"===e._controlledReadableStream._state}function It(e,t,r,o){const n=Object.create(ReadableStreamDefaultController.prototype);let a,i,l;a=void 0!==t.start?()=>t.start(n):()=>{},i=void 0!==t.pull?()=>t.pull(n):()=>d(void 0),l=void 0!==t.cancel?e=>t.cancel(e):()=>d(void 0),function(e,t,r,o,n,a,i){t._controlledReadableStream=e,t._queue=void 0,t._queueTotalSize=void 0,de(t),t._started=!1,t._closeRequested=!1,t._pullAgain=!1,t._pulling=!1,t._strategySizeAlgorithm=i,t._strategyHWM=a,t._pullAlgorithm=o,t._cancelAlgorithm=n,e._readableStreamController=t,h(d(r()),(()=>(t._started=!0,jt(t),null)),(e=>(Lt(t,e),null)))}(e,n,a,i,l,r,o)}function $t(e){return new TypeError(`ReadableStreamDefaultController.prototype.${e} can only be used on a ReadableStreamDefaultController`)}function Mt(e,t,r){return I(e,r),r=>w(e,t,[r])}function Yt(e,t,r){return I(e,r),r=>w(e,t,[r])}function Qt(e,t,r){return I(e,r),r=>S(e,t,[r])}function Nt(e,t){if("bytes"!==(e=`${e}`))throw new TypeError(`${t} '${e}' is not a valid enumeration value for ReadableStreamType`);return e}function xt(e,t){if("byob"!==(e=`${e}`))throw new TypeError(`${t} '${e}' is not a valid enumeration value for ReadableStreamReaderMode`);return e}function Ht(e,t){D(e,t);const r=null==e?void 0:e.preventAbort,o=null==e?void 0:e.preventCancel,n=null==e?void 0:e.preventClose,a=null==e?void 0:e.signal;return void 0!==a&&function(e,t){if(!function(e){if("object"!=typeof e||null===e)return!1;try{return"boolean"==typeof e.aborted}catch(e){return!1}}(e))throw new TypeError(`${t} is not an AbortSignal.`)}(a,`${t} has member 'signal' that`),{preventAbort:Boolean(r),preventCancel:Boolean(o),preventClose:Boolean(n),signal:a}}function Vt(e,t){D(e,t);const r=null==e?void 0:e.readable;Y(r,"readable","ReadableWritablePair"),function(e,t){if(!H(e))throw new TypeError(`${t} is not a ReadableStream.`)}(r,`${t} has member 'readable' that`);const o=null==e?void 0:e.writable;return Y(o,"writable","ReadableWritablePair"),function(e,t){if(!V(e))throw new TypeError(`${t} is not a WritableStream.`)}(o,`${t} has member 'writable' that`),{readable:r,writable:o}}Object.defineProperties(ReadableStreamDefaultController.prototype,{close:{enumerable:!0},enqueue:{enumerable:!0},error:{enumerable:!0},desiredSize:{enumerable:!0}}),a(ReadableStreamDefaultController.prototype.close,"close"),a(ReadableStreamDefaultController.prototype.enqueue,"enqueue"),a(ReadableStreamDefaultController.prototype.error,"error"),"symbol"==typeof t.toStringTag&&Object.defineProperty(ReadableStreamDefaultController.prototype,t.toStringTag,{value:"ReadableStreamDefaultController",configurable:!0});class ReadableStream{constructor(e={},t={}){void 0===e?e=null:$(e,"First parameter");const r=Qe(t,"Second parameter"),o=function(e,t){D(e,t);const r=e,o=null==r?void 0:r.autoAllocateChunkSize,n=null==r?void 0:r.cancel,a=null==r?void 0:r.pull,i=null==r?void 0:r.start,l=null==r?void 0:r.type;return{autoAllocateChunkSize:void 0===o?void 0:x(o,`${t} has member 'autoAllocateChunkSize' that`),cancel:void 0===n?void 0:Mt(n,r,`${t} has member 'cancel' that`),pull:void 0===a?void 0:Yt(a,r,`${t} has member 'pull' that`),start:void 0===i?void 0:Qt(i,r,`${t} has member 'start' that`),type:void 0===l?void 0:Nt(l,`${t} has member 'type' that`)}}(e,"First parameter");var n;if((n=this)._state="readable",n._reader=void 0,n._storedError=void 0,n._disturbed=!1,"bytes"===o.type){if(void 0!==r.size)throw new RangeError("The strategy for a byte stream cannot have a size function");Be(this,o,Me(r,0))}else{const e=Ye(r);It(this,o,Me(r,1),e)}}get locked(){if(!Ut(this))throw Zt("locked");return Gt(this)}cancel(e){return Ut(this)?Gt(this)?f(new TypeError("Cannot cancel a stream that already has a reader")):Xt(this,e):f(Zt("cancel"))}getReader(e){if(!Ut(this))throw Zt("getReader");return void 0===function(e,t){D(e,t);const r=null==e?void 0:e.mode;return{mode:void 0===r?void 0:xt(r,`${t} has member 'mode' that`)}}(e,"First parameter").mode?new ReadableStreamDefaultReader(this):function(e){return new ReadableStreamBYOBReader(e)}(this)}pipeThrough(e,t={}){if(!H(this))throw Zt("pipeThrough");M(e,1,"pipeThrough");const r=Vt(e,"First parameter"),o=Ht(t,"Second parameter");if(this.locked)throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream");if(r.writable.locked)throw new TypeError("ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream");return y(kt(this,r.writable,o.preventClose,o.preventAbort,o.preventCancel,o.signal)),r.readable}pipeTo(e,t={}){if(!H(this))return f(Zt("pipeTo"));if(void 0===e)return f("Parameter 1 is required in 'pipeTo'.");if(!V(e))return f(new TypeError("ReadableStream.prototype.pipeTo's first argument must be a WritableStream"));let r;try{r=Ht(t,"Second parameter")}catch(e){return f(e)}return this.locked?f(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream")):e.locked?f(new TypeError("ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream")):kt(this,e,r.preventClose,r.preventAbort,r.preventCancel,r.signal)}tee(){if(!H(this))throw Zt("tee");if(this.locked)throw new TypeError("Cannot tee a stream that already has a reader");return Bt(this)}values(e){if(!H(this))throw Zt("values");return function(e,t){const r=e.getReader(),o=new re(r,t),n=Object.create(oe);return n._asyncIteratorImpl=o,n}(this,function(e,t){D(e,t);const r=null==e?void 0:e.preventCancel;return{preventCancel:Boolean(r)}}(e,"First parameter").preventCancel)}}function Ut(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_readableStreamController")&&e instanceof ReadableStream)}function Gt(e){return void 0!==e._reader}function Xt(e,t){if(e._disturbed=!0,"closed"===e._state)return d(void 0);if("errored"===e._state)return f(e._storedError);Jt(e);const o=e._reader;if(void 0!==o&&De(o)){const e=o._readIntoRequests;o._readIntoRequests=new v,e.forEach((e=>{e._closeSteps(void 0)}))}return m(e._readableStreamController[q](t),r)}function Jt(e){e._state="closed";const t=e._reader;if(void 0!==t&&(z(t),Z(t))){const e=t._readRequests;t._readRequests=new v,e.forEach((e=>{e._closeSteps()}))}}function Kt(e,t){e._state="errored",e._storedError=t;const r=e._reader;void 0!==r&&(j(r,t),Z(r)?ee(r,t):Ie(r,t))}function Zt(e){return new TypeError(`ReadableStream.prototype.${e} can only be used on a ReadableStream`)}function er(e,t){D(e,t);const r=null==e?void 0:e.highWaterMark;return Y(r,"highWaterMark","QueuingStrategyInit"),{highWaterMark:Q(r)}}Object.defineProperties(ReadableStream.prototype,{cancel:{enumerable:!0},getReader:{enumerable:!0},pipeThrough:{enumerable:!0},pipeTo:{enumerable:!0},tee:{enumerable:!0},values:{enumerable:!0},locked:{enumerable:!0}}),a(ReadableStream.prototype.cancel,"cancel"),a(ReadableStream.prototype.getReader,"getReader"),a(ReadableStream.prototype.pipeThrough,"pipeThrough"),a(ReadableStream.prototype.pipeTo,"pipeTo"),a(ReadableStream.prototype.tee,"tee"),a(ReadableStream.prototype.values,"values"),"symbol"==typeof t.toStringTag&&Object.defineProperty(ReadableStream.prototype,t.toStringTag,{value:"ReadableStream",configurable:!0}),"symbol"==typeof t.asyncIterator&&Object.defineProperty(ReadableStream.prototype,t.asyncIterator,{value:ReadableStream.prototype.values,writable:!0,configurable:!0});const tr=e=>e.byteLength;a(tr,"size");class ByteLengthQueuingStrategy{constructor(e){M(e,1,"ByteLengthQueuingStrategy"),e=er(e,"First parameter"),this._byteLengthQueuingStrategyHighWaterMark=e.highWaterMark}get highWaterMark(){if(!or(this))throw rr("highWaterMark");return this._byteLengthQueuingStrategyHighWaterMark}get size(){if(!or(this))throw rr("size");return tr}}function rr(e){return new TypeError(`ByteLengthQueuingStrategy.prototype.${e} can only be used on a ByteLengthQueuingStrategy`)}function or(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_byteLengthQueuingStrategyHighWaterMark")&&e instanceof ByteLengthQueuingStrategy)}Object.defineProperties(ByteLengthQueuingStrategy.prototype,{highWaterMark:{enumerable:!0},size:{enumerable:!0}}),"symbol"==typeof t.toStringTag&&Object.defineProperty(ByteLengthQueuingStrategy.prototype,t.toStringTag,{value:"ByteLengthQueuingStrategy",configurable:!0});const nr=()=>1;a(nr,"size");class CountQueuingStrategy{constructor(e){M(e,1,"CountQueuingStrategy"),e=er(e,"First parameter"),this._countQueuingStrategyHighWaterMark=e.highWaterMark}get highWaterMark(){if(!ir(this))throw ar("highWaterMark");return this._countQueuingStrategyHighWaterMark}get size(){if(!ir(this))throw ar("size");return nr}}function ar(e){return new TypeError(`CountQueuingStrategy.prototype.${e} can only be used on a CountQueuingStrategy`)}function ir(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_countQueuingStrategyHighWaterMark")&&e instanceof CountQueuingStrategy)}function lr(e,t,r){return I(e,r),r=>w(e,t,[r])}function sr(e,t,r){return I(e,r),r=>S(e,t,[r])}function ur(e,t,r){return I(e,r),(r,o)=>w(e,t,[r,o])}Object.defineProperties(CountQueuingStrategy.prototype,{highWaterMark:{enumerable:!0},size:{enumerable:!0}}),"symbol"==typeof t.toStringTag&&Object.defineProperty(CountQueuingStrategy.prototype,t.toStringTag,{value:"CountQueuingStrategy",configurable:!0});class TransformStream{constructor(e={},t={},r={}){void 0===e&&(e=null);const o=Qe(t,"Second parameter"),n=Qe(r,"Third parameter"),a=function(e,t){D(e,t);const r=null==e?void 0:e.flush,o=null==e?void 0:e.readableType,n=null==e?void 0:e.start,a=null==e?void 0:e.transform,i=null==e?void 0:e.writableType;return{flush:void 0===r?void 0:lr(r,e,`${t} has member 'flush' that`),readableType:o,start:void 0===n?void 0:sr(n,e,`${t} has member 'start' that`),transform:void 0===a?void 0:ur(a,e,`${t} has member 'transform' that`),writableType:i}}(e,"First parameter");if(void 0!==a.readableType)throw new RangeError("Invalid readableType specified");if(void 0!==a.writableType)throw new RangeError("Invalid writableType specified");const i=Me(n,0),l=Ye(n),s=Me(o,1),u=Ye(o);let b;!function(e,t,r,o,n,a){function i(){return t}function l(t){return function(e,t){const r=e._transformStreamController;if(e._backpressure){return m(e._backpressureChangePromise,(()=>{if("erroring"===(Xe(e._writable)?e._writable._state:e._writableState))throw Xe(e._writable)?e._writable._storedError:e._writableStoredError;return mr(r,t)}))}return mr(r,t)}(e,t)}function s(t){return function(e,t){return dr(e,t),d(void 0)}(e,t)}function u(){return function(e){const t=e._transformStreamController,r=t._flushAlgorithm();return _r(t),m(r,(()=>{if("errored"===e._readableState)throw e._readableStoredError;Sr(e)&&wr(e)}),(t=>{throw dr(e,t),e._readableStoredError}))}(e)}function c(){return function(e){return br(e,!1),e._backpressureChangePromise}(e)}function f(t){return fr(e,t),d(void 0)}e._writableState="writable",e._writableStoredError=void 0,e._writableHasInFlightOperation=!1,e._writableStarted=!1,e._writable=function(e,t,r,o,n,a,i){return new WritableStream({start(r){e._writableController=r;try{const t=r.signal;void 0!==t&&t.addEventListener("abort",(()=>{"writable"===e._writableState&&(e._writableState="erroring",t.reason&&(e._writableStoredError=t.reason))}))}catch(e){}return m(t(),(()=>(e._writableStarted=!0,Pr(e),null)),(t=>{throw e._writableStarted=!0,Tr(e,t),t}))},write:t=>(function(e){e._writableHasInFlightOperation=!0}(e),m(r(t),(()=>(function(e){e._writableHasInFlightOperation=!1}(e),Pr(e),null)),(t=>{throw function(e,t){e._writableHasInFlightOperation=!1,Tr(e,t)}(e,t),t}))),close:()=>(function(e){e._writableHasInFlightOperation=!0}(e),m(o(),(()=>(function(e){e._writableHasInFlightOperation=!1;"erroring"===e._writableState&&(e._writableStoredError=void 0);e._writableState="closed"}(e),null)),(t=>{throw function(e,t){e._writableHasInFlightOperation=!1,e._writableState,Tr(e,t)}(e,t),t}))),abort:t=>(e._writableState="errored",e._writableStoredError=t,n(t))},{highWaterMark:a,size:i})}(e,i,l,u,s,r,o),e._readableState="readable",e._readableStoredError=void 0,e._readableCloseRequested=!1,e._readablePulling=!1,e._readable=function(e,t,r,o,n,a){return new ReadableStream({start:r=>(e._readableController=r,t().catch((t=>{vr(e,t)}))),pull:()=>(e._readablePulling=!0,r().catch((t=>{vr(e,t)}))),cancel:t=>(e._readableState="closed",o(t))},{highWaterMark:n,size:a})}(e,i,c,f,n,a),e._backpressure=void 0,e._backpressureChangePromise=void 0,e._backpressureChangePromise_resolve=void 0,br(e,!0),e._transformStreamController=void 0}(this,c((e=>{b=e})),s,u,i,l),function(e,t){const r=Object.create(TransformStreamDefaultController.prototype);let o,n;o=void 0!==t.transform?e=>t.transform(e,r):e=>{try{return pr(r,e),d(void 0)}catch(e){return f(e)}};n=void 0!==t.flush?()=>t.flush(r):()=>d(void 0);!function(e,t,r,o){t._controlledTransformStream=e,e._transformStreamController=t,t._transformAlgorithm=r,t._flushAlgorithm=o}(e,r,o,n)}(this,a),void 0!==a.start?b(a.start(this._transformStreamController)):b(void 0)}get readable(){if(!cr(this))throw gr("readable");return this._readable}get writable(){if(!cr(this))throw gr("writable");return this._writable}}function cr(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_transformStreamController")&&e instanceof TransformStream)}function dr(e,t){vr(e,t),fr(e,t)}function fr(e,t){_r(e._transformStreamController),function(e,t){e._writableController.error(t);"writable"===e._writableState&&qr(e,t)}(e,t),e._backpressure&&br(e,!1)}function br(e,t){void 0!==e._backpressureChangePromise&&e._backpressureChangePromise_resolve(),e._backpressureChangePromise=c((t=>{e._backpressureChangePromise_resolve=t})),e._backpressure=t}Object.defineProperties(TransformStream.prototype,{readable:{enumerable:!0},writable:{enumerable:!0}}),"symbol"==typeof t.toStringTag&&Object.defineProperty(TransformStream.prototype,t.toStringTag,{value:"TransformStream",configurable:!0});class TransformStreamDefaultController{constructor(){throw new TypeError("Illegal constructor")}get desiredSize(){if(!hr(this))throw yr("desiredSize");return Rr(this._controlledTransformStream)}enqueue(e){if(!hr(this))throw yr("enqueue");pr(this,e)}error(e){if(!hr(this))throw yr("error");var t;t=e,dr(this._controlledTransformStream,t)}terminate(){if(!hr(this))throw yr("terminate");!function(e){const t=e._controlledTransformStream;Sr(t)&&wr(t);const r=new TypeError("TransformStream terminated");fr(t,r)}(this)}}function hr(e){return!!o(e)&&(!!Object.prototype.hasOwnProperty.call(e,"_controlledTransformStream")&&e instanceof TransformStreamDefaultController)}function _r(e){e._transformAlgorithm=void 0,e._flushAlgorithm=void 0}function pr(e,t){const r=e._controlledTransformStream;if(!Sr(r))throw new TypeError("Readable side is not in a state that permits enqueue");try{!function(e,t){e._readablePulling=!1;try{e._readableController.enqueue(t)}catch(t){throw vr(e,t),t}}(r,t)}catch(e){throw fr(r,e),r._readableStoredError}const o=function(e){return!function(e){if(!Sr(e))return!1;if(e._readablePulling)return!0;if(Rr(e)>0)return!0;return!1}(e)}(r);o!==r._backpressure&&br(r,!0)}function mr(e,t){return m(e._transformAlgorithm(t),void 0,(t=>{throw dr(e._controlledTransformStream,t),t}))}function yr(e){return new TypeError(`TransformStreamDefaultController.prototype.${e} can only be used on a TransformStreamDefaultController`)}function gr(e){return new TypeError(`TransformStream.prototype.${e} can only be used on a TransformStream`)}function Sr(e){return!e._readableCloseRequested&&"readable"===e._readableState}function wr(e){e._readableState="closed",e._readableCloseRequested=!0,e._readableController.close()}function vr(e,t){"readable"===e._readableState&&(e._readableState="errored",e._readableStoredError=t),e._readableController.error(t)}function Rr(e){return e._readableController.desiredSize}function Tr(e,t){"writable"!==e._writableState?Cr(e):qr(e,t)}function qr(e,t){e._writableState="erroring",e._writableStoredError=t,!function(e){return e._writableHasInFlightOperation}(e)&&e._writableStarted&&Cr(e)}function Cr(e){e._writableState="errored"}function Pr(e){"erroring"===e._writableState&&Cr(e)}Object.defineProperties(TransformStreamDefaultController.prototype,{enqueue:{enumerable:!0},error:{enumerable:!0},terminate:{enumerable:!0},desiredSize:{enumerable:!0}}),a(TransformStreamDefaultController.prototype.enqueue,"enqueue"),a(TransformStreamDefaultController.prototype.error,"error"),a(TransformStreamDefaultController.prototype.terminate,"terminate"),"symbol"==typeof t.toStringTag&&Object.defineProperty(TransformStreamDefaultController.prototype,t.toStringTag,{value:"TransformStreamDefaultController",configurable:!0}),e.ByteLengthQueuingStrategy=ByteLengthQueuingStrategy,e.CountQueuingStrategy=CountQueuingStrategy,e.ReadableByteStreamController=ReadableByteStreamController,e.ReadableStream=ReadableStream,e.ReadableStreamBYOBReader=ReadableStreamBYOBReader,e.ReadableStreamBYOBRequest=ReadableStreamBYOBRequest,e.ReadableStreamDefaultController=ReadableStreamDefaultController,e.ReadableStreamDefaultReader=ReadableStreamDefaultReader,e.TransformStream=TransformStream,e.TransformStreamDefaultController=TransformStreamDefaultController,e.WritableStream=WritableStream,e.WritableStreamDefaultController=WritableStreamDefaultController,e.WritableStreamDefaultWriter=WritableStreamDefaultWriter,Object.defineProperty(e,"__esModule",{value:!0})})); + + +/***/ }), + +/***/ 845: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; +/*! + * humanize-ms - index.js + * Copyright(c) 2014 dead_horse + * MIT Licensed + */ + + + +/** + * Module dependencies. + */ + +var util = __nccwpck_require__(3837); +var ms = __nccwpck_require__(900); + +module.exports = function (t) { + if (typeof t === 'number') return t; + var r = ms(t); + if (r === undefined) { + var err = new Error(util.format('humanize-ms(%j) result undefined', t)); + console.warn(err.stack); + } + return r; +}; + + +/***/ }), + +/***/ 3287: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +/*! + * is-plain-object + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + */ + +function isObject(o) { + return Object.prototype.toString.call(o) === '[object Object]'; +} + +function isPlainObject(o) { + var ctor,prot; + + if (isObject(o) === false) return false; + + // If has modified constructor + ctor = o.constructor; + if (ctor === undefined) return true; + + // If has modified prototype + prot = ctor.prototype; + if (isObject(prot) === false) return false; + + // If constructor does not have an Object-specific method + if (prot.hasOwnProperty('isPrototypeOf') === false) { + return false; + } + + // Most likely a plain Object + return true; +} + +exports.isPlainObject = isPlainObject; + + +/***/ }), + +/***/ 900: +/***/ ((module) => { + +/** + * Helpers. + */ + +var s = 1000; +var m = s * 60; +var h = m * 60; +var d = h * 24; +var w = d * 7; +var y = d * 365.25; + +/** + * Parse or format the given `val`. + * + * Options: + * + * - `long` verbose formatting [false] + * + * @param {String|Number} val + * @param {Object} [options] + * @throws {Error} throw an error if val is not a non-empty string or a number + * @return {String|Number} + * @api public + */ + +module.exports = function(val, options) { + options = options || {}; + var type = typeof val; + if (type === 'string' && val.length > 0) { + return parse(val); + } else if (type === 'number' && isFinite(val)) { + return options.long ? fmtLong(val) : fmtShort(val); + } + throw new Error( + 'val is not a non-empty string or a valid number. val=' + + JSON.stringify(val) + ); +}; + +/** + * Parse the given `str` and return milliseconds. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function parse(str) { + str = String(str); + if (str.length > 100) { + return; + } + var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec( + str + ); + if (!match) { + return; + } + var n = parseFloat(match[1]); + var type = (match[2] || 'ms').toLowerCase(); + switch (type) { + case 'years': + case 'year': + case 'yrs': + case 'yr': + case 'y': + return n * y; + case 'weeks': + case 'week': + case 'w': + return n * w; + case 'days': + case 'day': + case 'd': + return n * d; + case 'hours': + case 'hour': + case 'hrs': + case 'hr': + case 'h': + return n * h; + case 'minutes': + case 'minute': + case 'mins': + case 'min': + case 'm': + return n * m; + case 'seconds': + case 'second': + case 'secs': + case 'sec': + case 's': + return n * s; + case 'milliseconds': + case 'millisecond': + case 'msecs': + case 'msec': + case 'ms': + return n; + default: + return undefined; + } +} + +/** + * Short format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtShort(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return Math.round(ms / d) + 'd'; + } + if (msAbs >= h) { + return Math.round(ms / h) + 'h'; + } + if (msAbs >= m) { + return Math.round(ms / m) + 'm'; + } + if (msAbs >= s) { + return Math.round(ms / s) + 's'; + } + return ms + 'ms'; +} + +/** + * Long format for `ms`. + * + * @param {Number} ms + * @return {String} + * @api private + */ + +function fmtLong(ms) { + var msAbs = Math.abs(ms); + if (msAbs >= d) { + return plural(ms, msAbs, d, 'day'); + } + if (msAbs >= h) { + return plural(ms, msAbs, h, 'hour'); + } + if (msAbs >= m) { + return plural(ms, msAbs, m, 'minute'); + } + if (msAbs >= s) { + return plural(ms, msAbs, s, 'second'); + } + return ms + ' ms'; +} + +/** + * Pluralization helper. + */ + +function plural(ms, msAbs, n, name) { + var isPlural = msAbs >= n * 1.5; + return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : ''); +} + + +/***/ }), + +/***/ 7760: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +/*! node-domexception. MIT License. Jimmy WƤrting */ + +if (!globalThis.DOMException) { + try { + const { MessageChannel } = __nccwpck_require__(1267), + port = new MessageChannel().port1, + ab = new ArrayBuffer() + port.postMessage(ab, [ab, ab]) + } catch (err) { + err.constructor.name === 'DOMException' && ( + globalThis.DOMException = err.constructor + ) + } +} + +module.exports = globalThis.DOMException + + +/***/ }), + +/***/ 467: +/***/ ((module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } + +var Stream = _interopDefault(__nccwpck_require__(2781)); +var http = _interopDefault(__nccwpck_require__(3685)); +var Url = _interopDefault(__nccwpck_require__(7310)); +var whatwgUrl = _interopDefault(__nccwpck_require__(3323)); +var https = _interopDefault(__nccwpck_require__(5687)); +var zlib = _interopDefault(__nccwpck_require__(9796)); + +// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js + +// fix for "Readable" isn't a named export issue +const Readable = Stream.Readable; + +const BUFFER = Symbol('buffer'); +const TYPE = Symbol('type'); + +class Blob { + constructor() { + this[TYPE] = ''; + + const blobParts = arguments[0]; + const options = arguments[1]; + + const buffers = []; + let size = 0; + + if (blobParts) { + const a = blobParts; + const length = Number(a.length); + for (let i = 0; i < length; i++) { + const element = a[i]; + let buffer; + if (element instanceof Buffer) { + buffer = element; + } else if (ArrayBuffer.isView(element)) { + buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength); + } else if (element instanceof ArrayBuffer) { + buffer = Buffer.from(element); + } else if (element instanceof Blob) { + buffer = element[BUFFER]; + } else { + buffer = Buffer.from(typeof element === 'string' ? element : String(element)); + } + size += buffer.length; + buffers.push(buffer); + } + } + + this[BUFFER] = Buffer.concat(buffers); + + let type = options && options.type !== undefined && String(options.type).toLowerCase(); + if (type && !/[^\u0020-\u007E]/.test(type)) { + this[TYPE] = type; + } + } + get size() { + return this[BUFFER].length; + } + get type() { + return this[TYPE]; + } + text() { + return Promise.resolve(this[BUFFER].toString()); + } + arrayBuffer() { + const buf = this[BUFFER]; + const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + return Promise.resolve(ab); + } + stream() { + const readable = new Readable(); + readable._read = function () {}; + readable.push(this[BUFFER]); + readable.push(null); + return readable; + } + toString() { + return '[object Blob]'; + } + slice() { + const size = this.size; + + const start = arguments[0]; + const end = arguments[1]; + let relativeStart, relativeEnd; + if (start === undefined) { + relativeStart = 0; + } else if (start < 0) { + relativeStart = Math.max(size + start, 0); + } else { + relativeStart = Math.min(start, size); + } + if (end === undefined) { + relativeEnd = size; + } else if (end < 0) { + relativeEnd = Math.max(size + end, 0); + } else { + relativeEnd = Math.min(end, size); + } + const span = Math.max(relativeEnd - relativeStart, 0); + + const buffer = this[BUFFER]; + const slicedBuffer = buffer.slice(relativeStart, relativeStart + span); + const blob = new Blob([], { type: arguments[2] }); + blob[BUFFER] = slicedBuffer; + return blob; + } +} + +Object.defineProperties(Blob.prototype, { + size: { enumerable: true }, + type: { enumerable: true }, + slice: { enumerable: true } +}); + +Object.defineProperty(Blob.prototype, Symbol.toStringTag, { + value: 'Blob', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * fetch-error.js + * + * FetchError interface for operational errors + */ + +/** + * Create FetchError instance + * + * @param String message Error message for human + * @param String type Error type for machine + * @param String systemError For Node.js system error + * @return FetchError + */ +function FetchError(message, type, systemError) { + Error.call(this, message); + + this.message = message; + this.type = type; + + // when err.type is `system`, err.code contains system error code + if (systemError) { + this.code = this.errno = systemError.code; + } + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +FetchError.prototype = Object.create(Error.prototype); +FetchError.prototype.constructor = FetchError; +FetchError.prototype.name = 'FetchError'; + +let convert; +try { + convert = (__nccwpck_require__(3975).convert); +} catch (e) {} + +const INTERNALS = Symbol('Body internals'); + +// fix an issue where "PassThrough" isn't a named export for node <10 +const PassThrough = Stream.PassThrough; + +/** + * Body mixin + * + * Ref: https://fetch.spec.whatwg.org/#body + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +function Body(body) { + var _this = this; + + var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, + _ref$size = _ref.size; + + let size = _ref$size === undefined ? 0 : _ref$size; + var _ref$timeout = _ref.timeout; + let timeout = _ref$timeout === undefined ? 0 : _ref$timeout; + + if (body == null) { + // body is undefined or null + body = null; + } else if (isURLSearchParams(body)) { + // body is a URLSearchParams + body = Buffer.from(body.toString()); + } else if (isBlob(body)) ; else if (Buffer.isBuffer(body)) ; else if (Object.prototype.toString.call(body) === '[object ArrayBuffer]') { + // body is ArrayBuffer + body = Buffer.from(body); + } else if (ArrayBuffer.isView(body)) { + // body is ArrayBufferView + body = Buffer.from(body.buffer, body.byteOffset, body.byteLength); + } else if (body instanceof Stream) ; else { + // none of the above + // coerce to string then buffer + body = Buffer.from(String(body)); + } + this[INTERNALS] = { + body, + disturbed: false, + error: null + }; + this.size = size; + this.timeout = timeout; + + if (body instanceof Stream) { + body.on('error', function (err) { + const error = err.name === 'AbortError' ? err : new FetchError(`Invalid response body while trying to fetch ${_this.url}: ${err.message}`, 'system', err); + _this[INTERNALS].error = error; + }); + } +} + +Body.prototype = { + get body() { + return this[INTERNALS].body; + }, + + get bodyUsed() { + return this[INTERNALS].disturbed; + }, + + /** + * Decode response as ArrayBuffer + * + * @return Promise + */ + arrayBuffer() { + return consumeBody.call(this).then(function (buf) { + return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength); + }); + }, + + /** + * Return raw response as Blob + * + * @return Promise + */ + blob() { + let ct = this.headers && this.headers.get('content-type') || ''; + return consumeBody.call(this).then(function (buf) { + return Object.assign( + // Prevent copying + new Blob([], { + type: ct.toLowerCase() + }), { + [BUFFER]: buf + }); + }); + }, + + /** + * Decode response as json + * + * @return Promise + */ + json() { + var _this2 = this; + + return consumeBody.call(this).then(function (buffer) { + try { + return JSON.parse(buffer.toString()); + } catch (err) { + return Body.Promise.reject(new FetchError(`invalid json response body at ${_this2.url} reason: ${err.message}`, 'invalid-json')); + } + }); + }, + + /** + * Decode response as text + * + * @return Promise + */ + text() { + return consumeBody.call(this).then(function (buffer) { + return buffer.toString(); + }); + }, + + /** + * Decode response as buffer (non-spec api) + * + * @return Promise + */ + buffer() { + return consumeBody.call(this); + }, + + /** + * Decode response as text, while automatically detecting the encoding and + * trying to decode to UTF-8 (non-spec api) + * + * @return Promise + */ + textConverted() { + var _this3 = this; + + return consumeBody.call(this).then(function (buffer) { + return convertBody(buffer, _this3.headers); + }); + } +}; + +// In browsers, all properties are enumerable. +Object.defineProperties(Body.prototype, { + body: { enumerable: true }, + bodyUsed: { enumerable: true }, + arrayBuffer: { enumerable: true }, + blob: { enumerable: true }, + json: { enumerable: true }, + text: { enumerable: true } +}); + +Body.mixIn = function (proto) { + for (const name of Object.getOwnPropertyNames(Body.prototype)) { + // istanbul ignore else: future proof + if (!(name in proto)) { + const desc = Object.getOwnPropertyDescriptor(Body.prototype, name); + Object.defineProperty(proto, name, desc); + } + } +}; + +/** + * Consume and convert an entire Body to a Buffer. + * + * Ref: https://fetch.spec.whatwg.org/#concept-body-consume-body + * + * @return Promise + */ +function consumeBody() { + var _this4 = this; + + if (this[INTERNALS].disturbed) { + return Body.Promise.reject(new TypeError(`body used already for: ${this.url}`)); + } + + this[INTERNALS].disturbed = true; + + if (this[INTERNALS].error) { + return Body.Promise.reject(this[INTERNALS].error); + } + + let body = this.body; + + // body is null + if (body === null) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is blob + if (isBlob(body)) { + body = body.stream(); + } + + // body is buffer + if (Buffer.isBuffer(body)) { + return Body.Promise.resolve(body); + } + + // istanbul ignore if: should never happen + if (!(body instanceof Stream)) { + return Body.Promise.resolve(Buffer.alloc(0)); + } + + // body is stream + // get ready to actually consume the body + let accum = []; + let accumBytes = 0; + let abort = false; + + return new Body.Promise(function (resolve, reject) { + let resTimeout; + + // allow timeout on slow response body + if (_this4.timeout) { + resTimeout = setTimeout(function () { + abort = true; + reject(new FetchError(`Response timeout while trying to fetch ${_this4.url} (over ${_this4.timeout}ms)`, 'body-timeout')); + }, _this4.timeout); + } + + // handle stream errors + body.on('error', function (err) { + if (err.name === 'AbortError') { + // if the request was aborted, reject with this Error + abort = true; + reject(err); + } else { + // other errors, such as incorrect content-encoding + reject(new FetchError(`Invalid response body while trying to fetch ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + + body.on('data', function (chunk) { + if (abort || chunk === null) { + return; + } + + if (_this4.size && accumBytes + chunk.length > _this4.size) { + abort = true; + reject(new FetchError(`content size at ${_this4.url} over limit: ${_this4.size}`, 'max-size')); + return; + } + + accumBytes += chunk.length; + accum.push(chunk); + }); + + body.on('end', function () { + if (abort) { + return; + } + + clearTimeout(resTimeout); + + try { + resolve(Buffer.concat(accum, accumBytes)); + } catch (err) { + // handle streams that have accumulated too much data (issue #414) + reject(new FetchError(`Could not create Buffer from response body for ${_this4.url}: ${err.message}`, 'system', err)); + } + }); + }); +} + +/** + * Detect buffer encoding and convert to target encoding + * ref: http://www.w3.org/TR/2011/WD-html5-20110113/parsing.html#determining-the-character-encoding + * + * @param Buffer buffer Incoming buffer + * @param String encoding Target encoding + * @return String + */ +function convertBody(buffer, headers) { + if (typeof convert !== 'function') { + throw new Error('The package `encoding` must be installed to use the textConverted() function'); + } + + const ct = headers.get('content-type'); + let charset = 'utf-8'; + let res, str; + + // header + if (ct) { + res = /charset=([^;]*)/i.exec(ct); + } + + // no charset in content type, peek at response body for at most 1024 bytes + str = buffer.slice(0, 1024).toString(); + + // html5 + if (!res && str) { + res = / 0 && arguments[0] !== undefined ? arguments[0] : undefined; + + this[MAP] = Object.create(null); + + if (init instanceof Headers) { + const rawHeaders = init.raw(); + const headerNames = Object.keys(rawHeaders); + + for (const headerName of headerNames) { + for (const value of rawHeaders[headerName]) { + this.append(headerName, value); + } + } + + return; + } + + // We don't worry about converting prop to ByteString here as append() + // will handle it. + if (init == null) ; else if (typeof init === 'object') { + const method = init[Symbol.iterator]; + if (method != null) { + if (typeof method !== 'function') { + throw new TypeError('Header pairs must be iterable'); + } + + // sequence> + // Note: per spec we have to first exhaust the lists then process them + const pairs = []; + for (const pair of init) { + if (typeof pair !== 'object' || typeof pair[Symbol.iterator] !== 'function') { + throw new TypeError('Each header pair must be iterable'); + } + pairs.push(Array.from(pair)); + } + + for (const pair of pairs) { + if (pair.length !== 2) { + throw new TypeError('Each header pair must be a name/value tuple'); + } + this.append(pair[0], pair[1]); + } + } else { + // record + for (const key of Object.keys(init)) { + const value = init[key]; + this.append(key, value); + } + } + } else { + throw new TypeError('Provided initializer must be an object'); + } + } + + /** + * Return combined header value given name + * + * @param String name Header name + * @return Mixed + */ + get(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key === undefined) { + return null; + } + + return this[MAP][key].join(', '); + } + + /** + * Iterate over all headers + * + * @param Function callback Executed for each item with parameters (value, name, thisArg) + * @param Boolean thisArg `this` context for callback function + * @return Void + */ + forEach(callback) { + let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined; + + let pairs = getHeaders(this); + let i = 0; + while (i < pairs.length) { + var _pairs$i = pairs[i]; + const name = _pairs$i[0], + value = _pairs$i[1]; + + callback.call(thisArg, value, name, this); + pairs = getHeaders(this); + i++; + } + } + + /** + * Overwrite header values given name + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + set(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + this[MAP][key !== undefined ? key : name] = [value]; + } + + /** + * Append a value onto existing header + * + * @param String name Header name + * @param String value Header value + * @return Void + */ + append(name, value) { + name = `${name}`; + value = `${value}`; + validateName(name); + validateValue(value); + const key = find(this[MAP], name); + if (key !== undefined) { + this[MAP][key].push(value); + } else { + this[MAP][name] = [value]; + } + } + + /** + * Check for header name existence + * + * @param String name Header name + * @return Boolean + */ + has(name) { + name = `${name}`; + validateName(name); + return find(this[MAP], name) !== undefined; + } + + /** + * Delete all header values given name + * + * @param String name Header name + * @return Void + */ + delete(name) { + name = `${name}`; + validateName(name); + const key = find(this[MAP], name); + if (key !== undefined) { + delete this[MAP][key]; + } + } + + /** + * Return raw headers (non-spec api) + * + * @return Object + */ + raw() { + return this[MAP]; + } + + /** + * Get an iterator on keys. + * + * @return Iterator + */ + keys() { + return createHeadersIterator(this, 'key'); + } + + /** + * Get an iterator on values. + * + * @return Iterator + */ + values() { + return createHeadersIterator(this, 'value'); + } + + /** + * Get an iterator on entries. + * + * This is the default iterator of the Headers object. + * + * @return Iterator + */ + [Symbol.iterator]() { + return createHeadersIterator(this, 'key+value'); + } +} +Headers.prototype.entries = Headers.prototype[Symbol.iterator]; + +Object.defineProperty(Headers.prototype, Symbol.toStringTag, { + value: 'Headers', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Headers.prototype, { + get: { enumerable: true }, + forEach: { enumerable: true }, + set: { enumerable: true }, + append: { enumerable: true }, + has: { enumerable: true }, + delete: { enumerable: true }, + keys: { enumerable: true }, + values: { enumerable: true }, + entries: { enumerable: true } +}); + +function getHeaders(headers) { + let kind = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'key+value'; + + const keys = Object.keys(headers[MAP]).sort(); + return keys.map(kind === 'key' ? function (k) { + return k.toLowerCase(); + } : kind === 'value' ? function (k) { + return headers[MAP][k].join(', '); + } : function (k) { + return [k.toLowerCase(), headers[MAP][k].join(', ')]; + }); +} + +const INTERNAL = Symbol('internal'); + +function createHeadersIterator(target, kind) { + const iterator = Object.create(HeadersIteratorPrototype); + iterator[INTERNAL] = { + target, + kind, + index: 0 + }; + return iterator; +} + +const HeadersIteratorPrototype = Object.setPrototypeOf({ + next() { + // istanbul ignore if + if (!this || Object.getPrototypeOf(this) !== HeadersIteratorPrototype) { + throw new TypeError('Value of `this` is not a HeadersIterator'); + } + + var _INTERNAL = this[INTERNAL]; + const target = _INTERNAL.target, + kind = _INTERNAL.kind, + index = _INTERNAL.index; + + const values = getHeaders(target, kind); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + this[INTERNAL].index = index + 1; + + return { + value: values[index], + done: false + }; + } +}, Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))); + +Object.defineProperty(HeadersIteratorPrototype, Symbol.toStringTag, { + value: 'HeadersIterator', + writable: false, + enumerable: false, + configurable: true +}); + +/** + * Export the Headers object in a form that Node.js can consume. + * + * @param Headers headers + * @return Object + */ +function exportNodeCompatibleHeaders(headers) { + const obj = Object.assign({ __proto__: null }, headers[MAP]); + + // http.request() only supports string as Host header. This hack makes + // specifying custom Host header possible. + const hostHeaderKey = find(headers[MAP], 'Host'); + if (hostHeaderKey !== undefined) { + obj[hostHeaderKey] = obj[hostHeaderKey][0]; + } + + return obj; +} + +/** + * Create a Headers object from an object of headers, ignoring those that do + * not conform to HTTP grammar productions. + * + * @param Object obj Object of headers + * @return Headers + */ +function createHeadersLenient(obj) { + const headers = new Headers(); + for (const name of Object.keys(obj)) { + if (invalidTokenRegex.test(name)) { + continue; + } + if (Array.isArray(obj[name])) { + for (const val of obj[name]) { + if (invalidHeaderCharRegex.test(val)) { + continue; + } + if (headers[MAP][name] === undefined) { + headers[MAP][name] = [val]; + } else { + headers[MAP][name].push(val); + } + } + } else if (!invalidHeaderCharRegex.test(obj[name])) { + headers[MAP][name] = [obj[name]]; + } + } + return headers; +} + +const INTERNALS$1 = Symbol('Response internals'); + +// fix an issue where "STATUS_CODES" aren't a named export for node <10 +const STATUS_CODES = http.STATUS_CODES; + +/** + * Response class + * + * @param Stream body Readable stream + * @param Object opts Response options + * @return Void + */ +class Response { + constructor() { + let body = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + Body.call(this, body, opts); + + const status = opts.status || 200; + const headers = new Headers(opts.headers); + + if (body != null && !headers.has('Content-Type')) { + const contentType = extractContentType(body); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + this[INTERNALS$1] = { + url: opts.url, + status, + statusText: opts.statusText || STATUS_CODES[status], + headers, + counter: opts.counter + }; + } + + get url() { + return this[INTERNALS$1].url || ''; + } + + get status() { + return this[INTERNALS$1].status; + } + + /** + * Convenience property representing if the request ended normally + */ + get ok() { + return this[INTERNALS$1].status >= 200 && this[INTERNALS$1].status < 300; + } + + get redirected() { + return this[INTERNALS$1].counter > 0; + } + + get statusText() { + return this[INTERNALS$1].statusText; + } + + get headers() { + return this[INTERNALS$1].headers; + } + + /** + * Clone this response + * + * @return Response + */ + clone() { + return new Response(clone(this), { + url: this.url, + status: this.status, + statusText: this.statusText, + headers: this.headers, + ok: this.ok, + redirected: this.redirected + }); + } +} + +Body.mixIn(Response.prototype); + +Object.defineProperties(Response.prototype, { + url: { enumerable: true }, + status: { enumerable: true }, + ok: { enumerable: true }, + redirected: { enumerable: true }, + statusText: { enumerable: true }, + headers: { enumerable: true }, + clone: { enumerable: true } +}); + +Object.defineProperty(Response.prototype, Symbol.toStringTag, { + value: 'Response', + writable: false, + enumerable: false, + configurable: true +}); + +const INTERNALS$2 = Symbol('Request internals'); +const URL = Url.URL || whatwgUrl.URL; + +// fix an issue where "format", "parse" aren't a named export for node <10 +const parse_url = Url.parse; +const format_url = Url.format; + +/** + * Wrapper around `new URL` to handle arbitrary URLs + * + * @param {string} urlStr + * @return {void} + */ +function parseURL(urlStr) { + /* + Check whether the URL is absolute or not + Scheme: https://tools.ietf.org/html/rfc3986#section-3.1 + Absolute URL: https://tools.ietf.org/html/rfc3986#section-4.3 + */ + if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.exec(urlStr)) { + urlStr = new URL(urlStr).toString(); + } + + // Fallback to old implementation for arbitrary URLs + return parse_url(urlStr); +} + +const streamDestructionSupported = 'destroy' in Stream.Readable.prototype; + +/** + * Check if a value is an instance of Request. + * + * @param Mixed input + * @return Boolean + */ +function isRequest(input) { + return typeof input === 'object' && typeof input[INTERNALS$2] === 'object'; +} + +function isAbortSignal(signal) { + const proto = signal && typeof signal === 'object' && Object.getPrototypeOf(signal); + return !!(proto && proto.constructor.name === 'AbortSignal'); +} + +/** + * Request class + * + * @param Mixed input Url or Request instance + * @param Object init Custom options + * @return Void + */ +class Request { + constructor(input) { + let init = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + let parsedURL; + + // normalize input + if (!isRequest(input)) { + if (input && input.href) { + // in order to support Node.js' Url objects; though WHATWG's URL objects + // will fall into this branch also (since their `toString()` will return + // `href` property anyway) + parsedURL = parseURL(input.href); + } else { + // coerce input to a string before attempting to parse + parsedURL = parseURL(`${input}`); + } + input = {}; + } else { + parsedURL = parseURL(input.url); + } + + let method = init.method || input.method || 'GET'; + method = method.toUpperCase(); + + if ((init.body != null || isRequest(input) && input.body !== null) && (method === 'GET' || method === 'HEAD')) { + throw new TypeError('Request with GET/HEAD method cannot have body'); + } + + let inputBody = init.body != null ? init.body : isRequest(input) && input.body !== null ? clone(input) : null; + + Body.call(this, inputBody, { + timeout: init.timeout || input.timeout || 0, + size: init.size || input.size || 0 + }); + + const headers = new Headers(init.headers || input.headers || {}); + + if (inputBody != null && !headers.has('Content-Type')) { + const contentType = extractContentType(inputBody); + if (contentType) { + headers.append('Content-Type', contentType); + } + } + + let signal = isRequest(input) ? input.signal : null; + if ('signal' in init) signal = init.signal; + + if (signal != null && !isAbortSignal(signal)) { + throw new TypeError('Expected signal to be an instanceof AbortSignal'); + } + + this[INTERNALS$2] = { + method, + redirect: init.redirect || input.redirect || 'follow', + headers, + parsedURL, + signal + }; + + // node-fetch-only options + this.follow = init.follow !== undefined ? init.follow : input.follow !== undefined ? input.follow : 20; + this.compress = init.compress !== undefined ? init.compress : input.compress !== undefined ? input.compress : true; + this.counter = init.counter || input.counter || 0; + this.agent = init.agent || input.agent; + } + + get method() { + return this[INTERNALS$2].method; + } + + get url() { + return format_url(this[INTERNALS$2].parsedURL); + } + + get headers() { + return this[INTERNALS$2].headers; + } + + get redirect() { + return this[INTERNALS$2].redirect; + } + + get signal() { + return this[INTERNALS$2].signal; + } + + /** + * Clone this request + * + * @return Request + */ + clone() { + return new Request(this); + } +} + +Body.mixIn(Request.prototype); + +Object.defineProperty(Request.prototype, Symbol.toStringTag, { + value: 'Request', + writable: false, + enumerable: false, + configurable: true +}); + +Object.defineProperties(Request.prototype, { + method: { enumerable: true }, + url: { enumerable: true }, + headers: { enumerable: true }, + redirect: { enumerable: true }, + clone: { enumerable: true }, + signal: { enumerable: true } +}); + +/** + * Convert a Request to Node.js http request options. + * + * @param Request A Request instance + * @return Object The options object to be passed to http.request + */ +function getNodeRequestOptions(request) { + const parsedURL = request[INTERNALS$2].parsedURL; + const headers = new Headers(request[INTERNALS$2].headers); + + // fetch step 1.3 + if (!headers.has('Accept')) { + headers.set('Accept', '*/*'); + } + + // Basic fetch + if (!parsedURL.protocol || !parsedURL.hostname) { + throw new TypeError('Only absolute URLs are supported'); + } + + if (!/^https?:$/.test(parsedURL.protocol)) { + throw new TypeError('Only HTTP(S) protocols are supported'); + } + + if (request.signal && request.body instanceof Stream.Readable && !streamDestructionSupported) { + throw new Error('Cancellation of streamed requests with AbortSignal is not supported in node < 8'); + } + + // HTTP-network-or-cache fetch steps 2.4-2.7 + let contentLengthValue = null; + if (request.body == null && /^(POST|PUT)$/i.test(request.method)) { + contentLengthValue = '0'; + } + if (request.body != null) { + const totalBytes = getTotalBytes(request); + if (typeof totalBytes === 'number') { + contentLengthValue = String(totalBytes); + } + } + if (contentLengthValue) { + headers.set('Content-Length', contentLengthValue); + } + + // HTTP-network-or-cache fetch step 2.11 + if (!headers.has('User-Agent')) { + headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)'); + } + + // HTTP-network-or-cache fetch step 2.15 + if (request.compress && !headers.has('Accept-Encoding')) { + headers.set('Accept-Encoding', 'gzip,deflate'); + } + + let agent = request.agent; + if (typeof agent === 'function') { + agent = agent(parsedURL); + } + + if (!headers.has('Connection') && !agent) { + headers.set('Connection', 'close'); + } + + // HTTP-network fetch step 4.2 + // chunked encoding is handled by Node.js + + return Object.assign({}, parsedURL, { + method: request.method, + headers: exportNodeCompatibleHeaders(headers), + agent + }); +} + +/** + * abort-error.js + * + * AbortError interface for cancelled requests + */ + +/** + * Create AbortError instance + * + * @param String message Error message for human + * @return AbortError + */ +function AbortError(message) { + Error.call(this, message); + + this.type = 'aborted'; + this.message = message; + + // hide custom error implementation details from end-users + Error.captureStackTrace(this, this.constructor); +} + +AbortError.prototype = Object.create(Error.prototype); +AbortError.prototype.constructor = AbortError; +AbortError.prototype.name = 'AbortError'; + +const URL$1 = Url.URL || whatwgUrl.URL; + +// fix an issue where "PassThrough", "resolve" aren't a named export for node <10 +const PassThrough$1 = Stream.PassThrough; + +const isDomainOrSubdomain = function isDomainOrSubdomain(destination, original) { + const orig = new URL$1(original).hostname; + const dest = new URL$1(destination).hostname; + + return orig === dest || orig[orig.length - dest.length - 1] === '.' && orig.endsWith(dest); +}; + +/** + * Fetch function + * + * @param Mixed url Absolute url or Request instance + * @param Object opts Fetch options + * @return Promise + */ +function fetch(url, opts) { + + // allow custom promise + if (!fetch.Promise) { + throw new Error('native promise missing, set fetch.Promise to your favorite alternative'); + } + + Body.Promise = fetch.Promise; + + // wrap http.request into fetch + return new fetch.Promise(function (resolve, reject) { + // build request object + const request = new Request(url, opts); + const options = getNodeRequestOptions(request); + + const send = (options.protocol === 'https:' ? https : http).request; + const signal = request.signal; + + let response = null; + + const abort = function abort() { + let error = new AbortError('The user aborted a request.'); + reject(error); + if (request.body && request.body instanceof Stream.Readable) { + request.body.destroy(error); + } + if (!response || !response.body) return; + response.body.emit('error', error); + }; + + if (signal && signal.aborted) { + abort(); + return; + } + + const abortAndFinalize = function abortAndFinalize() { + abort(); + finalize(); + }; + + // send request + const req = send(options); + let reqTimeout; + + if (signal) { + signal.addEventListener('abort', abortAndFinalize); + } + + function finalize() { + req.abort(); + if (signal) signal.removeEventListener('abort', abortAndFinalize); + clearTimeout(reqTimeout); + } + + if (request.timeout) { + req.once('socket', function (socket) { + reqTimeout = setTimeout(function () { + reject(new FetchError(`network timeout at: ${request.url}`, 'request-timeout')); + finalize(); + }, request.timeout); + }); + } + + req.on('error', function (err) { + reject(new FetchError(`request to ${request.url} failed, reason: ${err.message}`, 'system', err)); + finalize(); + }); + + req.on('response', function (res) { + clearTimeout(reqTimeout); + + const headers = createHeadersLenient(res.headers); + + // HTTP fetch step 5 + if (fetch.isRedirect(res.statusCode)) { + // HTTP fetch step 5.2 + const location = headers.get('Location'); + + // HTTP fetch step 5.3 + let locationURL = null; + try { + locationURL = location === null ? null : new URL$1(location, request.url).toString(); + } catch (err) { + // error here can only be invalid URL in Location: header + // do not throw when options.redirect == manual + // let the user extract the errorneous redirect URL + if (request.redirect !== 'manual') { + reject(new FetchError(`uri requested responds with an invalid redirect URL: ${location}`, 'invalid-redirect')); + finalize(); + return; + } + } + + // HTTP fetch step 5.5 + switch (request.redirect) { + case 'error': + reject(new FetchError(`uri requested responds with a redirect, redirect mode is set to error: ${request.url}`, 'no-redirect')); + finalize(); + return; + case 'manual': + // node-fetch-specific step: make manual redirect a bit easier to use by setting the Location header value to the resolved URL. + if (locationURL !== null) { + // handle corrupted header + try { + headers.set('Location', locationURL); + } catch (err) { + // istanbul ignore next: nodejs server prevent invalid response headers, we can't test this through normal request + reject(err); + } + } + break; + case 'follow': + // HTTP-redirect fetch step 2 + if (locationURL === null) { + break; + } + + // HTTP-redirect fetch step 5 + if (request.counter >= request.follow) { + reject(new FetchError(`maximum redirect reached at: ${request.url}`, 'max-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 6 (counter increment) + // Create a new Request object. + const requestOpts = { + headers: new Headers(request.headers), + follow: request.follow, + counter: request.counter + 1, + agent: request.agent, + compress: request.compress, + method: request.method, + body: request.body, + signal: request.signal, + timeout: request.timeout, + size: request.size + }; + + if (!isDomainOrSubdomain(request.url, locationURL)) { + for (const name of ['authorization', 'www-authenticate', 'cookie', 'cookie2']) { + requestOpts.headers.delete(name); + } + } + + // HTTP-redirect fetch step 9 + if (res.statusCode !== 303 && request.body && getTotalBytes(request) === null) { + reject(new FetchError('Cannot follow redirect with body being a readable stream', 'unsupported-redirect')); + finalize(); + return; + } + + // HTTP-redirect fetch step 11 + if (res.statusCode === 303 || (res.statusCode === 301 || res.statusCode === 302) && request.method === 'POST') { + requestOpts.method = 'GET'; + requestOpts.body = undefined; + requestOpts.headers.delete('content-length'); + } + + // HTTP-redirect fetch step 15 + resolve(fetch(new Request(locationURL, requestOpts))); + finalize(); + return; + } + } + + // prepare response + res.once('end', function () { + if (signal) signal.removeEventListener('abort', abortAndFinalize); + }); + let body = res.pipe(new PassThrough$1()); + + const response_options = { + url: request.url, + status: res.statusCode, + statusText: res.statusMessage, + headers: headers, + size: request.size, + timeout: request.timeout, + counter: request.counter + }; + + // HTTP-network fetch step 12.1.1.3 + const codings = headers.get('Content-Encoding'); + + // HTTP-network fetch step 12.1.1.4: handle content codings + + // in following scenarios we ignore compression support + // 1. compression support is disabled + // 2. HEAD request + // 3. no Content-Encoding header + // 4. no content response (204) + // 5. content not modified response (304) + if (!request.compress || request.method === 'HEAD' || codings === null || res.statusCode === 204 || res.statusCode === 304) { + response = new Response(body, response_options); + resolve(response); + return; + } + + // For Node v6+ + // Be less strict when decoding compressed responses, since sometimes + // servers send slightly invalid responses that are still accepted + // by common browsers. + // Always using Z_SYNC_FLUSH is what cURL does. + const zlibOptions = { + flush: zlib.Z_SYNC_FLUSH, + finishFlush: zlib.Z_SYNC_FLUSH + }; + + // for gzip + if (codings == 'gzip' || codings == 'x-gzip') { + body = body.pipe(zlib.createGunzip(zlibOptions)); + response = new Response(body, response_options); + resolve(response); + return; + } + + // for deflate + if (codings == 'deflate' || codings == 'x-deflate') { + // handle the infamous raw deflate response from old servers + // a hack for old IIS and Apache servers + const raw = res.pipe(new PassThrough$1()); + raw.once('data', function (chunk) { + // see http://stackoverflow.com/questions/37519828 + if ((chunk[0] & 0x0F) === 0x08) { + body = body.pipe(zlib.createInflate()); + } else { + body = body.pipe(zlib.createInflateRaw()); + } + response = new Response(body, response_options); + resolve(response); + }); + return; + } + + // for br + if (codings == 'br' && typeof zlib.createBrotliDecompress === 'function') { + body = body.pipe(zlib.createBrotliDecompress()); + response = new Response(body, response_options); + resolve(response); + return; + } + + // otherwise, use response as-is + response = new Response(body, response_options); + resolve(response); + }); + + writeToStream(req, request); + }); +} +/** + * Redirect code matching + * + * @param Number code Status code + * @return Boolean + */ +fetch.isRedirect = function (code) { + return code === 301 || code === 302 || code === 303 || code === 307 || code === 308; +}; + +// expose Promise +fetch.Promise = global.Promise; + +module.exports = exports = fetch; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports["default"] = exports; +exports.Headers = Headers; +exports.Request = Request; +exports.Response = Response; +exports.FetchError = FetchError; + + +/***/ }), + +/***/ 2299: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +var punycode = __nccwpck_require__(5477); +var mappingTable = __nccwpck_require__(1907); + +var PROCESSING_OPTIONS = { + TRANSITIONAL: 0, + NONTRANSITIONAL: 1 +}; + +function normalize(str) { // fix bug in v8 + return str.split('\u0000').map(function (s) { return s.normalize('NFC'); }).join('\u0000'); +} + +function findStatus(val) { + var start = 0; + var end = mappingTable.length - 1; + + while (start <= end) { + var mid = Math.floor((start + end) / 2); + + var target = mappingTable[mid]; + if (target[0][0] <= val && target[0][1] >= val) { + return target; + } else if (target[0][0] > val) { + end = mid - 1; + } else { + start = mid + 1; + } + } + + return null; +} + +var regexAstralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g; + +function countSymbols(string) { + return string + // replace every surrogate pair with a BMP symbol + .replace(regexAstralSymbols, '_') + // then get the length + .length; +} + +function mapChars(domain_name, useSTD3, processing_option) { + var hasError = false; + var processed = ""; + + var len = countSymbols(domain_name); + for (var i = 0; i < len; ++i) { + var codePoint = domain_name.codePointAt(i); + var status = findStatus(codePoint); + + switch (status[1]) { + case "disallowed": + hasError = true; + processed += String.fromCodePoint(codePoint); + break; + case "ignored": + break; + case "mapped": + processed += String.fromCodePoint.apply(String, status[2]); + break; + case "deviation": + if (processing_option === PROCESSING_OPTIONS.TRANSITIONAL) { + processed += String.fromCodePoint.apply(String, status[2]); + } else { + processed += String.fromCodePoint(codePoint); + } + break; + case "valid": + processed += String.fromCodePoint(codePoint); + break; + case "disallowed_STD3_mapped": + if (useSTD3) { + hasError = true; + processed += String.fromCodePoint(codePoint); + } else { + processed += String.fromCodePoint.apply(String, status[2]); + } + break; + case "disallowed_STD3_valid": + if (useSTD3) { + hasError = true; + } + + processed += String.fromCodePoint(codePoint); + break; + } + } + + return { + string: processed, + error: hasError + }; +} + +var combiningMarksRegex = /[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08E4-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C03\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D01-\u0D03\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u18A9\u1920-\u192B\u1930-\u193B\u19B0-\u19C0\u19C8\u19C9\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF8\u1CF9\u1DC0-\u1DF5\u1DFC-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C4\uA8E0-\uA8F1\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2D]|\uD800[\uDDFD\uDEE0\uDF76-\uDF7A]|\uD802[\uDE01-\uDE03\uDE05\uDE06\uDE0C-\uDE0F\uDE38-\uDE3A\uDE3F\uDEE5\uDEE6]|\uD804[\uDC00-\uDC02\uDC38-\uDC46\uDC7F-\uDC82\uDCB0-\uDCBA\uDD00-\uDD02\uDD27-\uDD34\uDD73\uDD80-\uDD82\uDDB3-\uDDC0\uDE2C-\uDE37\uDEDF-\uDEEA\uDF01-\uDF03\uDF3C\uDF3E-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF62\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDCB0-\uDCC3\uDDAF-\uDDB5\uDDB8-\uDDC0\uDE30-\uDE40\uDEAB-\uDEB7]|\uD81A[\uDEF0-\uDEF4\uDF30-\uDF36]|\uD81B[\uDF51-\uDF7E\uDF8F-\uDF92]|\uD82F[\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD83A[\uDCD0-\uDCD6]|\uDB40[\uDD00-\uDDEF]/; + +function validateLabel(label, processing_option) { + if (label.substr(0, 4) === "xn--") { + label = punycode.toUnicode(label); + processing_option = PROCESSING_OPTIONS.NONTRANSITIONAL; + } + + var error = false; + + if (normalize(label) !== label || + (label[3] === "-" && label[4] === "-") || + label[0] === "-" || label[label.length - 1] === "-" || + label.indexOf(".") !== -1 || + label.search(combiningMarksRegex) === 0) { + error = true; + } + + var len = countSymbols(label); + for (var i = 0; i < len; ++i) { + var status = findStatus(label.codePointAt(i)); + if ((processing === PROCESSING_OPTIONS.TRANSITIONAL && status[1] !== "valid") || + (processing === PROCESSING_OPTIONS.NONTRANSITIONAL && + status[1] !== "valid" && status[1] !== "deviation")) { + error = true; + break; + } + } + + return { + label: label, + error: error + }; +} + +function processing(domain_name, useSTD3, processing_option) { + var result = mapChars(domain_name, useSTD3, processing_option); + result.string = normalize(result.string); + + var labels = result.string.split("."); + for (var i = 0; i < labels.length; ++i) { + try { + var validation = validateLabel(labels[i]); + labels[i] = validation.label; + result.error = result.error || validation.error; + } catch(e) { + result.error = true; + } + } + + return { + string: labels.join("."), + error: result.error + }; +} + +module.exports.toASCII = function(domain_name, useSTD3, processing_option, verifyDnsLength) { + var result = processing(domain_name, useSTD3, processing_option); + var labels = result.string.split("."); + labels = labels.map(function(l) { + try { + return punycode.toASCII(l); + } catch(e) { + result.error = true; + return l; + } + }); + + if (verifyDnsLength) { + var total = labels.slice(0, labels.length - 1).join(".").length; + if (total.length > 253 || total.length === 0) { + result.error = true; + } + + for (var i=0; i < labels.length; ++i) { + if (labels.length > 63 || labels.length === 0) { + result.error = true; + break; + } + } + } + + if (result.error) return null; + return labels.join("."); +}; + +module.exports.toUnicode = function(domain_name, useSTD3) { + var result = processing(domain_name, useSTD3, PROCESSING_OPTIONS.NONTRANSITIONAL); + + return { + domain: result.string, + error: result.error + }; +}; + +module.exports.PROCESSING_OPTIONS = PROCESSING_OPTIONS; + + +/***/ }), + +/***/ 5871: +/***/ ((module) => { + +"use strict"; + + +var conversions = {}; +module.exports = conversions; + +function sign(x) { + return x < 0 ? -1 : 1; +} + +function evenRound(x) { + // Round x to the nearest integer, choosing the even integer if it lies halfway between two. + if ((x % 1) === 0.5 && (x & 1) === 0) { // [even number].5; round down (i.e. floor) + return Math.floor(x); + } else { + return Math.round(x); + } +} + +function createNumberConversion(bitLength, typeOpts) { + if (!typeOpts.unsigned) { + --bitLength; + } + const lowerBound = typeOpts.unsigned ? 0 : -Math.pow(2, bitLength); + const upperBound = Math.pow(2, bitLength) - 1; + + const moduloVal = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength) : Math.pow(2, bitLength); + const moduloBound = typeOpts.moduloBitLength ? Math.pow(2, typeOpts.moduloBitLength - 1) : Math.pow(2, bitLength - 1); + + return function(V, opts) { + if (!opts) opts = {}; + + let x = +V; + + if (opts.enforceRange) { + if (!Number.isFinite(x)) { + throw new TypeError("Argument is not a finite number"); + } + + x = sign(x) * Math.floor(Math.abs(x)); + if (x < lowerBound || x > upperBound) { + throw new TypeError("Argument is not in byte range"); + } + + return x; + } + + if (!isNaN(x) && opts.clamp) { + x = evenRound(x); + + if (x < lowerBound) x = lowerBound; + if (x > upperBound) x = upperBound; + return x; + } + + if (!Number.isFinite(x) || x === 0) { + return 0; + } + + x = sign(x) * Math.floor(Math.abs(x)); + x = x % moduloVal; + + if (!typeOpts.unsigned && x >= moduloBound) { + return x - moduloVal; + } else if (typeOpts.unsigned) { + if (x < 0) { + x += moduloVal; + } else if (x === -0) { // don't return negative zero + return 0; + } + } + + return x; + } +} + +conversions["void"] = function () { + return undefined; +}; + +conversions["boolean"] = function (val) { + return !!val; +}; + +conversions["byte"] = createNumberConversion(8, { unsigned: false }); +conversions["octet"] = createNumberConversion(8, { unsigned: true }); + +conversions["short"] = createNumberConversion(16, { unsigned: false }); +conversions["unsigned short"] = createNumberConversion(16, { unsigned: true }); + +conversions["long"] = createNumberConversion(32, { unsigned: false }); +conversions["unsigned long"] = createNumberConversion(32, { unsigned: true }); + +conversions["long long"] = createNumberConversion(32, { unsigned: false, moduloBitLength: 64 }); +conversions["unsigned long long"] = createNumberConversion(32, { unsigned: true, moduloBitLength: 64 }); + +conversions["double"] = function (V) { + const x = +V; + + if (!Number.isFinite(x)) { + throw new TypeError("Argument is not a finite floating-point value"); + } + + return x; +}; + +conversions["unrestricted double"] = function (V) { + const x = +V; + + if (isNaN(x)) { + throw new TypeError("Argument is NaN"); + } + + return x; +}; + +// not quite valid, but good enough for JS +conversions["float"] = conversions["double"]; +conversions["unrestricted float"] = conversions["unrestricted double"]; + +conversions["DOMString"] = function (V, opts) { + if (!opts) opts = {}; + + if (opts.treatNullAsEmptyString && V === null) { + return ""; + } + + return String(V); +}; + +conversions["ByteString"] = function (V, opts) { + const x = String(V); + let c = undefined; + for (let i = 0; (c = x.codePointAt(i)) !== undefined; ++i) { + if (c > 255) { + throw new TypeError("Argument is not a valid bytestring"); + } + } + + return x; +}; + +conversions["USVString"] = function (V) { + const S = String(V); + const n = S.length; + const U = []; + for (let i = 0; i < n; ++i) { + const c = S.charCodeAt(i); + if (c < 0xD800 || c > 0xDFFF) { + U.push(String.fromCodePoint(c)); + } else if (0xDC00 <= c && c <= 0xDFFF) { + U.push(String.fromCodePoint(0xFFFD)); + } else { + if (i === n - 1) { + U.push(String.fromCodePoint(0xFFFD)); + } else { + const d = S.charCodeAt(i + 1); + if (0xDC00 <= d && d <= 0xDFFF) { + const a = c & 0x3FF; + const b = d & 0x3FF; + U.push(String.fromCodePoint((2 << 15) + (2 << 9) * a + b)); + ++i; + } else { + U.push(String.fromCodePoint(0xFFFD)); + } + } + } + } + + return U.join(''); +}; + +conversions["Date"] = function (V, opts) { + if (!(V instanceof Date)) { + throw new TypeError("Argument is not a Date object"); + } + if (isNaN(V)) { + return undefined; + } + + return V; +}; + +conversions["RegExp"] = function (V, opts) { + if (!(V instanceof RegExp)) { + V = new RegExp(V); + } + + return V; +}; + + +/***/ }), + +/***/ 8262: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +const usm = __nccwpck_require__(33); + +exports.implementation = class URLImpl { + constructor(constructorArgs) { + const url = constructorArgs[0]; + const base = constructorArgs[1]; + + let parsedBase = null; + if (base !== undefined) { + parsedBase = usm.basicURLParse(base); + if (parsedBase === "failure") { + throw new TypeError("Invalid base URL"); + } + } + + const parsedURL = usm.basicURLParse(url, { baseURL: parsedBase }); + if (parsedURL === "failure") { + throw new TypeError("Invalid URL"); + } + + this._url = parsedURL; + + // TODO: query stuff + } + + get href() { + return usm.serializeURL(this._url); + } + + set href(v) { + const parsedURL = usm.basicURLParse(v); + if (parsedURL === "failure") { + throw new TypeError("Invalid URL"); + } + + this._url = parsedURL; + } + + get origin() { + return usm.serializeURLOrigin(this._url); + } + + get protocol() { + return this._url.scheme + ":"; + } + + set protocol(v) { + usm.basicURLParse(v + ":", { url: this._url, stateOverride: "scheme start" }); + } + + get username() { + return this._url.username; + } + + set username(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + usm.setTheUsername(this._url, v); + } + + get password() { + return this._url.password; + } + + set password(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + usm.setThePassword(this._url, v); + } + + get host() { + const url = this._url; + + if (url.host === null) { + return ""; + } + + if (url.port === null) { + return usm.serializeHost(url.host); + } + + return usm.serializeHost(url.host) + ":" + usm.serializeInteger(url.port); + } + + set host(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + usm.basicURLParse(v, { url: this._url, stateOverride: "host" }); + } + + get hostname() { + if (this._url.host === null) { + return ""; + } + + return usm.serializeHost(this._url.host); + } + + set hostname(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + usm.basicURLParse(v, { url: this._url, stateOverride: "hostname" }); + } + + get port() { + if (this._url.port === null) { + return ""; + } + + return usm.serializeInteger(this._url.port); + } + + set port(v) { + if (usm.cannotHaveAUsernamePasswordPort(this._url)) { + return; + } + + if (v === "") { + this._url.port = null; + } else { + usm.basicURLParse(v, { url: this._url, stateOverride: "port" }); + } + } + + get pathname() { + if (this._url.cannotBeABaseURL) { + return this._url.path[0]; + } + + if (this._url.path.length === 0) { + return ""; + } + + return "/" + this._url.path.join("/"); + } + + set pathname(v) { + if (this._url.cannotBeABaseURL) { + return; + } + + this._url.path = []; + usm.basicURLParse(v, { url: this._url, stateOverride: "path start" }); + } + + get search() { + if (this._url.query === null || this._url.query === "") { + return ""; + } + + return "?" + this._url.query; + } + + set search(v) { + // TODO: query stuff + + const url = this._url; + + if (v === "") { + url.query = null; + return; + } + + const input = v[0] === "?" ? v.substring(1) : v; + url.query = ""; + usm.basicURLParse(input, { url, stateOverride: "query" }); + } + + get hash() { + if (this._url.fragment === null || this._url.fragment === "") { + return ""; + } + + return "#" + this._url.fragment; + } + + set hash(v) { + if (v === "") { + this._url.fragment = null; + return; + } + + const input = v[0] === "#" ? v.substring(1) : v; + this._url.fragment = ""; + usm.basicURLParse(input, { url: this._url, stateOverride: "fragment" }); + } + + toJSON() { + return this.href; + } +}; + + +/***/ }), + +/***/ 653: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + + +const conversions = __nccwpck_require__(5871); +const utils = __nccwpck_require__(276); +const Impl = __nccwpck_require__(8262); + +const impl = utils.implSymbol; + +function URL(url) { + if (!this || this[impl] || !(this instanceof URL)) { + throw new TypeError("Failed to construct 'URL': Please use the 'new' operator, this DOM object constructor cannot be called as a function."); + } + if (arguments.length < 1) { + throw new TypeError("Failed to construct 'URL': 1 argument required, but only " + arguments.length + " present."); + } + const args = []; + for (let i = 0; i < arguments.length && i < 2; ++i) { + args[i] = arguments[i]; + } + args[0] = conversions["USVString"](args[0]); + if (args[1] !== undefined) { + args[1] = conversions["USVString"](args[1]); + } + + module.exports.setup(this, args); +} + +URL.prototype.toJSON = function toJSON() { + if (!this || !module.exports.is(this)) { + throw new TypeError("Illegal invocation"); + } + const args = []; + for (let i = 0; i < arguments.length && i < 0; ++i) { + args[i] = arguments[i]; + } + return this[impl].toJSON.apply(this[impl], args); +}; +Object.defineProperty(URL.prototype, "href", { + get() { + return this[impl].href; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].href = V; + }, + enumerable: true, + configurable: true +}); + +URL.prototype.toString = function () { + if (!this || !module.exports.is(this)) { + throw new TypeError("Illegal invocation"); + } + return this.href; +}; + +Object.defineProperty(URL.prototype, "origin", { + get() { + return this[impl].origin; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "protocol", { + get() { + return this[impl].protocol; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].protocol = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "username", { + get() { + return this[impl].username; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].username = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "password", { + get() { + return this[impl].password; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].password = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "host", { + get() { + return this[impl].host; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].host = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "hostname", { + get() { + return this[impl].hostname; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].hostname = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "port", { + get() { + return this[impl].port; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].port = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "pathname", { + get() { + return this[impl].pathname; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].pathname = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "search", { + get() { + return this[impl].search; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].search = V; + }, + enumerable: true, + configurable: true +}); + +Object.defineProperty(URL.prototype, "hash", { + get() { + return this[impl].hash; + }, + set(V) { + V = conversions["USVString"](V); + this[impl].hash = V; + }, + enumerable: true, + configurable: true +}); + + +module.exports = { + is(obj) { + return !!obj && obj[impl] instanceof Impl.implementation; + }, + create(constructorArgs, privateData) { + let obj = Object.create(URL.prototype); + this.setup(obj, constructorArgs, privateData); + return obj; + }, + setup(obj, constructorArgs, privateData) { + if (!privateData) privateData = {}; + privateData.wrapper = obj; + + obj[impl] = new Impl.implementation(constructorArgs, privateData); + obj[impl][utils.wrapperSymbol] = obj; + }, + interface: URL, + expose: { + Window: { URL: URL }, + Worker: { URL: URL } + } +}; + + + +/***/ }), + +/***/ 3323: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +exports.URL = __nccwpck_require__(653)["interface"]; +exports.serializeURL = __nccwpck_require__(33).serializeURL; +exports.serializeURLOrigin = __nccwpck_require__(33).serializeURLOrigin; +exports.basicURLParse = __nccwpck_require__(33).basicURLParse; +exports.setTheUsername = __nccwpck_require__(33).setTheUsername; +exports.setThePassword = __nccwpck_require__(33).setThePassword; +exports.serializeHost = __nccwpck_require__(33).serializeHost; +exports.serializeInteger = __nccwpck_require__(33).serializeInteger; +exports.parseURL = __nccwpck_require__(33).parseURL; + + +/***/ }), + +/***/ 33: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +"use strict"; + +const punycode = __nccwpck_require__(5477); +const tr46 = __nccwpck_require__(2299); + +const specialSchemes = { + ftp: 21, + file: null, + gopher: 70, + http: 80, + https: 443, + ws: 80, + wss: 443 +}; + +const failure = Symbol("failure"); + +function countSymbols(str) { + return punycode.ucs2.decode(str).length; +} + +function at(input, idx) { + const c = input[idx]; + return isNaN(c) ? undefined : String.fromCodePoint(c); +} + +function isASCIIDigit(c) { + return c >= 0x30 && c <= 0x39; +} + +function isASCIIAlpha(c) { + return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); +} + +function isASCIIAlphanumeric(c) { + return isASCIIAlpha(c) || isASCIIDigit(c); +} + +function isASCIIHex(c) { + return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66); +} + +function isSingleDot(buffer) { + return buffer === "." || buffer.toLowerCase() === "%2e"; +} + +function isDoubleDot(buffer) { + buffer = buffer.toLowerCase(); + return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; +} + +function isWindowsDriveLetterCodePoints(cp1, cp2) { + return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124); +} + +function isWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|"); +} + +function isNormalizedWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":"; +} + +function containsForbiddenHostCodePoint(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function containsForbiddenHostCodePointExcludingPercent(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function isSpecialScheme(scheme) { + return specialSchemes[scheme] !== undefined; +} + +function isSpecial(url) { + return isSpecialScheme(url.scheme); +} + +function defaultPort(scheme) { + return specialSchemes[scheme]; +} + +function percentEncode(c) { + let hex = c.toString(16).toUpperCase(); + if (hex.length === 1) { + hex = "0" + hex; + } + + return "%" + hex; +} + +function utf8PercentEncode(c) { + const buf = new Buffer(c); + + let str = ""; + + for (let i = 0; i < buf.length; ++i) { + str += percentEncode(buf[i]); + } + + return str; +} + +function utf8PercentDecode(str) { + const input = new Buffer(str); + const output = []; + for (let i = 0; i < input.length; ++i) { + if (input[i] !== 37) { + output.push(input[i]); + } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) { + output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16)); + i += 2; + } else { + output.push(input[i]); + } + } + return new Buffer(output).toString(); +} + +function isC0ControlPercentEncode(c) { + return c <= 0x1F || c > 0x7E; +} + +const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]); +function isPathPercentEncode(c) { + return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c); +} + +const extraUserinfoPercentEncodeSet = + new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]); +function isUserinfoPercentEncode(c) { + return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c); +} + +function percentEncodeChar(c, encodeSetPredicate) { + const cStr = String.fromCodePoint(c); + + if (encodeSetPredicate(c)) { + return utf8PercentEncode(cStr); + } + + return cStr; +} + +function parseIPv4Number(input) { + let R = 10; + + if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") { + input = input.substring(2); + R = 16; + } else if (input.length >= 2 && input.charAt(0) === "0") { + input = input.substring(1); + R = 8; + } + + if (input === "") { + return 0; + } + + const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/); + if (regex.test(input)) { + return failure; + } + + return parseInt(input, R); +} + +function parseIPv4(input) { + const parts = input.split("."); + if (parts[parts.length - 1] === "") { + if (parts.length > 1) { + parts.pop(); + } + } + + if (parts.length > 4) { + return input; + } + + const numbers = []; + for (const part of parts) { + if (part === "") { + return input; + } + const n = parseIPv4Number(part); + if (n === failure) { + return input; + } + + numbers.push(n); + } + + for (let i = 0; i < numbers.length - 1; ++i) { + if (numbers[i] > 255) { + return failure; + } + } + if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) { + return failure; + } + + let ipv4 = numbers.pop(); + let counter = 0; + + for (const n of numbers) { + ipv4 += n * Math.pow(256, 3 - counter); + ++counter; + } + + return ipv4; +} + +function serializeIPv4(address) { + let output = ""; + let n = address; + + for (let i = 1; i <= 4; ++i) { + output = String(n % 256) + output; + if (i !== 4) { + output = "." + output; + } + n = Math.floor(n / 256); + } + + return output; +} + +function parseIPv6(input) { + const address = [0, 0, 0, 0, 0, 0, 0, 0]; + let pieceIndex = 0; + let compress = null; + let pointer = 0; + + input = punycode.ucs2.decode(input); + + if (input[pointer] === 58) { + if (input[pointer + 1] !== 58) { + return failure; + } + + pointer += 2; + ++pieceIndex; + compress = pieceIndex; + } + + while (pointer < input.length) { + if (pieceIndex === 8) { + return failure; + } + + if (input[pointer] === 58) { + if (compress !== null) { + return failure; + } + ++pointer; + ++pieceIndex; + compress = pieceIndex; + continue; + } + + let value = 0; + let length = 0; + + while (length < 4 && isASCIIHex(input[pointer])) { + value = value * 0x10 + parseInt(at(input, pointer), 16); + ++pointer; + ++length; + } + + if (input[pointer] === 46) { + if (length === 0) { + return failure; + } + + pointer -= length; + + if (pieceIndex > 6) { + return failure; + } + + let numbersSeen = 0; + + while (input[pointer] !== undefined) { + let ipv4Piece = null; + + if (numbersSeen > 0) { + if (input[pointer] === 46 && numbersSeen < 4) { + ++pointer; + } else { + return failure; + } + } + + if (!isASCIIDigit(input[pointer])) { + return failure; + } + + while (isASCIIDigit(input[pointer])) { + const number = parseInt(at(input, pointer)); + if (ipv4Piece === null) { + ipv4Piece = number; + } else if (ipv4Piece === 0) { + return failure; + } else { + ipv4Piece = ipv4Piece * 10 + number; + } + if (ipv4Piece > 255) { + return failure; + } + ++pointer; + } + + address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece; + + ++numbersSeen; + + if (numbersSeen === 2 || numbersSeen === 4) { + ++pieceIndex; + } + } + + if (numbersSeen !== 4) { + return failure; + } + + break; + } else if (input[pointer] === 58) { + ++pointer; + if (input[pointer] === undefined) { + return failure; + } + } else if (input[pointer] !== undefined) { + return failure; + } + + address[pieceIndex] = value; + ++pieceIndex; + } + + if (compress !== null) { + let swaps = pieceIndex - compress; + pieceIndex = 7; + while (pieceIndex !== 0 && swaps > 0) { + const temp = address[compress + swaps - 1]; + address[compress + swaps - 1] = address[pieceIndex]; + address[pieceIndex] = temp; + --pieceIndex; + --swaps; + } + } else if (compress === null && pieceIndex !== 8) { + return failure; + } + + return address; +} + +function serializeIPv6(address) { + let output = ""; + const seqResult = findLongestZeroSequence(address); + const compress = seqResult.idx; + let ignore0 = false; + + for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) { + if (ignore0 && address[pieceIndex] === 0) { + continue; + } else if (ignore0) { + ignore0 = false; + } + + if (compress === pieceIndex) { + const separator = pieceIndex === 0 ? "::" : ":"; + output += separator; + ignore0 = true; + continue; + } + + output += address[pieceIndex].toString(16); + + if (pieceIndex !== 7) { + output += ":"; + } + } + + return output; +} + +function parseHost(input, isSpecialArg) { + if (input[0] === "[") { + if (input[input.length - 1] !== "]") { + return failure; + } + + return parseIPv6(input.substring(1, input.length - 1)); + } + + if (!isSpecialArg) { + return parseOpaqueHost(input); + } + + const domain = utf8PercentDecode(input); + const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false); + if (asciiDomain === null) { + return failure; + } + + if (containsForbiddenHostCodePoint(asciiDomain)) { + return failure; + } + + const ipv4Host = parseIPv4(asciiDomain); + if (typeof ipv4Host === "number" || ipv4Host === failure) { + return ipv4Host; + } + + return asciiDomain; +} + +function parseOpaqueHost(input) { + if (containsForbiddenHostCodePointExcludingPercent(input)) { + return failure; + } + + let output = ""; + const decoded = punycode.ucs2.decode(input); + for (let i = 0; i < decoded.length; ++i) { + output += percentEncodeChar(decoded[i], isC0ControlPercentEncode); + } + return output; +} + +function findLongestZeroSequence(arr) { + let maxIdx = null; + let maxLen = 1; // only find elements > 1 + let currStart = null; + let currLen = 0; + + for (let i = 0; i < arr.length; ++i) { + if (arr[i] !== 0) { + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + currStart = null; + currLen = 0; + } else { + if (currStart === null) { + currStart = i; + } + ++currLen; + } + } + + // if trailing zeros + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + return { + idx: maxIdx, + len: maxLen + }; +} + +function serializeHost(host) { + if (typeof host === "number") { + return serializeIPv4(host); + } + + // IPv6 serializer + if (host instanceof Array) { + return "[" + serializeIPv6(host) + "]"; + } + + return host; +} + +function trimControlChars(url) { + return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, ""); +} + +function trimTabAndNewline(url) { + return url.replace(/\u0009|\u000A|\u000D/g, ""); +} + +function shortenPath(url) { + const path = url.path; + if (path.length === 0) { + return; + } + if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) { + return; + } + + path.pop(); +} + +function includesCredentials(url) { + return url.username !== "" || url.password !== ""; +} + +function cannotHaveAUsernamePasswordPort(url) { + return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file"; +} + +function isNormalizedWindowsDriveLetter(string) { + return /^[A-Za-z]:$/.test(string); +} + +function URLStateMachine(input, base, encodingOverride, url, stateOverride) { + this.pointer = 0; + this.input = input; + this.base = base || null; + this.encodingOverride = encodingOverride || "utf-8"; + this.stateOverride = stateOverride; + this.url = url; + this.failure = false; + this.parseError = false; + + if (!this.url) { + this.url = { + scheme: "", + username: "", + password: "", + host: null, + port: null, + path: [], + query: null, + fragment: null, + + cannotBeABaseURL: false + }; + + const res = trimControlChars(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + } + + const res = trimTabAndNewline(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + + this.state = stateOverride || "scheme start"; + + this.buffer = ""; + this.atFlag = false; + this.arrFlag = false; + this.passwordTokenSeenFlag = false; + + this.input = punycode.ucs2.decode(this.input); + + for (; this.pointer <= this.input.length; ++this.pointer) { + const c = this.input[this.pointer]; + const cStr = isNaN(c) ? undefined : String.fromCodePoint(c); + + // exec state machine + const ret = this["parse " + this.state](c, cStr); + if (!ret) { + break; // terminate algorithm + } else if (ret === failure) { + this.failure = true; + break; + } + } +} + +URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) { + if (isASCIIAlpha(c)) { + this.buffer += cStr.toLowerCase(); + this.state = "scheme"; + } else if (!this.stateOverride) { + this.state = "no scheme"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) { + if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) { + this.buffer += cStr.toLowerCase(); + } else if (c === 58) { + if (this.stateOverride) { + if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) { + return false; + } + + if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) { + return false; + } + + if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") { + return false; + } + + if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) { + return false; + } + } + this.url.scheme = this.buffer; + this.buffer = ""; + if (this.stateOverride) { + return false; + } + if (this.url.scheme === "file") { + if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) { + this.parseError = true; + } + this.state = "file"; + } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) { + this.state = "special relative or authority"; + } else if (isSpecial(this.url)) { + this.state = "special authority slashes"; + } else if (this.input[this.pointer + 1] === 47) { + this.state = "path or authority"; + ++this.pointer; + } else { + this.url.cannotBeABaseURL = true; + this.url.path.push(""); + this.state = "cannot-be-a-base-URL path"; + } + } else if (!this.stateOverride) { + this.buffer = ""; + this.state = "no scheme"; + this.pointer = -1; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) { + if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) { + return failure; + } else if (this.base.cannotBeABaseURL && c === 35) { + this.url.scheme = this.base.scheme; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.url.cannotBeABaseURL = true; + this.state = "fragment"; + } else if (this.base.scheme === "file") { + this.state = "file"; + --this.pointer; + } else { + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) { + if (c === 47) { + this.state = "authority"; + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative"] = function parseRelative(c) { + this.url.scheme = this.base.scheme; + if (isNaN(c)) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 47) { + this.state = "relative slash"; + } else if (c === 63) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else if (isSpecial(this.url) && c === 92) { + this.parseError = true; + this.state = "relative slash"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(0, this.base.path.length - 1); + + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) { + if (isSpecial(this.url) && (c === 47 || c === 92)) { + if (c === 92) { + this.parseError = true; + } + this.state = "special authority ignore slashes"; + } else if (c === 47) { + this.state = "authority"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "special authority ignore slashes"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) { + if (c !== 47 && c !== 92) { + this.state = "authority"; + --this.pointer; + } else { + this.parseError = true; + } + + return true; +}; + +URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) { + if (c === 64) { + this.parseError = true; + if (this.atFlag) { + this.buffer = "%40" + this.buffer; + } + this.atFlag = true; + + // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars + const len = countSymbols(this.buffer); + for (let pointer = 0; pointer < len; ++pointer) { + const codePoint = this.buffer.codePointAt(pointer); + + if (codePoint === 58 && !this.passwordTokenSeenFlag) { + this.passwordTokenSeenFlag = true; + continue; + } + const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode); + if (this.passwordTokenSeenFlag) { + this.url.password += encodedCodePoints; + } else { + this.url.username += encodedCodePoints; + } + } + this.buffer = ""; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + if (this.atFlag && this.buffer === "") { + this.parseError = true; + return failure; + } + this.pointer -= countSymbols(this.buffer) + 1; + this.buffer = ""; + this.state = "host"; + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse hostname"] = +URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { + if (this.stateOverride && this.url.scheme === "file") { + --this.pointer; + this.state = "file host"; + } else if (c === 58 && !this.arrFlag) { + if (this.buffer === "") { + this.parseError = true; + return failure; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "port"; + if (this.stateOverride === "hostname") { + return false; + } + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + --this.pointer; + if (isSpecial(this.url) && this.buffer === "") { + this.parseError = true; + return failure; + } else if (this.stateOverride && this.buffer === "" && + (includesCredentials(this.url) || this.url.port !== null)) { + this.parseError = true; + return false; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "path start"; + if (this.stateOverride) { + return false; + } + } else { + if (c === 91) { + this.arrFlag = true; + } else if (c === 93) { + this.arrFlag = false; + } + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) { + if (isASCIIDigit(c)) { + this.buffer += cStr; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92) || + this.stateOverride) { + if (this.buffer !== "") { + const port = parseInt(this.buffer); + if (port > Math.pow(2, 16) - 1) { + this.parseError = true; + return failure; + } + this.url.port = port === defaultPort(this.url.scheme) ? null : port; + this.buffer = ""; + } + if (this.stateOverride) { + return false; + } + this.state = "path start"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]); + +URLStateMachine.prototype["parse file"] = function parseFile(c) { + this.url.scheme = "file"; + + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file slash"; + } else if (this.base !== null && this.base.scheme === "file") { + if (isNaN(c)) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 63) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else { + if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points + !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) || + (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points + !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + shortenPath(this.url); + } else { + this.parseError = true; + } + + this.state = "path"; + --this.pointer; + } + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) { + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file host"; + } else { + if (this.base !== null && this.base.scheme === "file") { + if (isNormalizedWindowsDriveLetterString(this.base.path[0])) { + this.url.path.push(this.base.path[0]); + } else { + this.url.host = this.base.host; + } + } + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) { + if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) { + --this.pointer; + if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) { + this.parseError = true; + this.state = "path"; + } else if (this.buffer === "") { + this.url.host = ""; + if (this.stateOverride) { + return false; + } + this.state = "path start"; + } else { + let host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + if (host === "localhost") { + host = ""; + } + this.url.host = host; + + if (this.stateOverride) { + return false; + } + + this.buffer = ""; + this.state = "path start"; + } + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse path start"] = function parsePathStart(c) { + if (isSpecial(this.url)) { + if (c === 92) { + this.parseError = true; + } + this.state = "path"; + + if (c !== 47 && c !== 92) { + --this.pointer; + } + } else if (!this.stateOverride && c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (!this.stateOverride && c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else if (c !== undefined) { + this.state = "path"; + if (c !== 47) { + --this.pointer; + } + } + + return true; +}; + +URLStateMachine.prototype["parse path"] = function parsePath(c) { + if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) || + (!this.stateOverride && (c === 63 || c === 35))) { + if (isSpecial(this.url) && c === 92) { + this.parseError = true; + } + + if (isDoubleDot(this.buffer)) { + shortenPath(this.url); + if (c !== 47 && !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } + } else if (isSingleDot(this.buffer) && c !== 47 && + !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } else if (!isSingleDot(this.buffer)) { + if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) { + if (this.url.host !== "" && this.url.host !== null) { + this.parseError = true; + this.url.host = ""; + } + this.buffer = this.buffer[0] + ":"; + } + this.url.path.push(this.buffer); + } + this.buffer = ""; + if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) { + while (this.url.path.length > 1 && this.url.path[0] === "") { + this.parseError = true; + this.url.path.shift(); + } + } + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += percentEncodeChar(c, isPathPercentEncode); + } + + return true; +}; + +URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) { + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else { + // TODO: Add: not a URL code point + if (!isNaN(c) && c !== 37) { + this.parseError = true; + } + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + if (!isNaN(c)) { + this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode); + } + } + + return true; +}; + +URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) { + if (isNaN(c) || (!this.stateOverride && c === 35)) { + if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") { + this.encodingOverride = "utf-8"; + } + + const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead + for (let i = 0; i < buffer.length; ++i) { + if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 || + buffer[i] === 0x3C || buffer[i] === 0x3E) { + this.url.query += percentEncode(buffer[i]); + } else { + this.url.query += String.fromCodePoint(buffer[i]); + } + } + + this.buffer = ""; + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse fragment"] = function parseFragment(c) { + if (isNaN(c)) { // do nothing + } else if (c === 0x0) { + this.parseError = true; + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode); + } + + return true; +}; + +function serializeURL(url, excludeFragment) { + let output = url.scheme + ":"; + if (url.host !== null) { + output += "//"; + + if (url.username !== "" || url.password !== "") { + output += url.username; + if (url.password !== "") { + output += ":" + url.password; + } + output += "@"; + } + + output += serializeHost(url.host); + + if (url.port !== null) { + output += ":" + url.port; + } + } else if (url.host === null && url.scheme === "file") { + output += "//"; + } + + if (url.cannotBeABaseURL) { + output += url.path[0]; + } else { + for (const string of url.path) { + output += "/" + string; + } + } + + if (url.query !== null) { + output += "?" + url.query; + } + + if (!excludeFragment && url.fragment !== null) { + output += "#" + url.fragment; + } + + return output; +} + +function serializeOrigin(tuple) { + let result = tuple.scheme + "://"; + result += serializeHost(tuple.host); + + if (tuple.port !== null) { + result += ":" + tuple.port; + } + + return result; +} + +module.exports.serializeURL = serializeURL; + +module.exports.serializeURLOrigin = function (url) { + // https://url.spec.whatwg.org/#concept-url-origin + switch (url.scheme) { + case "blob": + try { + return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0])); + } catch (e) { + // serializing an opaque origin returns "null" + return "null"; + } + case "ftp": + case "gopher": + case "http": + case "https": + case "ws": + case "wss": + return serializeOrigin({ + scheme: url.scheme, + host: url.host, + port: url.port + }); + case "file": + // spec says "exercise to the reader", chrome says "file://" + return "file://"; + default: + // serializing an opaque origin returns "null" + return "null"; + } +}; + +module.exports.basicURLParse = function (input, options) { + if (options === undefined) { + options = {}; + } + + const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride); + if (usm.failure) { + return "failure"; + } + + return usm.url; +}; + +module.exports.setTheUsername = function (url, username) { + url.username = ""; + const decoded = punycode.ucs2.decode(username); + for (let i = 0; i < decoded.length; ++i) { + url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.setThePassword = function (url, password) { + url.password = ""; + const decoded = punycode.ucs2.decode(password); + for (let i = 0; i < decoded.length; ++i) { + url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.serializeHost = serializeHost; + +module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort; + +module.exports.serializeInteger = function (integer) { + return String(integer); +}; + +module.exports.parseURL = function (input, options) { + if (options === undefined) { + options = {}; + } + + // We don't handle blobs, so this just delegates: + return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride }); +}; + + +/***/ }), + +/***/ 276: +/***/ ((module) => { + +"use strict"; + + +module.exports.mixin = function mixin(target, source) { + const keys = Object.getOwnPropertyNames(source); + for (let i = 0; i < keys.length; ++i) { + Object.defineProperty(target, keys[i], Object.getOwnPropertyDescriptor(source, keys[i])); + } +}; + +module.exports.wrapperSymbol = Symbol("wrapper"); +module.exports.implSymbol = Symbol("impl"); + +module.exports.wrapperForImpl = function (impl) { + return impl[module.exports.wrapperSymbol]; +}; + +module.exports.implForWrapper = function (wrapper) { + return wrapper[module.exports.implSymbol]; +}; + + + +/***/ }), + +/***/ 1223: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +var wrappy = __nccwpck_require__(2940) +module.exports = wrappy(once) +module.exports.strict = wrappy(onceStrict) + +once.proto = once(function () { + Object.defineProperty(Function.prototype, 'once', { + value: function () { + return once(this) + }, + configurable: true + }) + + Object.defineProperty(Function.prototype, 'onceStrict', { + value: function () { + return onceStrict(this) + }, + configurable: true + }) +}) + +function once (fn) { + var f = function () { + if (f.called) return f.value + f.called = true + return f.value = fn.apply(this, arguments) + } + f.called = false + return f +} + +function onceStrict (fn) { + var f = function () { + if (f.called) + throw new Error(f.onceError) + f.called = true + return f.value = fn.apply(this, arguments) + } + var name = fn.name || 'Function wrapped with `once`' + f.onceError = name + " shouldn't be called more than once" + f.called = false + return f +} + + +/***/ }), + +/***/ 4294: +/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { + +module.exports = __nccwpck_require__(4219); + + +/***/ }), + +/***/ 4219: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +var net = __nccwpck_require__(1808); +var tls = __nccwpck_require__(4404); +var http = __nccwpck_require__(3685); +var https = __nccwpck_require__(5687); +var events = __nccwpck_require__(2361); +var assert = __nccwpck_require__(9491); +var util = __nccwpck_require__(3837); + + +exports.httpOverHttp = httpOverHttp; +exports.httpsOverHttp = httpsOverHttp; +exports.httpOverHttps = httpOverHttps; +exports.httpsOverHttps = httpsOverHttps; + + +function httpOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + return agent; +} + +function httpsOverHttp(options) { + var agent = new TunnelingAgent(options); + agent.request = http.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + +function httpOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + return agent; +} + +function httpsOverHttps(options) { + var agent = new TunnelingAgent(options); + agent.request = https.request; + agent.createSocket = createSecureSocket; + agent.defaultPort = 443; + return agent; +} + + +function TunnelingAgent(options) { + var self = this; + self.options = options || {}; + self.proxyOptions = self.options.proxy || {}; + self.maxSockets = self.options.maxSockets || http.Agent.defaultMaxSockets; + self.requests = []; + self.sockets = []; + + self.on('free', function onFree(socket, host, port, localAddress) { + var options = toOptions(host, port, localAddress); + for (var i = 0, len = self.requests.length; i < len; ++i) { + var pending = self.requests[i]; + if (pending.host === options.host && pending.port === options.port) { + // Detect the request to connect same origin server, + // reuse the connection. + self.requests.splice(i, 1); + pending.request.onSocket(socket); + return; + } + } + socket.destroy(); + self.removeSocket(socket); + }); +} +util.inherits(TunnelingAgent, events.EventEmitter); + +TunnelingAgent.prototype.addRequest = function addRequest(req, host, port, localAddress) { + var self = this; + var options = mergeOptions({request: req}, self.options, toOptions(host, port, localAddress)); + + if (self.sockets.length >= this.maxSockets) { + // We are over limit so we'll add it to the queue. + self.requests.push(options); + return; + } + + // If we are under maxSockets create a new one. + self.createSocket(options, function(socket) { + socket.on('free', onFree); + socket.on('close', onCloseOrRemove); + socket.on('agentRemove', onCloseOrRemove); + req.onSocket(socket); + + function onFree() { + self.emit('free', socket, options); + } + + function onCloseOrRemove(err) { + self.removeSocket(socket); + socket.removeListener('free', onFree); + socket.removeListener('close', onCloseOrRemove); + socket.removeListener('agentRemove', onCloseOrRemove); + } + }); +}; + +TunnelingAgent.prototype.createSocket = function createSocket(options, cb) { + var self = this; + var placeholder = {}; + self.sockets.push(placeholder); + + var connectOptions = mergeOptions({}, self.proxyOptions, { + method: 'CONNECT', + path: options.host + ':' + options.port, + agent: false, + headers: { + host: options.host + ':' + options.port + } + }); + if (options.localAddress) { + connectOptions.localAddress = options.localAddress; + } + if (connectOptions.proxyAuth) { + connectOptions.headers = connectOptions.headers || {}; + connectOptions.headers['Proxy-Authorization'] = 'Basic ' + + new Buffer(connectOptions.proxyAuth).toString('base64'); + } + + debug('making CONNECT request'); + var connectReq = self.request(connectOptions); + connectReq.useChunkedEncodingByDefault = false; // for v0.6 + connectReq.once('response', onResponse); // for v0.6 + connectReq.once('upgrade', onUpgrade); // for v0.6 + connectReq.once('connect', onConnect); // for v0.7 or later + connectReq.once('error', onError); + connectReq.end(); + + function onResponse(res) { + // Very hacky. This is necessary to avoid http-parser leaks. + res.upgrade = true; + } + + function onUpgrade(res, socket, head) { + // Hacky. + process.nextTick(function() { + onConnect(res, socket, head); + }); + } + + function onConnect(res, socket, head) { + connectReq.removeAllListeners(); + socket.removeAllListeners(); + + if (res.statusCode !== 200) { + debug('tunneling socket could not be established, statusCode=%d', + res.statusCode); + socket.destroy(); + var error = new Error('tunneling socket could not be established, ' + + 'statusCode=' + res.statusCode); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + if (head.length > 0) { + debug('got illegal response body from proxy'); + socket.destroy(); + var error = new Error('got illegal response body from proxy'); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + return; + } + debug('tunneling connection has established'); + self.sockets[self.sockets.indexOf(placeholder)] = socket; + return cb(socket); + } + + function onError(cause) { + connectReq.removeAllListeners(); + + debug('tunneling socket could not be established, cause=%s\n', + cause.message, cause.stack); + var error = new Error('tunneling socket could not be established, ' + + 'cause=' + cause.message); + error.code = 'ECONNRESET'; + options.request.emit('error', error); + self.removeSocket(placeholder); + } +}; + +TunnelingAgent.prototype.removeSocket = function removeSocket(socket) { + var pos = this.sockets.indexOf(socket) + if (pos === -1) { + return; + } + this.sockets.splice(pos, 1); + + var pending = this.requests.shift(); + if (pending) { + // If we have pending requests and a socket gets closed a new one + // needs to be created to take over in the pool for the one that closed. + this.createSocket(pending, function(socket) { + pending.request.onSocket(socket); + }); + } +}; + +function createSecureSocket(options, cb) { + var self = this; + TunnelingAgent.prototype.createSocket.call(self, options, function(socket) { + var hostHeader = options.request.getHeader('host'); + var tlsOptions = mergeOptions({}, self.options, { + socket: socket, + servername: hostHeader ? hostHeader.replace(/:.*$/, '') : options.host + }); + + // 0 is dummy port for v0.6 + var secureSocket = tls.connect(0, tlsOptions); + self.sockets[self.sockets.indexOf(socket)] = secureSocket; + cb(secureSocket); + }); +} + + +function toOptions(host, port, localAddress) { + if (typeof host === 'string') { // since v0.10 + return { + host: host, + port: port, + localAddress: localAddress + }; + } + return host; // for v0.11 or later +} + +function mergeOptions(target) { + for (var i = 1, len = arguments.length; i < len; ++i) { + var overrides = arguments[i]; + if (typeof overrides === 'object') { + var keys = Object.keys(overrides); + for (var j = 0, keyLen = keys.length; j < keyLen; ++j) { + var k = keys[j]; + if (overrides[k] !== undefined) { + target[k] = overrides[k]; + } + } + } + } + return target; +} + + +var debug; +if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) { + debug = function() { + var args = Array.prototype.slice.call(arguments); + if (typeof args[0] === 'string') { + args[0] = 'TUNNEL: ' + args[0]; + } else { + args.unshift('TUNNEL:'); + } + console.error.apply(console, args); + } +} else { + debug = function() {}; +} +exports.debug = debug; // for test + + +/***/ }), + +/***/ 5030: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +function getUserAgent() { + if (typeof navigator === "object" && "userAgent" in navigator) { + return navigator.userAgent; + } + + if (typeof process === "object" && "version" in process) { + return `Node.js/${process.version.substr(1)} (${process.platform}; ${process.arch})`; + } + + return ""; +} + +exports.getUserAgent = getUserAgent; +//# sourceMappingURL=index.js.map + + +/***/ }), + +/***/ 5840: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +Object.defineProperty(exports, "v1", ({ + enumerable: true, + get: function () { + return _v.default; + } +})); +Object.defineProperty(exports, "v3", ({ + enumerable: true, + get: function () { + return _v2.default; + } +})); +Object.defineProperty(exports, "v4", ({ + enumerable: true, + get: function () { + return _v3.default; + } +})); +Object.defineProperty(exports, "v5", ({ + enumerable: true, + get: function () { + return _v4.default; + } +})); +Object.defineProperty(exports, "NIL", ({ + enumerable: true, + get: function () { + return _nil.default; + } +})); +Object.defineProperty(exports, "version", ({ + enumerable: true, + get: function () { + return _version.default; + } +})); +Object.defineProperty(exports, "validate", ({ + enumerable: true, + get: function () { + return _validate.default; + } +})); +Object.defineProperty(exports, "stringify", ({ + enumerable: true, + get: function () { + return _stringify.default; + } +})); +Object.defineProperty(exports, "parse", ({ + enumerable: true, + get: function () { + return _parse.default; + } +})); + +var _v = _interopRequireDefault(__nccwpck_require__(8628)); + +var _v2 = _interopRequireDefault(__nccwpck_require__(6409)); + +var _v3 = _interopRequireDefault(__nccwpck_require__(5122)); + +var _v4 = _interopRequireDefault(__nccwpck_require__(9120)); + +var _nil = _interopRequireDefault(__nccwpck_require__(5332)); + +var _version = _interopRequireDefault(__nccwpck_require__(1595)); + +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); + +var _parse = _interopRequireDefault(__nccwpck_require__(2746)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/***/ }), + +/***/ 4569: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function md5(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('md5').update(bytes).digest(); +} + +var _default = md5; +exports["default"] = _default; + +/***/ }), + +/***/ 5332: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = '00000000-0000-0000-0000-000000000000'; +exports["default"] = _default; + +/***/ }), + +/***/ 2746: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function parse(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + let v; + const arr = new Uint8Array(16); // Parse ########-....-....-....-............ + + arr[0] = (v = parseInt(uuid.slice(0, 8), 16)) >>> 24; + arr[1] = v >>> 16 & 0xff; + arr[2] = v >>> 8 & 0xff; + arr[3] = v & 0xff; // Parse ........-####-....-....-............ + + arr[4] = (v = parseInt(uuid.slice(9, 13), 16)) >>> 8; + arr[5] = v & 0xff; // Parse ........-....-####-....-............ + + arr[6] = (v = parseInt(uuid.slice(14, 18), 16)) >>> 8; + arr[7] = v & 0xff; // Parse ........-....-....-####-............ + + arr[8] = (v = parseInt(uuid.slice(19, 23), 16)) >>> 8; + arr[9] = v & 0xff; // Parse ........-....-....-....-############ + // (Use "/" to avoid 32-bit truncation when bit-shifting high-order bytes) + + arr[10] = (v = parseInt(uuid.slice(24, 36), 16)) / 0x10000000000 & 0xff; + arr[11] = v / 0x100000000 & 0xff; + arr[12] = v >>> 24 & 0xff; + arr[13] = v >>> 16 & 0xff; + arr[14] = v >>> 8 & 0xff; + arr[15] = v & 0xff; + return arr; +} + +var _default = parse; +exports["default"] = _default; + +/***/ }), + +/***/ 814: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; +var _default = /^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i; +exports["default"] = _default; + +/***/ }), + +/***/ 807: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = rng; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const rnds8Pool = new Uint8Array(256); // # of random values to pre-allocate + +let poolPtr = rnds8Pool.length; + +function rng() { + if (poolPtr > rnds8Pool.length - 16) { + _crypto.default.randomFillSync(rnds8Pool); + + poolPtr = 0; + } + + return rnds8Pool.slice(poolPtr, poolPtr += 16); +} + +/***/ }), + +/***/ 5274: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _crypto = _interopRequireDefault(__nccwpck_require__(6113)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function sha1(bytes) { + if (Array.isArray(bytes)) { + bytes = Buffer.from(bytes); + } else if (typeof bytes === 'string') { + bytes = Buffer.from(bytes, 'utf8'); + } + + return _crypto.default.createHash('sha1').update(bytes).digest(); +} + +var _default = sha1; +exports["default"] = _default; + +/***/ }), + +/***/ 8950: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Convert array of 16 byte values to UUID string format of the form: + * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + */ +const byteToHex = []; + +for (let i = 0; i < 256; ++i) { + byteToHex.push((i + 0x100).toString(16).substr(1)); +} + +function stringify(arr, offset = 0) { + // Note: Be careful editing this code! It's been tuned for performance + // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434 + const uuid = (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); // Consistency check for valid UUID. If this throws, it's likely due to one + // of the following: + // - One or more input array values don't map to a hex octet (leading to + // "undefined" in the uuid) + // - Invalid input values for the RFC `version` or `variant` fields + + if (!(0, _validate.default)(uuid)) { + throw TypeError('Stringified UUID is invalid'); + } + + return uuid; +} + +var _default = stringify; +exports["default"] = _default; + +/***/ }), + +/***/ 8628: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(807)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// **`v1()` - Generate time-based UUID** +// +// Inspired by https://github.com/LiosK/UUID.js +// and http://docs.python.org/library/uuid.html +let _nodeId; + +let _clockseq; // Previous uuid creation time + + +let _lastMSecs = 0; +let _lastNSecs = 0; // See https://github.com/uuidjs/uuid for API details + +function v1(options, buf, offset) { + let i = buf && offset || 0; + const b = buf || new Array(16); + options = options || {}; + let node = options.node || _nodeId; + let clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not + // specified. We do this lazily to minimize issues related to insufficient + // system entropy. See #189 + + if (node == null || clockseq == null) { + const seedBytes = options.random || (options.rng || _rng.default)(); + + if (node == null) { + // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) + node = _nodeId = [seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5]]; + } + + if (clockseq == null) { + // Per 4.2.2, randomize (14 bit) clockseq + clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; + } + } // UUID timestamps are 100 nano-second units since the Gregorian epoch, + // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so + // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' + // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. + + + let msecs = options.msecs !== undefined ? options.msecs : Date.now(); // Per 4.2.1.2, use count of uuid's generated during the current clock + // cycle to simulate higher resolution clock + + let nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) + + const dt = msecs - _lastMSecs + (nsecs - _lastNSecs) / 10000; // Per 4.2.1.2, Bump clockseq on clock regression + + if (dt < 0 && options.clockseq === undefined) { + clockseq = clockseq + 1 & 0x3fff; + } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new + // time interval + + + if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { + nsecs = 0; + } // Per 4.2.1.2 Throw error if too many uuids are requested + + + if (nsecs >= 10000) { + throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); + } + + _lastMSecs = msecs; + _lastNSecs = nsecs; + _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch + + msecs += 12219292800000; // `time_low` + + const tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; + b[i++] = tl >>> 24 & 0xff; + b[i++] = tl >>> 16 & 0xff; + b[i++] = tl >>> 8 & 0xff; + b[i++] = tl & 0xff; // `time_mid` + + const tmh = msecs / 0x100000000 * 10000 & 0xfffffff; + b[i++] = tmh >>> 8 & 0xff; + b[i++] = tmh & 0xff; // `time_high_and_version` + + b[i++] = tmh >>> 24 & 0xf | 0x10; // include version + + b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) + + b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` + + b[i++] = clockseq & 0xff; // `node` + + for (let n = 0; n < 6; ++n) { + b[i + n] = node[n]; + } + + return buf || (0, _stringify.default)(b); +} + +var _default = v1; +exports["default"] = _default; + +/***/ }), + +/***/ 6409: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(5998)); + +var _md = _interopRequireDefault(__nccwpck_require__(4569)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v3 = (0, _v.default)('v3', 0x30, _md.default); +var _default = v3; +exports["default"] = _default; + +/***/ }), + +/***/ 5998: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = _default; +exports.URL = exports.DNS = void 0; + +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); + +var _parse = _interopRequireDefault(__nccwpck_require__(2746)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function stringToBytes(str) { + str = unescape(encodeURIComponent(str)); // UTF8 escape + + const bytes = []; + + for (let i = 0; i < str.length; ++i) { + bytes.push(str.charCodeAt(i)); + } + + return bytes; +} + +const DNS = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; +exports.DNS = DNS; +const URL = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'; +exports.URL = URL; + +function _default(name, version, hashfunc) { + function generateUUID(value, namespace, buf, offset) { + if (typeof value === 'string') { + value = stringToBytes(value); + } + + if (typeof namespace === 'string') { + namespace = (0, _parse.default)(namespace); + } + + if (namespace.length !== 16) { + throw TypeError('Namespace must be array-like (16 iterable integer values, 0-255)'); + } // Compute hash of namespace and value, Per 4.3 + // Future: Use spread syntax when supported on all platforms, e.g. `bytes = + // hashfunc([...namespace, ... value])` + + + let bytes = new Uint8Array(16 + value.length); + bytes.set(namespace); + bytes.set(value, namespace.length); + bytes = hashfunc(bytes); + bytes[6] = bytes[6] & 0x0f | version; + bytes[8] = bytes[8] & 0x3f | 0x80; + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = bytes[i]; + } + + return buf; + } + + return (0, _stringify.default)(bytes); + } // Function#name is not settable on some platforms (#270) + + + try { + generateUUID.name = name; // eslint-disable-next-line no-empty + } catch (err) {} // For CommonJS default export support + + + generateUUID.DNS = DNS; + generateUUID.URL = URL; + return generateUUID; +} + +/***/ }), + +/***/ 5122: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _rng = _interopRequireDefault(__nccwpck_require__(807)); + +var _stringify = _interopRequireDefault(__nccwpck_require__(8950)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function v4(options, buf, offset) { + options = options || {}; + + const rnds = options.random || (options.rng || _rng.default)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` + + + rnds[6] = rnds[6] & 0x0f | 0x40; + rnds[8] = rnds[8] & 0x3f | 0x80; // Copy bytes to buffer, if provided + + if (buf) { + offset = offset || 0; + + for (let i = 0; i < 16; ++i) { + buf[offset + i] = rnds[i]; + } + + return buf; + } + + return (0, _stringify.default)(rnds); +} + +var _default = v4; +exports["default"] = _default; + +/***/ }), + +/***/ 9120: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _v = _interopRequireDefault(__nccwpck_require__(5998)); + +var _sha = _interopRequireDefault(__nccwpck_require__(5274)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +const v5 = (0, _v.default)('v5', 0x50, _sha.default); +var _default = v5; +exports["default"] = _default; + +/***/ }), + +/***/ 6900: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _regex = _interopRequireDefault(__nccwpck_require__(814)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function validate(uuid) { + return typeof uuid === 'string' && _regex.default.test(uuid); +} + +var _default = validate; +exports["default"] = _default; + +/***/ }), + +/***/ 1595: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ + value: true +})); +exports["default"] = void 0; + +var _validate = _interopRequireDefault(__nccwpck_require__(6900)); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function version(uuid) { + if (!(0, _validate.default)(uuid)) { + throw TypeError('Invalid UUID'); + } + + return parseInt(uuid.substr(14, 1), 16); +} + +var _default = version; +exports["default"] = _default; + +/***/ }), + +/***/ 1452: +/***/ (function(__unused_webpack_module, exports) { + +/** + * @license + * web-streams-polyfill v3.3.3 + * Copyright 2024 Mattias Buelens, Diwank Singh Tomer and other contributors. + * This code is released under the MIT license. + * SPDX-License-Identifier: MIT + */ +(function (global, factory) { + true ? factory(exports) : + 0; +})(this, (function (exports) { 'use strict'; + + function noop() { + return undefined; + } + + function typeIsObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; + } + const rethrowAssertionErrorRejection = noop; + function setFunctionName(fn, name) { + try { + Object.defineProperty(fn, 'name', { + value: name, + configurable: true + }); + } + catch (_a) { + // This property is non-configurable in older browsers, so ignore if this throws. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#browser_compatibility + } + } + + const originalPromise = Promise; + const originalPromiseThen = Promise.prototype.then; + const originalPromiseReject = Promise.reject.bind(originalPromise); + // https://webidl.spec.whatwg.org/#a-new-promise + function newPromise(executor) { + return new originalPromise(executor); + } + // https://webidl.spec.whatwg.org/#a-promise-resolved-with + function promiseResolvedWith(value) { + return newPromise(resolve => resolve(value)); + } + // https://webidl.spec.whatwg.org/#a-promise-rejected-with + function promiseRejectedWith(reason) { + return originalPromiseReject(reason); + } + function PerformPromiseThen(promise, onFulfilled, onRejected) { + // There doesn't appear to be any way to correctly emulate the behaviour from JavaScript, so this is just an + // approximation. + return originalPromiseThen.call(promise, onFulfilled, onRejected); + } + // Bluebird logs a warning when a promise is created within a fulfillment handler, but then isn't returned + // from that handler. To prevent this, return null instead of void from all handlers. + // http://bluebirdjs.com/docs/warning-explanations.html#warning-a-promise-was-created-in-a-handler-but-was-not-returned-from-it + function uponPromise(promise, onFulfilled, onRejected) { + PerformPromiseThen(PerformPromiseThen(promise, onFulfilled, onRejected), undefined, rethrowAssertionErrorRejection); + } + function uponFulfillment(promise, onFulfilled) { + uponPromise(promise, onFulfilled); + } + function uponRejection(promise, onRejected) { + uponPromise(promise, undefined, onRejected); + } + function transformPromiseWith(promise, fulfillmentHandler, rejectionHandler) { + return PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler); + } + function setPromiseIsHandledToTrue(promise) { + PerformPromiseThen(promise, undefined, rethrowAssertionErrorRejection); + } + let _queueMicrotask = callback => { + if (typeof queueMicrotask === 'function') { + _queueMicrotask = queueMicrotask; + } + else { + const resolvedPromise = promiseResolvedWith(undefined); + _queueMicrotask = cb => PerformPromiseThen(resolvedPromise, cb); + } + return _queueMicrotask(callback); + }; + function reflectCall(F, V, args) { + if (typeof F !== 'function') { + throw new TypeError('Argument is not a function'); + } + return Function.prototype.apply.call(F, V, args); + } + function promiseCall(F, V, args) { + try { + return promiseResolvedWith(reflectCall(F, V, args)); + } + catch (value) { + return promiseRejectedWith(value); + } + } + + // Original from Chromium + // https://chromium.googlesource.com/chromium/src/+/0aee4434a4dba42a42abaea9bfbc0cd196a63bc1/third_party/blink/renderer/core/streams/SimpleQueue.js + const QUEUE_MAX_ARRAY_SIZE = 16384; + /** + * Simple queue structure. + * + * Avoids scalability issues with using a packed array directly by using + * multiple arrays in a linked list and keeping the array size bounded. + */ + class SimpleQueue { + constructor() { + this._cursor = 0; + this._size = 0; + // _front and _back are always defined. + this._front = { + _elements: [], + _next: undefined + }; + this._back = this._front; + // The cursor is used to avoid calling Array.shift(). + // It contains the index of the front element of the array inside the + // front-most node. It is always in the range [0, QUEUE_MAX_ARRAY_SIZE). + this._cursor = 0; + // When there is only one node, size === elements.length - cursor. + this._size = 0; + } + get length() { + return this._size; + } + // For exception safety, this method is structured in order: + // 1. Read state + // 2. Calculate required state mutations + // 3. Perform state mutations + push(element) { + const oldBack = this._back; + let newBack = oldBack; + if (oldBack._elements.length === QUEUE_MAX_ARRAY_SIZE - 1) { + newBack = { + _elements: [], + _next: undefined + }; + } + // push() is the mutation most likely to throw an exception, so it + // goes first. + oldBack._elements.push(element); + if (newBack !== oldBack) { + this._back = newBack; + oldBack._next = newBack; + } + ++this._size; + } + // Like push(), shift() follows the read -> calculate -> mutate pattern for + // exception safety. + shift() { // must not be called on an empty queue + const oldFront = this._front; + let newFront = oldFront; + const oldCursor = this._cursor; + let newCursor = oldCursor + 1; + const elements = oldFront._elements; + const element = elements[oldCursor]; + if (newCursor === QUEUE_MAX_ARRAY_SIZE) { + newFront = oldFront._next; + newCursor = 0; + } + // No mutations before this point. + --this._size; + this._cursor = newCursor; + if (oldFront !== newFront) { + this._front = newFront; + } + // Permit shifted element to be garbage collected. + elements[oldCursor] = undefined; + return element; + } + // The tricky thing about forEach() is that it can be called + // re-entrantly. The queue may be mutated inside the callback. It is easy to + // see that push() within the callback has no negative effects since the end + // of the queue is checked for on every iteration. If shift() is called + // repeatedly within the callback then the next iteration may return an + // element that has been removed. In this case the callback will be called + // with undefined values until we either "catch up" with elements that still + // exist or reach the back of the queue. + forEach(callback) { + let i = this._cursor; + let node = this._front; + let elements = node._elements; + while (i !== elements.length || node._next !== undefined) { + if (i === elements.length) { + node = node._next; + elements = node._elements; + i = 0; + if (elements.length === 0) { + break; + } + } + callback(elements[i]); + ++i; + } + } + // Return the element that would be returned if shift() was called now, + // without modifying the queue. + peek() { // must not be called on an empty queue + const front = this._front; + const cursor = this._cursor; + return front._elements[cursor]; + } + } + + const AbortSteps = Symbol('[[AbortSteps]]'); + const ErrorSteps = Symbol('[[ErrorSteps]]'); + const CancelSteps = Symbol('[[CancelSteps]]'); + const PullSteps = Symbol('[[PullSteps]]'); + const ReleaseSteps = Symbol('[[ReleaseSteps]]'); + + function ReadableStreamReaderGenericInitialize(reader, stream) { + reader._ownerReadableStream = stream; + stream._reader = reader; + if (stream._state === 'readable') { + defaultReaderClosedPromiseInitialize(reader); + } + else if (stream._state === 'closed') { + defaultReaderClosedPromiseInitializeAsResolved(reader); + } + else { + defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError); + } + } + // A client of ReadableStreamDefaultReader and ReadableStreamBYOBReader may use these functions directly to bypass state + // check. + function ReadableStreamReaderGenericCancel(reader, reason) { + const stream = reader._ownerReadableStream; + return ReadableStreamCancel(stream, reason); + } + function ReadableStreamReaderGenericRelease(reader) { + const stream = reader._ownerReadableStream; + if (stream._state === 'readable') { + defaultReaderClosedPromiseReject(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + else { + defaultReaderClosedPromiseResetToRejected(reader, new TypeError(`Reader was released and can no longer be used to monitor the stream's closedness`)); + } + stream._readableStreamController[ReleaseSteps](); + stream._reader = undefined; + reader._ownerReadableStream = undefined; + } + // Helper functions for the readers. + function readerLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released reader'); + } + // Helper functions for the ReadableStreamDefaultReader. + function defaultReaderClosedPromiseInitialize(reader) { + reader._closedPromise = newPromise((resolve, reject) => { + reader._closedPromise_resolve = resolve; + reader._closedPromise_reject = reject; + }); + } + function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseReject(reader, reason); + } + function defaultReaderClosedPromiseInitializeAsResolved(reader) { + defaultReaderClosedPromiseInitialize(reader); + defaultReaderClosedPromiseResolve(reader); + } + function defaultReaderClosedPromiseReject(reader, reason) { + if (reader._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(reader._closedPromise); + reader._closedPromise_reject(reason); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; + } + function defaultReaderClosedPromiseResetToRejected(reader, reason) { + defaultReaderClosedPromiseInitializeAsRejected(reader, reason); + } + function defaultReaderClosedPromiseResolve(reader) { + if (reader._closedPromise_resolve === undefined) { + return; + } + reader._closedPromise_resolve(undefined); + reader._closedPromise_resolve = undefined; + reader._closedPromise_reject = undefined; + } + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isFinite#Polyfill + const NumberIsFinite = Number.isFinite || function (x) { + return typeof x === 'number' && isFinite(x); + }; + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc#Polyfill + const MathTrunc = Math.trunc || function (v) { + return v < 0 ? Math.ceil(v) : Math.floor(v); + }; + + // https://heycam.github.io/webidl/#idl-dictionaries + function isDictionary(x) { + return typeof x === 'object' || typeof x === 'function'; + } + function assertDictionary(obj, context) { + if (obj !== undefined && !isDictionary(obj)) { + throw new TypeError(`${context} is not an object.`); + } + } + // https://heycam.github.io/webidl/#idl-callback-functions + function assertFunction(x, context) { + if (typeof x !== 'function') { + throw new TypeError(`${context} is not a function.`); + } + } + // https://heycam.github.io/webidl/#idl-object + function isObject(x) { + return (typeof x === 'object' && x !== null) || typeof x === 'function'; + } + function assertObject(x, context) { + if (!isObject(x)) { + throw new TypeError(`${context} is not an object.`); + } + } + function assertRequiredArgument(x, position, context) { + if (x === undefined) { + throw new TypeError(`Parameter ${position} is required in '${context}'.`); + } + } + function assertRequiredField(x, field, context) { + if (x === undefined) { + throw new TypeError(`${field} is required in '${context}'.`); + } + } + // https://heycam.github.io/webidl/#idl-unrestricted-double + function convertUnrestrictedDouble(value) { + return Number(value); + } + function censorNegativeZero(x) { + return x === 0 ? 0 : x; + } + function integerPart(x) { + return censorNegativeZero(MathTrunc(x)); + } + // https://heycam.github.io/webidl/#idl-unsigned-long-long + function convertUnsignedLongLongWithEnforceRange(value, context) { + const lowerBound = 0; + const upperBound = Number.MAX_SAFE_INTEGER; + let x = Number(value); + x = censorNegativeZero(x); + if (!NumberIsFinite(x)) { + throw new TypeError(`${context} is not a finite number`); + } + x = integerPart(x); + if (x < lowerBound || x > upperBound) { + throw new TypeError(`${context} is outside the accepted range of ${lowerBound} to ${upperBound}, inclusive`); + } + if (!NumberIsFinite(x) || x === 0) { + return 0; + } + // TODO Use BigInt if supported? + // let xBigInt = BigInt(integerPart(x)); + // xBigInt = BigInt.asUintN(64, xBigInt); + // return Number(xBigInt); + return x; + } + + function assertReadableStream(x, context) { + if (!IsReadableStream(x)) { + throw new TypeError(`${context} is not a ReadableStream.`); + } + } + + // Abstract operations for the ReadableStream. + function AcquireReadableStreamDefaultReader(stream) { + return new ReadableStreamDefaultReader(stream); + } + // ReadableStream API exposed for controllers. + function ReadableStreamAddReadRequest(stream, readRequest) { + stream._reader._readRequests.push(readRequest); + } + function ReadableStreamFulfillReadRequest(stream, chunk, done) { + const reader = stream._reader; + const readRequest = reader._readRequests.shift(); + if (done) { + readRequest._closeSteps(); + } + else { + readRequest._chunkSteps(chunk); + } + } + function ReadableStreamGetNumReadRequests(stream) { + return stream._reader._readRequests.length; + } + function ReadableStreamHasDefaultReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamDefaultReader(reader)) { + return false; + } + return true; + } + /** + * A default reader vended by a {@link ReadableStream}. + * + * @public + */ + class ReadableStreamDefaultReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamDefaultReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, + * or rejected if the stream ever errors or the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + /** + * Returns a promise that allows access to the next chunk from the stream's internal queue, if available. + * + * If reading a chunk causes the queue to become empty, more data will be pulled from the underlying source. + */ + read() { + if (!IsReadableStreamDefaultReader(this)) { + return promiseRejectedWith(defaultReaderBrandCheckException('read')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: () => resolvePromise({ value: undefined, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamDefaultReaderRead(this, readRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamDefaultReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamDefaultReader(this)) { + throw defaultReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + ReadableStreamDefaultReaderRelease(this); + } + } + Object.defineProperties(ReadableStreamDefaultReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } + }); + setFunctionName(ReadableStreamDefaultReader.prototype.cancel, 'cancel'); + setFunctionName(ReadableStreamDefaultReader.prototype.read, 'read'); + setFunctionName(ReadableStreamDefaultReader.prototype.releaseLock, 'releaseLock'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultReader.prototype, Symbol.toStringTag, { + value: 'ReadableStreamDefaultReader', + configurable: true + }); + } + // Abstract operations for the readers. + function IsReadableStreamDefaultReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) { + return false; + } + return x instanceof ReadableStreamDefaultReader; + } + function ReadableStreamDefaultReaderRead(reader, readRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'closed') { + readRequest._closeSteps(); + } + else if (stream._state === 'errored') { + readRequest._errorSteps(stream._storedError); + } + else { + stream._readableStreamController[PullSteps](readRequest); + } + } + function ReadableStreamDefaultReaderRelease(reader) { + ReadableStreamReaderGenericRelease(reader); + const e = new TypeError('Reader was released'); + ReadableStreamDefaultReaderErrorReadRequests(reader, e); + } + function ReadableStreamDefaultReaderErrorReadRequests(reader, e) { + const readRequests = reader._readRequests; + reader._readRequests = new SimpleQueue(); + readRequests.forEach(readRequest => { + readRequest._errorSteps(e); + }); + } + // Helper functions for the ReadableStreamDefaultReader. + function defaultReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamDefaultReader.prototype.${name} can only be used on a ReadableStreamDefaultReader`); + } + + /// + /* eslint-disable @typescript-eslint/no-empty-function */ + const AsyncIteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(async function* () { }).prototype); + + /// + class ReadableStreamAsyncIteratorImpl { + constructor(reader, preventCancel) { + this._ongoingPromise = undefined; + this._isFinished = false; + this._reader = reader; + this._preventCancel = preventCancel; + } + next() { + const nextSteps = () => this._nextSteps(); + this._ongoingPromise = this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, nextSteps, nextSteps) : + nextSteps(); + return this._ongoingPromise; + } + return(value) { + const returnSteps = () => this._returnSteps(value); + return this._ongoingPromise ? + transformPromiseWith(this._ongoingPromise, returnSteps, returnSteps) : + returnSteps(); + } + _nextSteps() { + if (this._isFinished) { + return Promise.resolve({ value: undefined, done: true }); + } + const reader = this._reader; + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readRequest = { + _chunkSteps: chunk => { + this._ongoingPromise = undefined; + // This needs to be delayed by one microtask, otherwise we stop pulling too early which breaks a test. + // FIXME Is this a bug in the specification, or in the test? + _queueMicrotask(() => resolvePromise({ value: chunk, done: false })); + }, + _closeSteps: () => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + resolvePromise({ value: undefined, done: true }); + }, + _errorSteps: reason => { + this._ongoingPromise = undefined; + this._isFinished = true; + ReadableStreamReaderGenericRelease(reader); + rejectPromise(reason); + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promise; + } + _returnSteps(value) { + if (this._isFinished) { + return Promise.resolve({ value, done: true }); + } + this._isFinished = true; + const reader = this._reader; + if (!this._preventCancel) { + const result = ReadableStreamReaderGenericCancel(reader, value); + ReadableStreamReaderGenericRelease(reader); + return transformPromiseWith(result, () => ({ value, done: true })); + } + ReadableStreamReaderGenericRelease(reader); + return promiseResolvedWith({ value, done: true }); + } + } + const ReadableStreamAsyncIteratorPrototype = { + next() { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('next')); + } + return this._asyncIteratorImpl.next(); + }, + return(value) { + if (!IsReadableStreamAsyncIterator(this)) { + return promiseRejectedWith(streamAsyncIteratorBrandCheckException('return')); + } + return this._asyncIteratorImpl.return(value); + } + }; + Object.setPrototypeOf(ReadableStreamAsyncIteratorPrototype, AsyncIteratorPrototype); + // Abstract operations for the ReadableStream. + function AcquireReadableStreamAsyncIterator(stream, preventCancel) { + const reader = AcquireReadableStreamDefaultReader(stream); + const impl = new ReadableStreamAsyncIteratorImpl(reader, preventCancel); + const iterator = Object.create(ReadableStreamAsyncIteratorPrototype); + iterator._asyncIteratorImpl = impl; + return iterator; + } + function IsReadableStreamAsyncIterator(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_asyncIteratorImpl')) { + return false; + } + try { + // noinspection SuspiciousTypeOfGuard + return x._asyncIteratorImpl instanceof + ReadableStreamAsyncIteratorImpl; + } + catch (_a) { + return false; + } + } + // Helper functions for the ReadableStream. + function streamAsyncIteratorBrandCheckException(name) { + return new TypeError(`ReadableStreamAsyncIterator.${name} can only be used on a ReadableSteamAsyncIterator`); + } + + /// + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN#Polyfill + const NumberIsNaN = Number.isNaN || function (x) { + // eslint-disable-next-line no-self-compare + return x !== x; + }; + + var _a, _b, _c; + function CreateArrayFromList(elements) { + // We use arrays to represent lists, so this is basically a no-op. + // Do a slice though just in case we happen to depend on the unique-ness. + return elements.slice(); + } + function CopyDataBlockBytes(dest, destOffset, src, srcOffset, n) { + new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset); + } + let TransferArrayBuffer = (O) => { + if (typeof O.transfer === 'function') { + TransferArrayBuffer = buffer => buffer.transfer(); + } + else if (typeof structuredClone === 'function') { + TransferArrayBuffer = buffer => structuredClone(buffer, { transfer: [buffer] }); + } + else { + // Not implemented correctly + TransferArrayBuffer = buffer => buffer; + } + return TransferArrayBuffer(O); + }; + let IsDetachedBuffer = (O) => { + if (typeof O.detached === 'boolean') { + IsDetachedBuffer = buffer => buffer.detached; + } + else { + // Not implemented correctly + IsDetachedBuffer = buffer => buffer.byteLength === 0; + } + return IsDetachedBuffer(O); + }; + function ArrayBufferSlice(buffer, begin, end) { + // ArrayBuffer.prototype.slice is not available on IE10 + // https://www.caniuse.com/mdn-javascript_builtins_arraybuffer_slice + if (buffer.slice) { + return buffer.slice(begin, end); + } + const length = end - begin; + const slice = new ArrayBuffer(length); + CopyDataBlockBytes(slice, 0, buffer, begin, length); + return slice; + } + function GetMethod(receiver, prop) { + const func = receiver[prop]; + if (func === undefined || func === null) { + return undefined; + } + if (typeof func !== 'function') { + throw new TypeError(`${String(prop)} is not a function`); + } + return func; + } + function CreateAsyncFromSyncIterator(syncIteratorRecord) { + // Instead of re-implementing CreateAsyncFromSyncIterator and %AsyncFromSyncIteratorPrototype%, + // we use yield* inside an async generator function to achieve the same result. + // Wrap the sync iterator inside a sync iterable, so we can use it with yield*. + const syncIterable = { + [Symbol.iterator]: () => syncIteratorRecord.iterator + }; + // Create an async generator function and immediately invoke it. + const asyncIterator = (async function* () { + return yield* syncIterable; + }()); + // Return as an async iterator record. + const nextMethod = asyncIterator.next; + return { iterator: asyncIterator, nextMethod, done: false }; + } + // Aligns with core-js/modules/es.symbol.async-iterator.js + const SymbolAsyncIterator = (_c = (_a = Symbol.asyncIterator) !== null && _a !== void 0 ? _a : (_b = Symbol.for) === null || _b === void 0 ? void 0 : _b.call(Symbol, 'Symbol.asyncIterator')) !== null && _c !== void 0 ? _c : '@@asyncIterator'; + function GetIterator(obj, hint = 'sync', method) { + if (method === undefined) { + if (hint === 'async') { + method = GetMethod(obj, SymbolAsyncIterator); + if (method === undefined) { + const syncMethod = GetMethod(obj, Symbol.iterator); + const syncIteratorRecord = GetIterator(obj, 'sync', syncMethod); + return CreateAsyncFromSyncIterator(syncIteratorRecord); + } + } + else { + method = GetMethod(obj, Symbol.iterator); + } + } + if (method === undefined) { + throw new TypeError('The object is not iterable'); + } + const iterator = reflectCall(method, obj, []); + if (!typeIsObject(iterator)) { + throw new TypeError('The iterator method must return an object'); + } + const nextMethod = iterator.next; + return { iterator, nextMethod, done: false }; + } + function IteratorNext(iteratorRecord) { + const result = reflectCall(iteratorRecord.nextMethod, iteratorRecord.iterator, []); + if (!typeIsObject(result)) { + throw new TypeError('The iterator.next() method must return an object'); + } + return result; + } + function IteratorComplete(iterResult) { + return Boolean(iterResult.done); + } + function IteratorValue(iterResult) { + return iterResult.value; + } + + function IsNonNegativeNumber(v) { + if (typeof v !== 'number') { + return false; + } + if (NumberIsNaN(v)) { + return false; + } + if (v < 0) { + return false; + } + return true; + } + function CloneAsUint8Array(O) { + const buffer = ArrayBufferSlice(O.buffer, O.byteOffset, O.byteOffset + O.byteLength); + return new Uint8Array(buffer); + } + + function DequeueValue(container) { + const pair = container._queue.shift(); + container._queueTotalSize -= pair.size; + if (container._queueTotalSize < 0) { + container._queueTotalSize = 0; + } + return pair.value; + } + function EnqueueValueWithSize(container, value, size) { + if (!IsNonNegativeNumber(size) || size === Infinity) { + throw new RangeError('Size must be a finite, non-NaN, non-negative number.'); + } + container._queue.push({ value, size }); + container._queueTotalSize += size; + } + function PeekQueueValue(container) { + const pair = container._queue.peek(); + return pair.value; + } + function ResetQueue(container) { + container._queue = new SimpleQueue(); + container._queueTotalSize = 0; + } + + function isDataViewConstructor(ctor) { + return ctor === DataView; + } + function isDataView(view) { + return isDataViewConstructor(view.constructor); + } + function arrayBufferViewElementSize(ctor) { + if (isDataViewConstructor(ctor)) { + return 1; + } + return ctor.BYTES_PER_ELEMENT; + } + + /** + * A pull-into request in a {@link ReadableByteStreamController}. + * + * @public + */ + class ReadableStreamBYOBRequest { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the view for writing in to, or `null` if the BYOB request has already been responded to. + */ + get view() { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('view'); + } + return this._view; + } + respond(bytesWritten) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respond'); + } + assertRequiredArgument(bytesWritten, 1, 'respond'); + bytesWritten = convertUnsignedLongLongWithEnforceRange(bytesWritten, 'First parameter'); + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + if (IsDetachedBuffer(this._view.buffer)) { + throw new TypeError(`The BYOB request's buffer has been detached and so cannot be used as a response`); + } + ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten); + } + respondWithNewView(view) { + if (!IsReadableStreamBYOBRequest(this)) { + throw byobRequestBrandCheckException('respondWithNewView'); + } + assertRequiredArgument(view, 1, 'respondWithNewView'); + if (!ArrayBuffer.isView(view)) { + throw new TypeError('You can only respond with array buffer views'); + } + if (this._associatedReadableByteStreamController === undefined) { + throw new TypeError('This BYOB request has been invalidated'); + } + if (IsDetachedBuffer(view.buffer)) { + throw new TypeError('The given view\'s buffer has been detached and so cannot be used as a response'); + } + ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view); + } + } + Object.defineProperties(ReadableStreamBYOBRequest.prototype, { + respond: { enumerable: true }, + respondWithNewView: { enumerable: true }, + view: { enumerable: true } + }); + setFunctionName(ReadableStreamBYOBRequest.prototype.respond, 'respond'); + setFunctionName(ReadableStreamBYOBRequest.prototype.respondWithNewView, 'respondWithNewView'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBRequest.prototype, Symbol.toStringTag, { + value: 'ReadableStreamBYOBRequest', + configurable: true + }); + } + /** + * Allows control of a {@link ReadableStream | readable byte stream}'s state and internal queue. + * + * @public + */ + class ReadableByteStreamController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the current BYOB pull request, or `null` if there isn't one. + */ + get byobRequest() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('byobRequest'); + } + return ReadableByteStreamControllerGetBYOBRequest(this); + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying byte source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('desiredSize'); + } + return ReadableByteStreamControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('close'); + } + if (this._closeRequested) { + throw new TypeError('The stream has already been closed; do not close it again!'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be closed`); + } + ReadableByteStreamControllerClose(this); + } + enqueue(chunk) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('enqueue'); + } + assertRequiredArgument(chunk, 1, 'enqueue'); + if (!ArrayBuffer.isView(chunk)) { + throw new TypeError('chunk must be an array buffer view'); + } + if (chunk.byteLength === 0) { + throw new TypeError('chunk must have non-zero byteLength'); + } + if (chunk.buffer.byteLength === 0) { + throw new TypeError(`chunk's buffer must have non-zero byteLength`); + } + if (this._closeRequested) { + throw new TypeError('stream is closed or draining'); + } + const state = this._controlledReadableByteStream._state; + if (state !== 'readable') { + throw new TypeError(`The stream (in ${state} state) is not in the readable state and cannot be enqueued to`); + } + ReadableByteStreamControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableByteStreamController(this)) { + throw byteStreamControllerBrandCheckException('error'); + } + ReadableByteStreamControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + ReadableByteStreamControllerClearPendingPullIntos(this); + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableByteStreamControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableByteStream; + if (this._queueTotalSize > 0) { + ReadableByteStreamControllerFillReadRequestFromQueue(this, readRequest); + return; + } + const autoAllocateChunkSize = this._autoAllocateChunkSize; + if (autoAllocateChunkSize !== undefined) { + let buffer; + try { + buffer = new ArrayBuffer(autoAllocateChunkSize); + } + catch (bufferE) { + readRequest._errorSteps(bufferE); + return; + } + const pullIntoDescriptor = { + buffer, + bufferByteLength: autoAllocateChunkSize, + byteOffset: 0, + byteLength: autoAllocateChunkSize, + bytesFilled: 0, + minimumFill: 1, + elementSize: 1, + viewConstructor: Uint8Array, + readerType: 'default' + }; + this._pendingPullIntos.push(pullIntoDescriptor); + } + ReadableStreamAddReadRequest(stream, readRequest); + ReadableByteStreamControllerCallPullIfNeeded(this); + } + /** @internal */ + [ReleaseSteps]() { + if (this._pendingPullIntos.length > 0) { + const firstPullInto = this._pendingPullIntos.peek(); + firstPullInto.readerType = 'none'; + this._pendingPullIntos = new SimpleQueue(); + this._pendingPullIntos.push(firstPullInto); + } + } + } + Object.defineProperties(ReadableByteStreamController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + byobRequest: { enumerable: true }, + desiredSize: { enumerable: true } + }); + setFunctionName(ReadableByteStreamController.prototype.close, 'close'); + setFunctionName(ReadableByteStreamController.prototype.enqueue, 'enqueue'); + setFunctionName(ReadableByteStreamController.prototype.error, 'error'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(ReadableByteStreamController.prototype, Symbol.toStringTag, { + value: 'ReadableByteStreamController', + configurable: true + }); + } + // Abstract operations for the ReadableByteStreamController. + function IsReadableByteStreamController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableByteStream')) { + return false; + } + return x instanceof ReadableByteStreamController; + } + function IsReadableStreamBYOBRequest(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) { + return false; + } + return x instanceof ReadableStreamBYOBRequest; + } + function ReadableByteStreamControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableByteStreamControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + // TODO: Test controller argument + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + return null; + }, e => { + ReadableByteStreamControllerError(controller, e); + return null; + }); + } + function ReadableByteStreamControllerClearPendingPullIntos(controller) { + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + controller._pendingPullIntos = new SimpleQueue(); + } + function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) { + let done = false; + if (stream._state === 'closed') { + done = true; + } + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + if (pullIntoDescriptor.readerType === 'default') { + ReadableStreamFulfillReadRequest(stream, filledView, done); + } + else { + ReadableStreamFulfillReadIntoRequest(stream, filledView, done); + } + } + function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) { + const bytesFilled = pullIntoDescriptor.bytesFilled; + const elementSize = pullIntoDescriptor.elementSize; + return new pullIntoDescriptor.viewConstructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize); + } + function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) { + controller._queue.push({ buffer, byteOffset, byteLength }); + controller._queueTotalSize += byteLength; + } + function ReadableByteStreamControllerEnqueueClonedChunkToQueue(controller, buffer, byteOffset, byteLength) { + let clonedChunk; + try { + clonedChunk = ArrayBufferSlice(buffer, byteOffset, byteOffset + byteLength); + } + catch (cloneE) { + ReadableByteStreamControllerError(controller, cloneE); + throw cloneE; + } + ReadableByteStreamControllerEnqueueChunkToQueue(controller, clonedChunk, 0, byteLength); + } + function ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue(controller, firstDescriptor) { + if (firstDescriptor.bytesFilled > 0) { + ReadableByteStreamControllerEnqueueClonedChunkToQueue(controller, firstDescriptor.buffer, firstDescriptor.byteOffset, firstDescriptor.bytesFilled); + } + ReadableByteStreamControllerShiftPendingPullInto(controller); + } + function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) { + const maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled); + const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy; + let totalBytesToCopyRemaining = maxBytesToCopy; + let ready = false; + const remainderBytes = maxBytesFilled % pullIntoDescriptor.elementSize; + const maxAlignedBytes = maxBytesFilled - remainderBytes; + // A descriptor for a read() request that is not yet filled up to its minimum length will stay at the head + // of the queue, so the underlying source can keep filling it. + if (maxAlignedBytes >= pullIntoDescriptor.minimumFill) { + totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled; + ready = true; + } + const queue = controller._queue; + while (totalBytesToCopyRemaining > 0) { + const headOfQueue = queue.peek(); + const bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength); + const destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + CopyDataBlockBytes(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy); + if (headOfQueue.byteLength === bytesToCopy) { + queue.shift(); + } + else { + headOfQueue.byteOffset += bytesToCopy; + headOfQueue.byteLength -= bytesToCopy; + } + controller._queueTotalSize -= bytesToCopy; + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor); + totalBytesToCopyRemaining -= bytesToCopy; + } + return ready; + } + function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) { + pullIntoDescriptor.bytesFilled += size; + } + function ReadableByteStreamControllerHandleQueueDrain(controller) { + if (controller._queueTotalSize === 0 && controller._closeRequested) { + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(controller._controlledReadableByteStream); + } + else { + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + } + function ReadableByteStreamControllerInvalidateBYOBRequest(controller) { + if (controller._byobRequest === null) { + return; + } + controller._byobRequest._associatedReadableByteStreamController = undefined; + controller._byobRequest._view = null; + controller._byobRequest = null; + } + function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) { + while (controller._pendingPullIntos.length > 0) { + if (controller._queueTotalSize === 0) { + return; + } + const pullIntoDescriptor = controller._pendingPullIntos.peek(); + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + } + } + } + function ReadableByteStreamControllerProcessReadRequestsUsingQueue(controller) { + const reader = controller._controlledReadableByteStream._reader; + while (reader._readRequests.length > 0) { + if (controller._queueTotalSize === 0) { + return; + } + const readRequest = reader._readRequests.shift(); + ReadableByteStreamControllerFillReadRequestFromQueue(controller, readRequest); + } + } + function ReadableByteStreamControllerPullInto(controller, view, min, readIntoRequest) { + const stream = controller._controlledReadableByteStream; + const ctor = view.constructor; + const elementSize = arrayBufferViewElementSize(ctor); + const { byteOffset, byteLength } = view; + const minimumFill = min * elementSize; + let buffer; + try { + buffer = TransferArrayBuffer(view.buffer); + } + catch (e) { + readIntoRequest._errorSteps(e); + return; + } + const pullIntoDescriptor = { + buffer, + bufferByteLength: buffer.byteLength, + byteOffset, + byteLength, + bytesFilled: 0, + minimumFill, + elementSize, + viewConstructor: ctor, + readerType: 'byob' + }; + if (controller._pendingPullIntos.length > 0) { + controller._pendingPullIntos.push(pullIntoDescriptor); + // No ReadableByteStreamControllerCallPullIfNeeded() call since: + // - No change happens on desiredSize + // - The source has already been notified of that there's at least 1 pending read(view) + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + return; + } + if (stream._state === 'closed') { + const emptyView = new ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0); + readIntoRequest._closeSteps(emptyView); + return; + } + if (controller._queueTotalSize > 0) { + if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor)) { + const filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor); + ReadableByteStreamControllerHandleQueueDrain(controller); + readIntoRequest._chunkSteps(filledView); + return; + } + if (controller._closeRequested) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + readIntoRequest._errorSteps(e); + return; + } + } + controller._pendingPullIntos.push(pullIntoDescriptor); + ReadableStreamAddReadIntoRequest(stream, readIntoRequest); + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) { + if (firstDescriptor.readerType === 'none') { + ReadableByteStreamControllerShiftPendingPullInto(controller); + } + const stream = controller._controlledReadableByteStream; + if (ReadableStreamHasBYOBReader(stream)) { + while (ReadableStreamGetNumReadIntoRequests(stream) > 0) { + const pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller); + ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor); + } + } + } + function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) { + ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor); + if (pullIntoDescriptor.readerType === 'none') { + ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue(controller, pullIntoDescriptor); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + return; + } + if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.minimumFill) { + // A descriptor for a read() request that is not yet filled up to its minimum length will stay at the head + // of the queue, so the underlying source can keep filling it. + return; + } + ReadableByteStreamControllerShiftPendingPullInto(controller); + const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize; + if (remainderSize > 0) { + const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled; + ReadableByteStreamControllerEnqueueClonedChunkToQueue(controller, pullIntoDescriptor.buffer, end - remainderSize, remainderSize); + } + pullIntoDescriptor.bytesFilled -= remainderSize; + ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableByteStream, pullIntoDescriptor); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + } + function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) { + const firstDescriptor = controller._pendingPullIntos.peek(); + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + const state = controller._controlledReadableByteStream._state; + if (state === 'closed') { + ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor); + } + else { + ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerShiftPendingPullInto(controller) { + const descriptor = controller._pendingPullIntos.shift(); + return descriptor; + } + function ReadableByteStreamControllerShouldCallPull(controller) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return false; + } + if (controller._closeRequested) { + return false; + } + if (!controller._started) { + return false; + } + if (ReadableStreamHasDefaultReader(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + if (ReadableStreamHasBYOBReader(stream) && ReadableStreamGetNumReadIntoRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableByteStreamControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; + } + function ReadableByteStreamControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + } + // A client of ReadableByteStreamController may use these functions directly to bypass state check. + function ReadableByteStreamControllerClose(controller) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + if (controller._queueTotalSize > 0) { + controller._closeRequested = true; + return; + } + if (controller._pendingPullIntos.length > 0) { + const firstPendingPullInto = controller._pendingPullIntos.peek(); + if (firstPendingPullInto.bytesFilled % firstPendingPullInto.elementSize !== 0) { + const e = new TypeError('Insufficient bytes to fill elements in the given buffer'); + ReadableByteStreamControllerError(controller, e); + throw e; + } + } + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamClose(stream); + } + function ReadableByteStreamControllerEnqueue(controller, chunk) { + const stream = controller._controlledReadableByteStream; + if (controller._closeRequested || stream._state !== 'readable') { + return; + } + const { buffer, byteOffset, byteLength } = chunk; + if (IsDetachedBuffer(buffer)) { + throw new TypeError('chunk\'s buffer is detached and so cannot be enqueued'); + } + const transferredBuffer = TransferArrayBuffer(buffer); + if (controller._pendingPullIntos.length > 0) { + const firstPendingPullInto = controller._pendingPullIntos.peek(); + if (IsDetachedBuffer(firstPendingPullInto.buffer)) { + throw new TypeError('The BYOB request\'s buffer has been detached and so cannot be filled with an enqueued chunk'); + } + ReadableByteStreamControllerInvalidateBYOBRequest(controller); + firstPendingPullInto.buffer = TransferArrayBuffer(firstPendingPullInto.buffer); + if (firstPendingPullInto.readerType === 'none') { + ReadableByteStreamControllerEnqueueDetachedPullIntoToQueue(controller, firstPendingPullInto); + } + } + if (ReadableStreamHasDefaultReader(stream)) { + ReadableByteStreamControllerProcessReadRequestsUsingQueue(controller); + if (ReadableStreamGetNumReadRequests(stream) === 0) { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + else { + if (controller._pendingPullIntos.length > 0) { + ReadableByteStreamControllerShiftPendingPullInto(controller); + } + const transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength); + ReadableStreamFulfillReadRequest(stream, transferredView, false); + } + } + else if (ReadableStreamHasBYOBReader(stream)) { + // TODO: Ideally in this branch detaching should happen only if the buffer is not consumed fully. + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller); + } + else { + ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength); + } + ReadableByteStreamControllerCallPullIfNeeded(controller); + } + function ReadableByteStreamControllerError(controller, e) { + const stream = controller._controlledReadableByteStream; + if (stream._state !== 'readable') { + return; + } + ReadableByteStreamControllerClearPendingPullIntos(controller); + ResetQueue(controller); + ReadableByteStreamControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); + } + function ReadableByteStreamControllerFillReadRequestFromQueue(controller, readRequest) { + const entry = controller._queue.shift(); + controller._queueTotalSize -= entry.byteLength; + ReadableByteStreamControllerHandleQueueDrain(controller); + const view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength); + readRequest._chunkSteps(view); + } + function ReadableByteStreamControllerGetBYOBRequest(controller) { + if (controller._byobRequest === null && controller._pendingPullIntos.length > 0) { + const firstDescriptor = controller._pendingPullIntos.peek(); + const view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled); + const byobRequest = Object.create(ReadableStreamBYOBRequest.prototype); + SetUpReadableStreamBYOBRequest(byobRequest, controller, view); + controller._byobRequest = byobRequest; + } + return controller._byobRequest; + } + function ReadableByteStreamControllerGetDesiredSize(controller) { + const state = controller._controlledReadableByteStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; + } + function ReadableByteStreamControllerRespond(controller, bytesWritten) { + const firstDescriptor = controller._pendingPullIntos.peek(); + const state = controller._controlledReadableByteStream._state; + if (state === 'closed') { + if (bytesWritten !== 0) { + throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream'); + } + } + else { + if (bytesWritten === 0) { + throw new TypeError('bytesWritten must be greater than 0 when calling respond() on a readable stream'); + } + if (firstDescriptor.bytesFilled + bytesWritten > firstDescriptor.byteLength) { + throw new RangeError('bytesWritten out of range'); + } + } + firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer); + ReadableByteStreamControllerRespondInternal(controller, bytesWritten); + } + function ReadableByteStreamControllerRespondWithNewView(controller, view) { + const firstDescriptor = controller._pendingPullIntos.peek(); + const state = controller._controlledReadableByteStream._state; + if (state === 'closed') { + if (view.byteLength !== 0) { + throw new TypeError('The view\'s length must be 0 when calling respondWithNewView() on a closed stream'); + } + } + else { + if (view.byteLength === 0) { + throw new TypeError('The view\'s length must be greater than 0 when calling respondWithNewView() on a readable stream'); + } + } + if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) { + throw new RangeError('The region specified by view does not match byobRequest'); + } + if (firstDescriptor.bufferByteLength !== view.buffer.byteLength) { + throw new RangeError('The buffer of view has different capacity than byobRequest'); + } + if (firstDescriptor.bytesFilled + view.byteLength > firstDescriptor.byteLength) { + throw new RangeError('The region specified by view is larger than byobRequest'); + } + const viewByteLength = view.byteLength; + firstDescriptor.buffer = TransferArrayBuffer(view.buffer); + ReadableByteStreamControllerRespondInternal(controller, viewByteLength); + } + function SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize) { + controller._controlledReadableByteStream = stream; + controller._pullAgain = false; + controller._pulling = false; + controller._byobRequest = null; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._closeRequested = false; + controller._started = false; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + controller._autoAllocateChunkSize = autoAllocateChunkSize; + controller._pendingPullIntos = new SimpleQueue(); + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableByteStreamControllerCallPullIfNeeded(controller); + return null; + }, r => { + ReadableByteStreamControllerError(controller, r); + return null; + }); + } + function SetUpReadableByteStreamControllerFromUnderlyingSource(stream, underlyingByteSource, highWaterMark) { + const controller = Object.create(ReadableByteStreamController.prototype); + let startAlgorithm; + let pullAlgorithm; + let cancelAlgorithm; + if (underlyingByteSource.start !== undefined) { + startAlgorithm = () => underlyingByteSource.start(controller); + } + else { + startAlgorithm = () => undefined; + } + if (underlyingByteSource.pull !== undefined) { + pullAlgorithm = () => underlyingByteSource.pull(controller); + } + else { + pullAlgorithm = () => promiseResolvedWith(undefined); + } + if (underlyingByteSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingByteSource.cancel(reason); + } + else { + cancelAlgorithm = () => promiseResolvedWith(undefined); + } + const autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize; + if (autoAllocateChunkSize === 0) { + throw new TypeError('autoAllocateChunkSize must be greater than 0'); + } + SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, autoAllocateChunkSize); + } + function SetUpReadableStreamBYOBRequest(request, controller, view) { + request._associatedReadableByteStreamController = controller; + request._view = view; + } + // Helper functions for the ReadableStreamBYOBRequest. + function byobRequestBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBRequest.prototype.${name} can only be used on a ReadableStreamBYOBRequest`); + } + // Helper functions for the ReadableByteStreamController. + function byteStreamControllerBrandCheckException(name) { + return new TypeError(`ReadableByteStreamController.prototype.${name} can only be used on a ReadableByteStreamController`); + } + + function convertReaderOptions(options, context) { + assertDictionary(options, context); + const mode = options === null || options === void 0 ? void 0 : options.mode; + return { + mode: mode === undefined ? undefined : convertReadableStreamReaderMode(mode, `${context} has member 'mode' that`) + }; + } + function convertReadableStreamReaderMode(mode, context) { + mode = `${mode}`; + if (mode !== 'byob') { + throw new TypeError(`${context} '${mode}' is not a valid enumeration value for ReadableStreamReaderMode`); + } + return mode; + } + function convertByobReadOptions(options, context) { + var _a; + assertDictionary(options, context); + const min = (_a = options === null || options === void 0 ? void 0 : options.min) !== null && _a !== void 0 ? _a : 1; + return { + min: convertUnsignedLongLongWithEnforceRange(min, `${context} has member 'min' that`) + }; + } + + // Abstract operations for the ReadableStream. + function AcquireReadableStreamBYOBReader(stream) { + return new ReadableStreamBYOBReader(stream); + } + // ReadableStream API exposed for controllers. + function ReadableStreamAddReadIntoRequest(stream, readIntoRequest) { + stream._reader._readIntoRequests.push(readIntoRequest); + } + function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) { + const reader = stream._reader; + const readIntoRequest = reader._readIntoRequests.shift(); + if (done) { + readIntoRequest._closeSteps(chunk); + } + else { + readIntoRequest._chunkSteps(chunk); + } + } + function ReadableStreamGetNumReadIntoRequests(stream) { + return stream._reader._readIntoRequests.length; + } + function ReadableStreamHasBYOBReader(stream) { + const reader = stream._reader; + if (reader === undefined) { + return false; + } + if (!IsReadableStreamBYOBReader(reader)) { + return false; + } + return true; + } + /** + * A BYOB reader vended by a {@link ReadableStream}. + * + * @public + */ + class ReadableStreamBYOBReader { + constructor(stream) { + assertRequiredArgument(stream, 1, 'ReadableStreamBYOBReader'); + assertReadableStream(stream, 'First parameter'); + if (IsReadableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive reading by another reader'); + } + if (!IsReadableByteStreamController(stream._readableStreamController)) { + throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + + 'source'); + } + ReadableStreamReaderGenericInitialize(this, stream); + this._readIntoRequests = new SimpleQueue(); + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the reader's lock is released before the stream finishes closing. + */ + get closed() { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * If the reader is active, behaves the same as {@link ReadableStream.cancel | stream.cancel(reason)}. + */ + cancel(reason = undefined) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('cancel')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('cancel')); + } + return ReadableStreamReaderGenericCancel(this, reason); + } + read(view, rawOptions = {}) { + if (!IsReadableStreamBYOBReader(this)) { + return promiseRejectedWith(byobReaderBrandCheckException('read')); + } + if (!ArrayBuffer.isView(view)) { + return promiseRejectedWith(new TypeError('view must be an array buffer view')); + } + if (view.byteLength === 0) { + return promiseRejectedWith(new TypeError('view must have non-zero byteLength')); + } + if (view.buffer.byteLength === 0) { + return promiseRejectedWith(new TypeError(`view's buffer must have non-zero byteLength`)); + } + if (IsDetachedBuffer(view.buffer)) { + return promiseRejectedWith(new TypeError('view\'s buffer has been detached')); + } + let options; + try { + options = convertByobReadOptions(rawOptions, 'options'); + } + catch (e) { + return promiseRejectedWith(e); + } + const min = options.min; + if (min === 0) { + return promiseRejectedWith(new TypeError('options.min must be greater than 0')); + } + if (!isDataView(view)) { + if (min > view.length) { + return promiseRejectedWith(new RangeError('options.min must be less than or equal to view\'s length')); + } + } + else if (min > view.byteLength) { + return promiseRejectedWith(new RangeError('options.min must be less than or equal to view\'s byteLength')); + } + if (this._ownerReadableStream === undefined) { + return promiseRejectedWith(readerLockException('read from')); + } + let resolvePromise; + let rejectPromise; + const promise = newPromise((resolve, reject) => { + resolvePromise = resolve; + rejectPromise = reject; + }); + const readIntoRequest = { + _chunkSteps: chunk => resolvePromise({ value: chunk, done: false }), + _closeSteps: chunk => resolvePromise({ value: chunk, done: true }), + _errorSteps: e => rejectPromise(e) + }; + ReadableStreamBYOBReaderRead(this, view, min, readIntoRequest); + return promise; + } + /** + * Releases the reader's lock on the corresponding stream. After the lock is released, the reader is no longer active. + * If the associated stream is errored when the lock is released, the reader will appear errored in the same way + * from now on; otherwise, the reader will appear closed. + * + * A reader's lock cannot be released while it still has a pending read request, i.e., if a promise returned by + * the reader's {@link ReadableStreamBYOBReader.read | read()} method has not yet been settled. Attempting to + * do so will throw a `TypeError` and leave the reader locked to the stream. + */ + releaseLock() { + if (!IsReadableStreamBYOBReader(this)) { + throw byobReaderBrandCheckException('releaseLock'); + } + if (this._ownerReadableStream === undefined) { + return; + } + ReadableStreamBYOBReaderRelease(this); + } + } + Object.defineProperties(ReadableStreamBYOBReader.prototype, { + cancel: { enumerable: true }, + read: { enumerable: true }, + releaseLock: { enumerable: true }, + closed: { enumerable: true } + }); + setFunctionName(ReadableStreamBYOBReader.prototype.cancel, 'cancel'); + setFunctionName(ReadableStreamBYOBReader.prototype.read, 'read'); + setFunctionName(ReadableStreamBYOBReader.prototype.releaseLock, 'releaseLock'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamBYOBReader.prototype, Symbol.toStringTag, { + value: 'ReadableStreamBYOBReader', + configurable: true + }); + } + // Abstract operations for the readers. + function IsReadableStreamBYOBReader(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) { + return false; + } + return x instanceof ReadableStreamBYOBReader; + } + function ReadableStreamBYOBReaderRead(reader, view, min, readIntoRequest) { + const stream = reader._ownerReadableStream; + stream._disturbed = true; + if (stream._state === 'errored') { + readIntoRequest._errorSteps(stream._storedError); + } + else { + ReadableByteStreamControllerPullInto(stream._readableStreamController, view, min, readIntoRequest); + } + } + function ReadableStreamBYOBReaderRelease(reader) { + ReadableStreamReaderGenericRelease(reader); + const e = new TypeError('Reader was released'); + ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e); + } + function ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e) { + const readIntoRequests = reader._readIntoRequests; + reader._readIntoRequests = new SimpleQueue(); + readIntoRequests.forEach(readIntoRequest => { + readIntoRequest._errorSteps(e); + }); + } + // Helper functions for the ReadableStreamBYOBReader. + function byobReaderBrandCheckException(name) { + return new TypeError(`ReadableStreamBYOBReader.prototype.${name} can only be used on a ReadableStreamBYOBReader`); + } + + function ExtractHighWaterMark(strategy, defaultHWM) { + const { highWaterMark } = strategy; + if (highWaterMark === undefined) { + return defaultHWM; + } + if (NumberIsNaN(highWaterMark) || highWaterMark < 0) { + throw new RangeError('Invalid highWaterMark'); + } + return highWaterMark; + } + function ExtractSizeAlgorithm(strategy) { + const { size } = strategy; + if (!size) { + return () => 1; + } + return size; + } + + function convertQueuingStrategy(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + const size = init === null || init === void 0 ? void 0 : init.size; + return { + highWaterMark: highWaterMark === undefined ? undefined : convertUnrestrictedDouble(highWaterMark), + size: size === undefined ? undefined : convertQueuingStrategySize(size, `${context} has member 'size' that`) + }; + } + function convertQueuingStrategySize(fn, context) { + assertFunction(fn, context); + return chunk => convertUnrestrictedDouble(fn(chunk)); + } + + function convertUnderlyingSink(original, context) { + assertDictionary(original, context); + const abort = original === null || original === void 0 ? void 0 : original.abort; + const close = original === null || original === void 0 ? void 0 : original.close; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + const write = original === null || original === void 0 ? void 0 : original.write; + return { + abort: abort === undefined ? + undefined : + convertUnderlyingSinkAbortCallback(abort, original, `${context} has member 'abort' that`), + close: close === undefined ? + undefined : + convertUnderlyingSinkCloseCallback(close, original, `${context} has member 'close' that`), + start: start === undefined ? + undefined : + convertUnderlyingSinkStartCallback(start, original, `${context} has member 'start' that`), + write: write === undefined ? + undefined : + convertUnderlyingSinkWriteCallback(write, original, `${context} has member 'write' that`), + type + }; + } + function convertUnderlyingSinkAbortCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); + } + function convertUnderlyingSinkCloseCallback(fn, original, context) { + assertFunction(fn, context); + return () => promiseCall(fn, original, []); + } + function convertUnderlyingSinkStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertUnderlyingSinkWriteCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); + } + + function assertWritableStream(x, context) { + if (!IsWritableStream(x)) { + throw new TypeError(`${context} is not a WritableStream.`); + } + } + + function isAbortSignal(value) { + if (typeof value !== 'object' || value === null) { + return false; + } + try { + return typeof value.aborted === 'boolean'; + } + catch (_a) { + // AbortSignal.prototype.aborted throws if its brand check fails + return false; + } + } + const supportsAbortController = typeof AbortController === 'function'; + /** + * Construct a new AbortController, if supported by the platform. + * + * @internal + */ + function createAbortController() { + if (supportsAbortController) { + return new AbortController(); + } + return undefined; + } + + /** + * A writable stream represents a destination for data, into which you can write. + * + * @public + */ + class WritableStream { + constructor(rawUnderlyingSink = {}, rawStrategy = {}) { + if (rawUnderlyingSink === undefined) { + rawUnderlyingSink = null; + } + else { + assertObject(rawUnderlyingSink, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSink = convertUnderlyingSink(rawUnderlyingSink, 'First parameter'); + InitializeWritableStream(this); + const type = underlyingSink.type; + if (type !== undefined) { + throw new RangeError('Invalid type is specified'); + } + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpWritableStreamDefaultControllerFromUnderlyingSink(this, underlyingSink, highWaterMark, sizeAlgorithm); + } + /** + * Returns whether or not the writable stream is locked to a writer. + */ + get locked() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('locked'); + } + return IsWritableStreamLocked(this); + } + /** + * Aborts the stream, signaling that the producer can no longer successfully write to the stream and it is to be + * immediately moved to an errored state, with any queued-up writes discarded. This will also execute any abort + * mechanism of the underlying sink. + * + * The returned promise will fulfill if the stream shuts down successfully, or reject if the underlying sink signaled + * that there was an error doing so. Additionally, it will reject with a `TypeError` (without attempting to cancel + * the stream) if the stream is currently locked. + */ + abort(reason = undefined) { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('abort')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot abort a stream that already has a writer')); + } + return WritableStreamAbort(this, reason); + } + /** + * Closes the stream. The underlying sink will finish processing any previously-written chunks, before invoking its + * close behavior. During this time any further attempts to write will fail (without erroring the stream). + * + * The method returns a promise that will fulfill if all remaining chunks are successfully written and the stream + * successfully closes, or rejects if an error is encountered during this process. Additionally, it will reject with + * a `TypeError` (without attempting to cancel the stream) if the stream is currently locked. + */ + close() { + if (!IsWritableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$2('close')); + } + if (IsWritableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot close a stream that already has a writer')); + } + if (WritableStreamCloseQueuedOrInFlight(this)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamClose(this); + } + /** + * Creates a {@link WritableStreamDefaultWriter | writer} and locks the stream to the new writer. While the stream + * is locked, no other writer can be acquired until this one is released. + * + * This functionality is especially useful for creating abstractions that desire the ability to write to a stream + * without interruption or interleaving. By getting a writer for the stream, you can ensure nobody else can write at + * the same time, which would cause the resulting written data to be unpredictable and probably useless. + */ + getWriter() { + if (!IsWritableStream(this)) { + throw streamBrandCheckException$2('getWriter'); + } + return AcquireWritableStreamDefaultWriter(this); + } + } + Object.defineProperties(WritableStream.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + getWriter: { enumerable: true }, + locked: { enumerable: true } + }); + setFunctionName(WritableStream.prototype.abort, 'abort'); + setFunctionName(WritableStream.prototype.close, 'close'); + setFunctionName(WritableStream.prototype.getWriter, 'getWriter'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(WritableStream.prototype, Symbol.toStringTag, { + value: 'WritableStream', + configurable: true + }); + } + // Abstract operations for the WritableStream. + function AcquireWritableStreamDefaultWriter(stream) { + return new WritableStreamDefaultWriter(stream); + } + // Throws if and only if startAlgorithm throws. + function CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(WritableStream.prototype); + InitializeWritableStream(stream); + const controller = Object.create(WritableStreamDefaultController.prototype); + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); + return stream; + } + function InitializeWritableStream(stream) { + stream._state = 'writable'; + // The error that will be reported by new method calls once the state becomes errored. Only set when [[state]] is + // 'erroring' or 'errored'. May be set to an undefined value. + stream._storedError = undefined; + stream._writer = undefined; + // Initialize to undefined first because the constructor of the controller checks this + // variable to validate the caller. + stream._writableStreamController = undefined; + // This queue is placed here instead of the writer class in order to allow for passing a writer to the next data + // producer without waiting for the queued writes to finish. + stream._writeRequests = new SimpleQueue(); + // Write requests are removed from _writeRequests when write() is called on the underlying sink. This prevents + // them from being erroneously rejected on error. If a write() call is in-flight, the request is stored here. + stream._inFlightWriteRequest = undefined; + // The promise that was returned from writer.close(). Stored here because it may be fulfilled after the writer + // has been detached. + stream._closeRequest = undefined; + // Close request is removed from _closeRequest when close() is called on the underlying sink. This prevents it + // from being erroneously rejected on error. If a close() call is in-flight, the request is stored here. + stream._inFlightCloseRequest = undefined; + // The promise that was returned from writer.abort(). This may also be fulfilled after the writer has detached. + stream._pendingAbortRequest = undefined; + // The backpressure signal set by the controller. + stream._backpressure = false; + } + function IsWritableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) { + return false; + } + return x instanceof WritableStream; + } + function IsWritableStreamLocked(stream) { + if (stream._writer === undefined) { + return false; + } + return true; + } + function WritableStreamAbort(stream, reason) { + var _a; + if (stream._state === 'closed' || stream._state === 'errored') { + return promiseResolvedWith(undefined); + } + stream._writableStreamController._abortReason = reason; + (_a = stream._writableStreamController._abortController) === null || _a === void 0 ? void 0 : _a.abort(reason); + // TypeScript narrows the type of `stream._state` down to 'writable' | 'erroring', + // but it doesn't know that signaling abort runs author code that might have changed the state. + // Widen the type again by casting to WritableStreamState. + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseResolvedWith(undefined); + } + if (stream._pendingAbortRequest !== undefined) { + return stream._pendingAbortRequest._promise; + } + let wasAlreadyErroring = false; + if (state === 'erroring') { + wasAlreadyErroring = true; + // reason will not be used, so don't keep a reference to it. + reason = undefined; + } + const promise = newPromise((resolve, reject) => { + stream._pendingAbortRequest = { + _promise: undefined, + _resolve: resolve, + _reject: reject, + _reason: reason, + _wasAlreadyErroring: wasAlreadyErroring + }; + }); + stream._pendingAbortRequest._promise = promise; + if (!wasAlreadyErroring) { + WritableStreamStartErroring(stream, reason); + } + return promise; + } + function WritableStreamClose(stream) { + const state = stream._state; + if (state === 'closed' || state === 'errored') { + return promiseRejectedWith(new TypeError(`The stream (in ${state} state) is not in the writable state and cannot be closed`)); + } + const promise = newPromise((resolve, reject) => { + const closeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._closeRequest = closeRequest; + }); + const writer = stream._writer; + if (writer !== undefined && stream._backpressure && state === 'writable') { + defaultWriterReadyPromiseResolve(writer); + } + WritableStreamDefaultControllerClose(stream._writableStreamController); + return promise; + } + // WritableStream API exposed for controllers. + function WritableStreamAddWriteRequest(stream) { + const promise = newPromise((resolve, reject) => { + const writeRequest = { + _resolve: resolve, + _reject: reject + }; + stream._writeRequests.push(writeRequest); + }); + return promise; + } + function WritableStreamDealWithRejection(stream, error) { + const state = stream._state; + if (state === 'writable') { + WritableStreamStartErroring(stream, error); + return; + } + WritableStreamFinishErroring(stream); + } + function WritableStreamStartErroring(stream, reason) { + const controller = stream._writableStreamController; + stream._state = 'erroring'; + stream._storedError = reason; + const writer = stream._writer; + if (writer !== undefined) { + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason); + } + if (!WritableStreamHasOperationMarkedInFlight(stream) && controller._started) { + WritableStreamFinishErroring(stream); + } + } + function WritableStreamFinishErroring(stream) { + stream._state = 'errored'; + stream._writableStreamController[ErrorSteps](); + const storedError = stream._storedError; + stream._writeRequests.forEach(writeRequest => { + writeRequest._reject(storedError); + }); + stream._writeRequests = new SimpleQueue(); + if (stream._pendingAbortRequest === undefined) { + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const abortRequest = stream._pendingAbortRequest; + stream._pendingAbortRequest = undefined; + if (abortRequest._wasAlreadyErroring) { + abortRequest._reject(storedError); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return; + } + const promise = stream._writableStreamController[AbortSteps](abortRequest._reason); + uponPromise(promise, () => { + abortRequest._resolve(); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return null; + }, (reason) => { + abortRequest._reject(reason); + WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream); + return null; + }); + } + function WritableStreamFinishInFlightWrite(stream) { + stream._inFlightWriteRequest._resolve(undefined); + stream._inFlightWriteRequest = undefined; + } + function WritableStreamFinishInFlightWriteWithError(stream, error) { + stream._inFlightWriteRequest._reject(error); + stream._inFlightWriteRequest = undefined; + WritableStreamDealWithRejection(stream, error); + } + function WritableStreamFinishInFlightClose(stream) { + stream._inFlightCloseRequest._resolve(undefined); + stream._inFlightCloseRequest = undefined; + const state = stream._state; + if (state === 'erroring') { + // The error was too late to do anything, so it is ignored. + stream._storedError = undefined; + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._resolve(); + stream._pendingAbortRequest = undefined; + } + } + stream._state = 'closed'; + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseResolve(writer); + } + } + function WritableStreamFinishInFlightCloseWithError(stream, error) { + stream._inFlightCloseRequest._reject(error); + stream._inFlightCloseRequest = undefined; + // Never execute sink abort() after sink close(). + if (stream._pendingAbortRequest !== undefined) { + stream._pendingAbortRequest._reject(error); + stream._pendingAbortRequest = undefined; + } + WritableStreamDealWithRejection(stream, error); + } + // TODO(ricea): Fix alphabetical order. + function WritableStreamCloseQueuedOrInFlight(stream) { + if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; + } + function WritableStreamHasOperationMarkedInFlight(stream) { + if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) { + return false; + } + return true; + } + function WritableStreamMarkCloseRequestInFlight(stream) { + stream._inFlightCloseRequest = stream._closeRequest; + stream._closeRequest = undefined; + } + function WritableStreamMarkFirstWriteRequestInFlight(stream) { + stream._inFlightWriteRequest = stream._writeRequests.shift(); + } + function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) { + if (stream._closeRequest !== undefined) { + stream._closeRequest._reject(stream._storedError); + stream._closeRequest = undefined; + } + const writer = stream._writer; + if (writer !== undefined) { + defaultWriterClosedPromiseReject(writer, stream._storedError); + } + } + function WritableStreamUpdateBackpressure(stream, backpressure) { + const writer = stream._writer; + if (writer !== undefined && backpressure !== stream._backpressure) { + if (backpressure) { + defaultWriterReadyPromiseReset(writer); + } + else { + defaultWriterReadyPromiseResolve(writer); + } + } + stream._backpressure = backpressure; + } + /** + * A default writer vended by a {@link WritableStream}. + * + * @public + */ + class WritableStreamDefaultWriter { + constructor(stream) { + assertRequiredArgument(stream, 1, 'WritableStreamDefaultWriter'); + assertWritableStream(stream, 'First parameter'); + if (IsWritableStreamLocked(stream)) { + throw new TypeError('This stream has already been locked for exclusive writing by another writer'); + } + this._ownerWritableStream = stream; + stream._writer = this; + const state = stream._state; + if (state === 'writable') { + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._backpressure) { + defaultWriterReadyPromiseInitialize(this); + } + else { + defaultWriterReadyPromiseInitializeAsResolved(this); + } + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'erroring') { + defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError); + defaultWriterClosedPromiseInitialize(this); + } + else if (state === 'closed') { + defaultWriterReadyPromiseInitializeAsResolved(this); + defaultWriterClosedPromiseInitializeAsResolved(this); + } + else { + const storedError = stream._storedError; + defaultWriterReadyPromiseInitializeAsRejected(this, storedError); + defaultWriterClosedPromiseInitializeAsRejected(this, storedError); + } + } + /** + * Returns a promise that will be fulfilled when the stream becomes closed, or rejected if the stream ever errors or + * the writerā€™s lock is released before the stream finishes closing. + */ + get closed() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('closed')); + } + return this._closedPromise; + } + /** + * Returns the desired size to fill the streamā€™s internal queue. It can be negative, if the queue is over-full. + * A producer can use this information to determine the right amount of data to write. + * + * It will be `null` if the stream cannot be successfully written to (due to either being errored, or having an abort + * queued up). It will return zero if the stream is closed. And the getter will throw an exception if invoked when + * the writerā€™s lock is released. + */ + get desiredSize() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('desiredSize'); + } + if (this._ownerWritableStream === undefined) { + throw defaultWriterLockException('desiredSize'); + } + return WritableStreamDefaultWriterGetDesiredSize(this); + } + /** + * Returns a promise that will be fulfilled when the desired size to fill the streamā€™s internal queue transitions + * from non-positive to positive, signaling that it is no longer applying backpressure. Once the desired size dips + * back to zero or below, the getter will return a new promise that stays pending until the next transition. + * + * If the stream becomes errored or aborted, or the writerā€™s lock is released, the returned promise will become + * rejected. + */ + get ready() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('ready')); + } + return this._readyPromise; + } + /** + * If the reader is active, behaves the same as {@link WritableStream.abort | stream.abort(reason)}. + */ + abort(reason = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('abort')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('abort')); + } + return WritableStreamDefaultWriterAbort(this, reason); + } + /** + * If the reader is active, behaves the same as {@link WritableStream.close | stream.close()}. + */ + close() { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('close')); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return promiseRejectedWith(defaultWriterLockException('close')); + } + if (WritableStreamCloseQueuedOrInFlight(stream)) { + return promiseRejectedWith(new TypeError('Cannot close an already-closing stream')); + } + return WritableStreamDefaultWriterClose(this); + } + /** + * Releases the writerā€™s lock on the corresponding stream. After the lock is released, the writer is no longer active. + * If the associated stream is errored when the lock is released, the writer will appear errored in the same way from + * now on; otherwise, the writer will appear closed. + * + * Note that the lock can still be released even if some ongoing writes have not yet finished (i.e. even if the + * promises returned from previous calls to {@link WritableStreamDefaultWriter.write | write()} have not yet settled). + * Itā€™s not necessary to hold the lock on the writer for the duration of the write; the lock instead simply prevents + * other producers from writing in an interleaved manner. + */ + releaseLock() { + if (!IsWritableStreamDefaultWriter(this)) { + throw defaultWriterBrandCheckException('releaseLock'); + } + const stream = this._ownerWritableStream; + if (stream === undefined) { + return; + } + WritableStreamDefaultWriterRelease(this); + } + write(chunk = undefined) { + if (!IsWritableStreamDefaultWriter(this)) { + return promiseRejectedWith(defaultWriterBrandCheckException('write')); + } + if (this._ownerWritableStream === undefined) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + return WritableStreamDefaultWriterWrite(this, chunk); + } + } + Object.defineProperties(WritableStreamDefaultWriter.prototype, { + abort: { enumerable: true }, + close: { enumerable: true }, + releaseLock: { enumerable: true }, + write: { enumerable: true }, + closed: { enumerable: true }, + desiredSize: { enumerable: true }, + ready: { enumerable: true } + }); + setFunctionName(WritableStreamDefaultWriter.prototype.abort, 'abort'); + setFunctionName(WritableStreamDefaultWriter.prototype.close, 'close'); + setFunctionName(WritableStreamDefaultWriter.prototype.releaseLock, 'releaseLock'); + setFunctionName(WritableStreamDefaultWriter.prototype.write, 'write'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultWriter.prototype, Symbol.toStringTag, { + value: 'WritableStreamDefaultWriter', + configurable: true + }); + } + // Abstract operations for the WritableStreamDefaultWriter. + function IsWritableStreamDefaultWriter(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) { + return false; + } + return x instanceof WritableStreamDefaultWriter; + } + // A client of WritableStreamDefaultWriter may use these functions directly to bypass state check. + function WritableStreamDefaultWriterAbort(writer, reason) { + const stream = writer._ownerWritableStream; + return WritableStreamAbort(stream, reason); + } + function WritableStreamDefaultWriterClose(writer) { + const stream = writer._ownerWritableStream; + return WritableStreamClose(stream); + } + function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseResolvedWith(undefined); + } + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + return WritableStreamDefaultWriterClose(writer); + } + function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) { + if (writer._closedPromiseState === 'pending') { + defaultWriterClosedPromiseReject(writer, error); + } + else { + defaultWriterClosedPromiseResetToRejected(writer, error); + } + } + function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) { + if (writer._readyPromiseState === 'pending') { + defaultWriterReadyPromiseReject(writer, error); + } + else { + defaultWriterReadyPromiseResetToRejected(writer, error); + } + } + function WritableStreamDefaultWriterGetDesiredSize(writer) { + const stream = writer._ownerWritableStream; + const state = stream._state; + if (state === 'errored' || state === 'erroring') { + return null; + } + if (state === 'closed') { + return 0; + } + return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController); + } + function WritableStreamDefaultWriterRelease(writer) { + const stream = writer._ownerWritableStream; + const releasedError = new TypeError(`Writer was released and can no longer be used to monitor the stream's closedness`); + WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError); + // The state transitions to "errored" before the sink abort() method runs, but the writer.closed promise is not + // rejected until afterwards. This means that simply testing state will not work. + WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError); + stream._writer = undefined; + writer._ownerWritableStream = undefined; + } + function WritableStreamDefaultWriterWrite(writer, chunk) { + const stream = writer._ownerWritableStream; + const controller = stream._writableStreamController; + const chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk); + if (stream !== writer._ownerWritableStream) { + return promiseRejectedWith(defaultWriterLockException('write to')); + } + const state = stream._state; + if (state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + if (WritableStreamCloseQueuedOrInFlight(stream) || state === 'closed') { + return promiseRejectedWith(new TypeError('The stream is closing or closed and cannot be written to')); + } + if (state === 'erroring') { + return promiseRejectedWith(stream._storedError); + } + const promise = WritableStreamAddWriteRequest(stream); + WritableStreamDefaultControllerWrite(controller, chunk, chunkSize); + return promise; + } + const closeSentinel = {}; + /** + * Allows control of a {@link WritableStream | writable stream}'s state and internal queue. + * + * @public + */ + class WritableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * The reason which was passed to `WritableStream.abort(reason)` when the stream was aborted. + * + * @deprecated + * This property has been removed from the specification, see https://github.com/whatwg/streams/pull/1177. + * Use {@link WritableStreamDefaultController.signal}'s `reason` instead. + */ + get abortReason() { + if (!IsWritableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$2('abortReason'); + } + return this._abortReason; + } + /** + * An `AbortSignal` that can be used to abort the pending write or close operation when the stream is aborted. + */ + get signal() { + if (!IsWritableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$2('signal'); + } + if (this._abortController === undefined) { + // Older browsers or older Node versions may not support `AbortController` or `AbortSignal`. + // We don't want to bundle and ship an `AbortController` polyfill together with our polyfill, + // so instead we only implement support for `signal` if we find a global `AbortController` constructor. + throw new TypeError('WritableStreamDefaultController.prototype.signal is not supported'); + } + return this._abortController.signal; + } + /** + * Closes the controlled writable stream, making all future interactions with it fail with the given error `e`. + * + * This method is rarely used, since usually it suffices to return a rejected promise from one of the underlying + * sink's methods. However, it can be useful for suddenly shutting down a stream in response to an event outside the + * normal lifecycle of interactions with the underlying sink. + */ + error(e = undefined) { + if (!IsWritableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$2('error'); + } + const state = this._controlledWritableStream._state; + if (state !== 'writable') { + // The stream is closed, errored or will be soon. The sink can't do anything useful if it gets an error here, so + // just treat it as a no-op. + return; + } + WritableStreamDefaultControllerError(this, e); + } + /** @internal */ + [AbortSteps](reason) { + const result = this._abortAlgorithm(reason); + WritableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [ErrorSteps]() { + ResetQueue(this); + } + } + Object.defineProperties(WritableStreamDefaultController.prototype, { + abortReason: { enumerable: true }, + signal: { enumerable: true }, + error: { enumerable: true } + }); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(WritableStreamDefaultController.prototype, Symbol.toStringTag, { + value: 'WritableStreamDefaultController', + configurable: true + }); + } + // Abstract operations implementing interface required by the WritableStream. + function IsWritableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledWritableStream')) { + return false; + } + return x instanceof WritableStreamDefaultController; + } + function SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledWritableStream = stream; + stream._writableStreamController = controller; + // Need to set the slots so that the assert doesn't fire. In the spec the slots already exist implicitly. + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._abortReason = undefined; + controller._abortController = createAbortController(); + controller._started = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._writeAlgorithm = writeAlgorithm; + controller._closeAlgorithm = closeAlgorithm; + controller._abortAlgorithm = abortAlgorithm; + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + const startResult = startAlgorithm(); + const startPromise = promiseResolvedWith(startResult); + uponPromise(startPromise, () => { + controller._started = true; + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + return null; + }, r => { + controller._started = true; + WritableStreamDealWithRejection(stream, r); + return null; + }); + } + function SetUpWritableStreamDefaultControllerFromUnderlyingSink(stream, underlyingSink, highWaterMark, sizeAlgorithm) { + const controller = Object.create(WritableStreamDefaultController.prototype); + let startAlgorithm; + let writeAlgorithm; + let closeAlgorithm; + let abortAlgorithm; + if (underlyingSink.start !== undefined) { + startAlgorithm = () => underlyingSink.start(controller); + } + else { + startAlgorithm = () => undefined; + } + if (underlyingSink.write !== undefined) { + writeAlgorithm = chunk => underlyingSink.write(chunk, controller); + } + else { + writeAlgorithm = () => promiseResolvedWith(undefined); + } + if (underlyingSink.close !== undefined) { + closeAlgorithm = () => underlyingSink.close(); + } + else { + closeAlgorithm = () => promiseResolvedWith(undefined); + } + if (underlyingSink.abort !== undefined) { + abortAlgorithm = reason => underlyingSink.abort(reason); + } + else { + abortAlgorithm = () => promiseResolvedWith(undefined); + } + SetUpWritableStreamDefaultController(stream, controller, startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, highWaterMark, sizeAlgorithm); + } + // ClearAlgorithms may be called twice. Erroring the same stream in multiple ways will often result in redundant calls. + function WritableStreamDefaultControllerClearAlgorithms(controller) { + controller._writeAlgorithm = undefined; + controller._closeAlgorithm = undefined; + controller._abortAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; + } + function WritableStreamDefaultControllerClose(controller) { + EnqueueValueWithSize(controller, closeSentinel, 0); + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + } + function WritableStreamDefaultControllerGetChunkSize(controller, chunk) { + try { + return controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE); + return 1; + } + } + function WritableStreamDefaultControllerGetDesiredSize(controller) { + return controller._strategyHWM - controller._queueTotalSize; + } + function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) { + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE); + return; + } + const stream = controller._controlledWritableStream; + if (!WritableStreamCloseQueuedOrInFlight(stream) && stream._state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + } + // Abstract operations for the WritableStreamDefaultController. + function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) { + const stream = controller._controlledWritableStream; + if (!controller._started) { + return; + } + if (stream._inFlightWriteRequest !== undefined) { + return; + } + const state = stream._state; + if (state === 'erroring') { + WritableStreamFinishErroring(stream); + return; + } + if (controller._queue.length === 0) { + return; + } + const value = PeekQueueValue(controller); + if (value === closeSentinel) { + WritableStreamDefaultControllerProcessClose(controller); + } + else { + WritableStreamDefaultControllerProcessWrite(controller, value); + } + } + function WritableStreamDefaultControllerErrorIfNeeded(controller, error) { + if (controller._controlledWritableStream._state === 'writable') { + WritableStreamDefaultControllerError(controller, error); + } + } + function WritableStreamDefaultControllerProcessClose(controller) { + const stream = controller._controlledWritableStream; + WritableStreamMarkCloseRequestInFlight(stream); + DequeueValue(controller); + const sinkClosePromise = controller._closeAlgorithm(); + WritableStreamDefaultControllerClearAlgorithms(controller); + uponPromise(sinkClosePromise, () => { + WritableStreamFinishInFlightClose(stream); + return null; + }, reason => { + WritableStreamFinishInFlightCloseWithError(stream, reason); + return null; + }); + } + function WritableStreamDefaultControllerProcessWrite(controller, chunk) { + const stream = controller._controlledWritableStream; + WritableStreamMarkFirstWriteRequestInFlight(stream); + const sinkWritePromise = controller._writeAlgorithm(chunk); + uponPromise(sinkWritePromise, () => { + WritableStreamFinishInFlightWrite(stream); + const state = stream._state; + DequeueValue(controller); + if (!WritableStreamCloseQueuedOrInFlight(stream) && state === 'writable') { + const backpressure = WritableStreamDefaultControllerGetBackpressure(controller); + WritableStreamUpdateBackpressure(stream, backpressure); + } + WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller); + return null; + }, reason => { + if (stream._state === 'writable') { + WritableStreamDefaultControllerClearAlgorithms(controller); + } + WritableStreamFinishInFlightWriteWithError(stream, reason); + return null; + }); + } + function WritableStreamDefaultControllerGetBackpressure(controller) { + const desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller); + return desiredSize <= 0; + } + // A client of WritableStreamDefaultController may use these functions directly to bypass state check. + function WritableStreamDefaultControllerError(controller, error) { + const stream = controller._controlledWritableStream; + WritableStreamDefaultControllerClearAlgorithms(controller); + WritableStreamStartErroring(stream, error); + } + // Helper functions for the WritableStream. + function streamBrandCheckException$2(name) { + return new TypeError(`WritableStream.prototype.${name} can only be used on a WritableStream`); + } + // Helper functions for the WritableStreamDefaultController. + function defaultControllerBrandCheckException$2(name) { + return new TypeError(`WritableStreamDefaultController.prototype.${name} can only be used on a WritableStreamDefaultController`); + } + // Helper functions for the WritableStreamDefaultWriter. + function defaultWriterBrandCheckException(name) { + return new TypeError(`WritableStreamDefaultWriter.prototype.${name} can only be used on a WritableStreamDefaultWriter`); + } + function defaultWriterLockException(name) { + return new TypeError('Cannot ' + name + ' a stream using a released writer'); + } + function defaultWriterClosedPromiseInitialize(writer) { + writer._closedPromise = newPromise((resolve, reject) => { + writer._closedPromise_resolve = resolve; + writer._closedPromise_reject = reject; + writer._closedPromiseState = 'pending'; + }); + } + function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseReject(writer, reason); + } + function defaultWriterClosedPromiseInitializeAsResolved(writer) { + defaultWriterClosedPromiseInitialize(writer); + defaultWriterClosedPromiseResolve(writer); + } + function defaultWriterClosedPromiseReject(writer, reason) { + if (writer._closedPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._closedPromise); + writer._closedPromise_reject(reason); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'rejected'; + } + function defaultWriterClosedPromiseResetToRejected(writer, reason) { + defaultWriterClosedPromiseInitializeAsRejected(writer, reason); + } + function defaultWriterClosedPromiseResolve(writer) { + if (writer._closedPromise_resolve === undefined) { + return; + } + writer._closedPromise_resolve(undefined); + writer._closedPromise_resolve = undefined; + writer._closedPromise_reject = undefined; + writer._closedPromiseState = 'resolved'; + } + function defaultWriterReadyPromiseInitialize(writer) { + writer._readyPromise = newPromise((resolve, reject) => { + writer._readyPromise_resolve = resolve; + writer._readyPromise_reject = reject; + }); + writer._readyPromiseState = 'pending'; + } + function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseReject(writer, reason); + } + function defaultWriterReadyPromiseInitializeAsResolved(writer) { + defaultWriterReadyPromiseInitialize(writer); + defaultWriterReadyPromiseResolve(writer); + } + function defaultWriterReadyPromiseReject(writer, reason) { + if (writer._readyPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(writer._readyPromise); + writer._readyPromise_reject(reason); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'rejected'; + } + function defaultWriterReadyPromiseReset(writer) { + defaultWriterReadyPromiseInitialize(writer); + } + function defaultWriterReadyPromiseResetToRejected(writer, reason) { + defaultWriterReadyPromiseInitializeAsRejected(writer, reason); + } + function defaultWriterReadyPromiseResolve(writer) { + if (writer._readyPromise_resolve === undefined) { + return; + } + writer._readyPromise_resolve(undefined); + writer._readyPromise_resolve = undefined; + writer._readyPromise_reject = undefined; + writer._readyPromiseState = 'fulfilled'; + } + + /// + function getGlobals() { + if (typeof globalThis !== 'undefined') { + return globalThis; + } + else if (typeof self !== 'undefined') { + return self; + } + else if (typeof global !== 'undefined') { + return global; + } + return undefined; + } + const globals = getGlobals(); + + /// + function isDOMExceptionConstructor(ctor) { + if (!(typeof ctor === 'function' || typeof ctor === 'object')) { + return false; + } + if (ctor.name !== 'DOMException') { + return false; + } + try { + new ctor(); + return true; + } + catch (_a) { + return false; + } + } + /** + * Support: + * - Web browsers + * - Node 18 and higher (https://github.com/nodejs/node/commit/e4b1fb5e6422c1ff151234bb9de792d45dd88d87) + */ + function getFromGlobal() { + const ctor = globals === null || globals === void 0 ? void 0 : globals.DOMException; + return isDOMExceptionConstructor(ctor) ? ctor : undefined; + } + /** + * Support: + * - All platforms + */ + function createPolyfill() { + // eslint-disable-next-line @typescript-eslint/no-shadow + const ctor = function DOMException(message, name) { + this.message = message || ''; + this.name = name || 'Error'; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + }; + setFunctionName(ctor, 'DOMException'); + ctor.prototype = Object.create(Error.prototype); + Object.defineProperty(ctor.prototype, 'constructor', { value: ctor, writable: true, configurable: true }); + return ctor; + } + // eslint-disable-next-line @typescript-eslint/no-redeclare + const DOMException = getFromGlobal() || createPolyfill(); + + function ReadableStreamPipeTo(source, dest, preventClose, preventAbort, preventCancel, signal) { + const reader = AcquireReadableStreamDefaultReader(source); + const writer = AcquireWritableStreamDefaultWriter(dest); + source._disturbed = true; + let shuttingDown = false; + // This is used to keep track of the spec's requirement that we wait for ongoing writes during shutdown. + let currentWrite = promiseResolvedWith(undefined); + return newPromise((resolve, reject) => { + let abortAlgorithm; + if (signal !== undefined) { + abortAlgorithm = () => { + const error = signal.reason !== undefined ? signal.reason : new DOMException('Aborted', 'AbortError'); + const actions = []; + if (!preventAbort) { + actions.push(() => { + if (dest._state === 'writable') { + return WritableStreamAbort(dest, error); + } + return promiseResolvedWith(undefined); + }); + } + if (!preventCancel) { + actions.push(() => { + if (source._state === 'readable') { + return ReadableStreamCancel(source, error); + } + return promiseResolvedWith(undefined); + }); + } + shutdownWithAction(() => Promise.all(actions.map(action => action())), true, error); + }; + if (signal.aborted) { + abortAlgorithm(); + return; + } + signal.addEventListener('abort', abortAlgorithm); + } + // Using reader and writer, read all chunks from this and write them to dest + // - Backpressure must be enforced + // - Shutdown must stop all activity + function pipeLoop() { + return newPromise((resolveLoop, rejectLoop) => { + function next(done) { + if (done) { + resolveLoop(); + } + else { + // Use `PerformPromiseThen` instead of `uponPromise` to avoid + // adding unnecessary `.catch(rethrowAssertionErrorRejection)` handlers + PerformPromiseThen(pipeStep(), next, rejectLoop); + } + } + next(false); + }); + } + function pipeStep() { + if (shuttingDown) { + return promiseResolvedWith(true); + } + return PerformPromiseThen(writer._readyPromise, () => { + return newPromise((resolveRead, rejectRead) => { + ReadableStreamDefaultReaderRead(reader, { + _chunkSteps: chunk => { + currentWrite = PerformPromiseThen(WritableStreamDefaultWriterWrite(writer, chunk), undefined, noop); + resolveRead(false); + }, + _closeSteps: () => resolveRead(true), + _errorSteps: rejectRead + }); + }); + }); + } + // Errors must be propagated forward + isOrBecomesErrored(source, reader._closedPromise, storedError => { + if (!preventAbort) { + shutdownWithAction(() => WritableStreamAbort(dest, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + return null; + }); + // Errors must be propagated backward + isOrBecomesErrored(dest, writer._closedPromise, storedError => { + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, storedError), true, storedError); + } + else { + shutdown(true, storedError); + } + return null; + }); + // Closing must be propagated forward + isOrBecomesClosed(source, reader._closedPromise, () => { + if (!preventClose) { + shutdownWithAction(() => WritableStreamDefaultWriterCloseWithErrorPropagation(writer)); + } + else { + shutdown(); + } + return null; + }); + // Closing must be propagated backward + if (WritableStreamCloseQueuedOrInFlight(dest) || dest._state === 'closed') { + const destClosed = new TypeError('the destination writable stream closed before all data could be piped to it'); + if (!preventCancel) { + shutdownWithAction(() => ReadableStreamCancel(source, destClosed), true, destClosed); + } + else { + shutdown(true, destClosed); + } + } + setPromiseIsHandledToTrue(pipeLoop()); + function waitForWritesToFinish() { + // Another write may have started while we were waiting on this currentWrite, so we have to be sure to wait + // for that too. + const oldCurrentWrite = currentWrite; + return PerformPromiseThen(currentWrite, () => oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined); + } + function isOrBecomesErrored(stream, promise, action) { + if (stream._state === 'errored') { + action(stream._storedError); + } + else { + uponRejection(promise, action); + } + } + function isOrBecomesClosed(stream, promise, action) { + if (stream._state === 'closed') { + action(); + } + else { + uponFulfillment(promise, action); + } + } + function shutdownWithAction(action, originalIsError, originalError) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), doTheRest); + } + else { + doTheRest(); + } + function doTheRest() { + uponPromise(action(), () => finalize(originalIsError, originalError), newError => finalize(true, newError)); + return null; + } + } + function shutdown(isError, error) { + if (shuttingDown) { + return; + } + shuttingDown = true; + if (dest._state === 'writable' && !WritableStreamCloseQueuedOrInFlight(dest)) { + uponFulfillment(waitForWritesToFinish(), () => finalize(isError, error)); + } + else { + finalize(isError, error); + } + } + function finalize(isError, error) { + WritableStreamDefaultWriterRelease(writer); + ReadableStreamReaderGenericRelease(reader); + if (signal !== undefined) { + signal.removeEventListener('abort', abortAlgorithm); + } + if (isError) { + reject(error); + } + else { + resolve(undefined); + } + return null; + } + }); + } + + /** + * Allows control of a {@link ReadableStream | readable stream}'s state and internal queue. + * + * @public + */ + class ReadableStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the desired size to fill the controlled stream's internal queue. It can be negative, if the queue is + * over-full. An underlying source ought to use this information to determine when and how to apply backpressure. + */ + get desiredSize() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('desiredSize'); + } + return ReadableStreamDefaultControllerGetDesiredSize(this); + } + /** + * Closes the controlled readable stream. Consumers will still be able to read any previously-enqueued chunks from + * the stream, but once those are read, the stream will become closed. + */ + close() { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('close'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits close'); + } + ReadableStreamDefaultControllerClose(this); + } + enqueue(chunk = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('enqueue'); + } + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(this)) { + throw new TypeError('The stream is not in a state that permits enqueue'); + } + return ReadableStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors the controlled readable stream, making all future interactions with it fail with the given error `e`. + */ + error(e = undefined) { + if (!IsReadableStreamDefaultController(this)) { + throw defaultControllerBrandCheckException$1('error'); + } + ReadableStreamDefaultControllerError(this, e); + } + /** @internal */ + [CancelSteps](reason) { + ResetQueue(this); + const result = this._cancelAlgorithm(reason); + ReadableStreamDefaultControllerClearAlgorithms(this); + return result; + } + /** @internal */ + [PullSteps](readRequest) { + const stream = this._controlledReadableStream; + if (this._queue.length > 0) { + const chunk = DequeueValue(this); + if (this._closeRequested && this._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(this); + ReadableStreamClose(stream); + } + else { + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + readRequest._chunkSteps(chunk); + } + else { + ReadableStreamAddReadRequest(stream, readRequest); + ReadableStreamDefaultControllerCallPullIfNeeded(this); + } + } + /** @internal */ + [ReleaseSteps]() { + // Do nothing. + } + } + Object.defineProperties(ReadableStreamDefaultController.prototype, { + close: { enumerable: true }, + enqueue: { enumerable: true }, + error: { enumerable: true }, + desiredSize: { enumerable: true } + }); + setFunctionName(ReadableStreamDefaultController.prototype.close, 'close'); + setFunctionName(ReadableStreamDefaultController.prototype.enqueue, 'enqueue'); + setFunctionName(ReadableStreamDefaultController.prototype.error, 'error'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(ReadableStreamDefaultController.prototype, Symbol.toStringTag, { + value: 'ReadableStreamDefaultController', + configurable: true + }); + } + // Abstract operations for the ReadableStreamDefaultController. + function IsReadableStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledReadableStream')) { + return false; + } + return x instanceof ReadableStreamDefaultController; + } + function ReadableStreamDefaultControllerCallPullIfNeeded(controller) { + const shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller); + if (!shouldPull) { + return; + } + if (controller._pulling) { + controller._pullAgain = true; + return; + } + controller._pulling = true; + const pullPromise = controller._pullAlgorithm(); + uponPromise(pullPromise, () => { + controller._pulling = false; + if (controller._pullAgain) { + controller._pullAgain = false; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + } + return null; + }, e => { + ReadableStreamDefaultControllerError(controller, e); + return null; + }); + } + function ReadableStreamDefaultControllerShouldCallPull(controller) { + const stream = controller._controlledReadableStream; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return false; + } + if (!controller._started) { + return false; + } + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + return true; + } + const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); + if (desiredSize > 0) { + return true; + } + return false; + } + function ReadableStreamDefaultControllerClearAlgorithms(controller) { + controller._pullAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + controller._strategySizeAlgorithm = undefined; + } + // A client of ReadableStreamDefaultController may use these functions directly to bypass state check. + function ReadableStreamDefaultControllerClose(controller) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + controller._closeRequested = true; + if (controller._queue.length === 0) { + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamClose(stream); + } + } + function ReadableStreamDefaultControllerEnqueue(controller, chunk) { + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)) { + return; + } + const stream = controller._controlledReadableStream; + if (IsReadableStreamLocked(stream) && ReadableStreamGetNumReadRequests(stream) > 0) { + ReadableStreamFulfillReadRequest(stream, chunk, false); + } + else { + let chunkSize; + try { + chunkSize = controller._strategySizeAlgorithm(chunk); + } + catch (chunkSizeE) { + ReadableStreamDefaultControllerError(controller, chunkSizeE); + throw chunkSizeE; + } + try { + EnqueueValueWithSize(controller, chunk, chunkSize); + } + catch (enqueueE) { + ReadableStreamDefaultControllerError(controller, enqueueE); + throw enqueueE; + } + } + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + } + function ReadableStreamDefaultControllerError(controller, e) { + const stream = controller._controlledReadableStream; + if (stream._state !== 'readable') { + return; + } + ResetQueue(controller); + ReadableStreamDefaultControllerClearAlgorithms(controller); + ReadableStreamError(stream, e); + } + function ReadableStreamDefaultControllerGetDesiredSize(controller) { + const state = controller._controlledReadableStream._state; + if (state === 'errored') { + return null; + } + if (state === 'closed') { + return 0; + } + return controller._strategyHWM - controller._queueTotalSize; + } + // This is used in the implementation of TransformStream. + function ReadableStreamDefaultControllerHasBackpressure(controller) { + if (ReadableStreamDefaultControllerShouldCallPull(controller)) { + return false; + } + return true; + } + function ReadableStreamDefaultControllerCanCloseOrEnqueue(controller) { + const state = controller._controlledReadableStream._state; + if (!controller._closeRequested && state === 'readable') { + return true; + } + return false; + } + function SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm) { + controller._controlledReadableStream = stream; + controller._queue = undefined; + controller._queueTotalSize = undefined; + ResetQueue(controller); + controller._started = false; + controller._closeRequested = false; + controller._pullAgain = false; + controller._pulling = false; + controller._strategySizeAlgorithm = sizeAlgorithm; + controller._strategyHWM = highWaterMark; + controller._pullAlgorithm = pullAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + stream._readableStreamController = controller; + const startResult = startAlgorithm(); + uponPromise(promiseResolvedWith(startResult), () => { + controller._started = true; + ReadableStreamDefaultControllerCallPullIfNeeded(controller); + return null; + }, r => { + ReadableStreamDefaultControllerError(controller, r); + return null; + }); + } + function SetUpReadableStreamDefaultControllerFromUnderlyingSource(stream, underlyingSource, highWaterMark, sizeAlgorithm) { + const controller = Object.create(ReadableStreamDefaultController.prototype); + let startAlgorithm; + let pullAlgorithm; + let cancelAlgorithm; + if (underlyingSource.start !== undefined) { + startAlgorithm = () => underlyingSource.start(controller); + } + else { + startAlgorithm = () => undefined; + } + if (underlyingSource.pull !== undefined) { + pullAlgorithm = () => underlyingSource.pull(controller); + } + else { + pullAlgorithm = () => promiseResolvedWith(undefined); + } + if (underlyingSource.cancel !== undefined) { + cancelAlgorithm = reason => underlyingSource.cancel(reason); + } + else { + cancelAlgorithm = () => promiseResolvedWith(undefined); + } + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); + } + // Helper functions for the ReadableStreamDefaultController. + function defaultControllerBrandCheckException$1(name) { + return new TypeError(`ReadableStreamDefaultController.prototype.${name} can only be used on a ReadableStreamDefaultController`); + } + + function ReadableStreamTee(stream, cloneForBranch2) { + if (IsReadableByteStreamController(stream._readableStreamController)) { + return ReadableByteStreamTee(stream); + } + return ReadableStreamDefaultTee(stream); + } + function ReadableStreamDefaultTee(stream, cloneForBranch2) { + const reader = AcquireReadableStreamDefaultReader(stream); + let reading = false; + let readAgain = false; + let canceled1 = false; + let canceled2 = false; + let reason1; + let reason2; + let branch1; + let branch2; + let resolveCancelPromise; + const cancelPromise = newPromise(resolve => { + resolveCancelPromise = resolve; + }); + function pullAlgorithm() { + if (reading) { + readAgain = true; + return promiseResolvedWith(undefined); + } + reading = true; + const readRequest = { + _chunkSteps: chunk => { + // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using + // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let + // successful synchronously-available reads get ahead of asynchronously-available errors. + _queueMicrotask(() => { + readAgain = false; + const chunk1 = chunk; + const chunk2 = chunk; + // There is no way to access the cloning code right now in the reference implementation. + // If we add one then we'll need an implementation for serializable objects. + // if (!canceled2 && cloneForBranch2) { + // chunk2 = StructuredDeserialize(StructuredSerialize(chunk2)); + // } + if (!canceled1) { + ReadableStreamDefaultControllerEnqueue(branch1._readableStreamController, chunk1); + } + if (!canceled2) { + ReadableStreamDefaultControllerEnqueue(branch2._readableStreamController, chunk2); + } + reading = false; + if (readAgain) { + pullAlgorithm(); + } + }); + }, + _closeSteps: () => { + reading = false; + if (!canceled1) { + ReadableStreamDefaultControllerClose(branch1._readableStreamController); + } + if (!canceled2) { + ReadableStreamDefaultControllerClose(branch2._readableStreamController); + } + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }, + _errorSteps: () => { + reading = false; + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + return promiseResolvedWith(undefined); + } + function cancel1Algorithm(reason) { + canceled1 = true; + reason1 = reason; + if (canceled2) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function cancel2Algorithm(reason) { + canceled2 = true; + reason2 = reason; + if (canceled1) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function startAlgorithm() { + // do nothing + } + branch1 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel1Algorithm); + branch2 = CreateReadableStream(startAlgorithm, pullAlgorithm, cancel2Algorithm); + uponRejection(reader._closedPromise, (r) => { + ReadableStreamDefaultControllerError(branch1._readableStreamController, r); + ReadableStreamDefaultControllerError(branch2._readableStreamController, r); + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + return null; + }); + return [branch1, branch2]; + } + function ReadableByteStreamTee(stream) { + let reader = AcquireReadableStreamDefaultReader(stream); + let reading = false; + let readAgainForBranch1 = false; + let readAgainForBranch2 = false; + let canceled1 = false; + let canceled2 = false; + let reason1; + let reason2; + let branch1; + let branch2; + let resolveCancelPromise; + const cancelPromise = newPromise(resolve => { + resolveCancelPromise = resolve; + }); + function forwardReaderError(thisReader) { + uponRejection(thisReader._closedPromise, r => { + if (thisReader !== reader) { + return null; + } + ReadableByteStreamControllerError(branch1._readableStreamController, r); + ReadableByteStreamControllerError(branch2._readableStreamController, r); + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + return null; + }); + } + function pullWithDefaultReader() { + if (IsReadableStreamBYOBReader(reader)) { + ReadableStreamReaderGenericRelease(reader); + reader = AcquireReadableStreamDefaultReader(stream); + forwardReaderError(reader); + } + const readRequest = { + _chunkSteps: chunk => { + // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using + // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let + // successful synchronously-available reads get ahead of asynchronously-available errors. + _queueMicrotask(() => { + readAgainForBranch1 = false; + readAgainForBranch2 = false; + const chunk1 = chunk; + let chunk2 = chunk; + if (!canceled1 && !canceled2) { + try { + chunk2 = CloneAsUint8Array(chunk); + } + catch (cloneE) { + ReadableByteStreamControllerError(branch1._readableStreamController, cloneE); + ReadableByteStreamControllerError(branch2._readableStreamController, cloneE); + resolveCancelPromise(ReadableStreamCancel(stream, cloneE)); + return; + } + } + if (!canceled1) { + ReadableByteStreamControllerEnqueue(branch1._readableStreamController, chunk1); + } + if (!canceled2) { + ReadableByteStreamControllerEnqueue(branch2._readableStreamController, chunk2); + } + reading = false; + if (readAgainForBranch1) { + pull1Algorithm(); + } + else if (readAgainForBranch2) { + pull2Algorithm(); + } + }); + }, + _closeSteps: () => { + reading = false; + if (!canceled1) { + ReadableByteStreamControllerClose(branch1._readableStreamController); + } + if (!canceled2) { + ReadableByteStreamControllerClose(branch2._readableStreamController); + } + if (branch1._readableStreamController._pendingPullIntos.length > 0) { + ReadableByteStreamControllerRespond(branch1._readableStreamController, 0); + } + if (branch2._readableStreamController._pendingPullIntos.length > 0) { + ReadableByteStreamControllerRespond(branch2._readableStreamController, 0); + } + if (!canceled1 || !canceled2) { + resolveCancelPromise(undefined); + } + }, + _errorSteps: () => { + reading = false; + } + }; + ReadableStreamDefaultReaderRead(reader, readRequest); + } + function pullWithBYOBReader(view, forBranch2) { + if (IsReadableStreamDefaultReader(reader)) { + ReadableStreamReaderGenericRelease(reader); + reader = AcquireReadableStreamBYOBReader(stream); + forwardReaderError(reader); + } + const byobBranch = forBranch2 ? branch2 : branch1; + const otherBranch = forBranch2 ? branch1 : branch2; + const readIntoRequest = { + _chunkSteps: chunk => { + // This needs to be delayed a microtask because it takes at least a microtask to detect errors (using + // reader._closedPromise below), and we want errors in stream to error both branches immediately. We cannot let + // successful synchronously-available reads get ahead of asynchronously-available errors. + _queueMicrotask(() => { + readAgainForBranch1 = false; + readAgainForBranch2 = false; + const byobCanceled = forBranch2 ? canceled2 : canceled1; + const otherCanceled = forBranch2 ? canceled1 : canceled2; + if (!otherCanceled) { + let clonedChunk; + try { + clonedChunk = CloneAsUint8Array(chunk); + } + catch (cloneE) { + ReadableByteStreamControllerError(byobBranch._readableStreamController, cloneE); + ReadableByteStreamControllerError(otherBranch._readableStreamController, cloneE); + resolveCancelPromise(ReadableStreamCancel(stream, cloneE)); + return; + } + if (!byobCanceled) { + ReadableByteStreamControllerRespondWithNewView(byobBranch._readableStreamController, chunk); + } + ReadableByteStreamControllerEnqueue(otherBranch._readableStreamController, clonedChunk); + } + else if (!byobCanceled) { + ReadableByteStreamControllerRespondWithNewView(byobBranch._readableStreamController, chunk); + } + reading = false; + if (readAgainForBranch1) { + pull1Algorithm(); + } + else if (readAgainForBranch2) { + pull2Algorithm(); + } + }); + }, + _closeSteps: chunk => { + reading = false; + const byobCanceled = forBranch2 ? canceled2 : canceled1; + const otherCanceled = forBranch2 ? canceled1 : canceled2; + if (!byobCanceled) { + ReadableByteStreamControllerClose(byobBranch._readableStreamController); + } + if (!otherCanceled) { + ReadableByteStreamControllerClose(otherBranch._readableStreamController); + } + if (chunk !== undefined) { + if (!byobCanceled) { + ReadableByteStreamControllerRespondWithNewView(byobBranch._readableStreamController, chunk); + } + if (!otherCanceled && otherBranch._readableStreamController._pendingPullIntos.length > 0) { + ReadableByteStreamControllerRespond(otherBranch._readableStreamController, 0); + } + } + if (!byobCanceled || !otherCanceled) { + resolveCancelPromise(undefined); + } + }, + _errorSteps: () => { + reading = false; + } + }; + ReadableStreamBYOBReaderRead(reader, view, 1, readIntoRequest); + } + function pull1Algorithm() { + if (reading) { + readAgainForBranch1 = true; + return promiseResolvedWith(undefined); + } + reading = true; + const byobRequest = ReadableByteStreamControllerGetBYOBRequest(branch1._readableStreamController); + if (byobRequest === null) { + pullWithDefaultReader(); + } + else { + pullWithBYOBReader(byobRequest._view, false); + } + return promiseResolvedWith(undefined); + } + function pull2Algorithm() { + if (reading) { + readAgainForBranch2 = true; + return promiseResolvedWith(undefined); + } + reading = true; + const byobRequest = ReadableByteStreamControllerGetBYOBRequest(branch2._readableStreamController); + if (byobRequest === null) { + pullWithDefaultReader(); + } + else { + pullWithBYOBReader(byobRequest._view, true); + } + return promiseResolvedWith(undefined); + } + function cancel1Algorithm(reason) { + canceled1 = true; + reason1 = reason; + if (canceled2) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function cancel2Algorithm(reason) { + canceled2 = true; + reason2 = reason; + if (canceled1) { + const compositeReason = CreateArrayFromList([reason1, reason2]); + const cancelResult = ReadableStreamCancel(stream, compositeReason); + resolveCancelPromise(cancelResult); + } + return cancelPromise; + } + function startAlgorithm() { + return; + } + branch1 = CreateReadableByteStream(startAlgorithm, pull1Algorithm, cancel1Algorithm); + branch2 = CreateReadableByteStream(startAlgorithm, pull2Algorithm, cancel2Algorithm); + forwardReaderError(reader); + return [branch1, branch2]; + } + + function isReadableStreamLike(stream) { + return typeIsObject(stream) && typeof stream.getReader !== 'undefined'; + } + + function ReadableStreamFrom(source) { + if (isReadableStreamLike(source)) { + return ReadableStreamFromDefaultReader(source.getReader()); + } + return ReadableStreamFromIterable(source); + } + function ReadableStreamFromIterable(asyncIterable) { + let stream; + const iteratorRecord = GetIterator(asyncIterable, 'async'); + const startAlgorithm = noop; + function pullAlgorithm() { + let nextResult; + try { + nextResult = IteratorNext(iteratorRecord); + } + catch (e) { + return promiseRejectedWith(e); + } + const nextPromise = promiseResolvedWith(nextResult); + return transformPromiseWith(nextPromise, iterResult => { + if (!typeIsObject(iterResult)) { + throw new TypeError('The promise returned by the iterator.next() method must fulfill with an object'); + } + const done = IteratorComplete(iterResult); + if (done) { + ReadableStreamDefaultControllerClose(stream._readableStreamController); + } + else { + const value = IteratorValue(iterResult); + ReadableStreamDefaultControllerEnqueue(stream._readableStreamController, value); + } + }); + } + function cancelAlgorithm(reason) { + const iterator = iteratorRecord.iterator; + let returnMethod; + try { + returnMethod = GetMethod(iterator, 'return'); + } + catch (e) { + return promiseRejectedWith(e); + } + if (returnMethod === undefined) { + return promiseResolvedWith(undefined); + } + let returnResult; + try { + returnResult = reflectCall(returnMethod, iterator, [reason]); + } + catch (e) { + return promiseRejectedWith(e); + } + const returnPromise = promiseResolvedWith(returnResult); + return transformPromiseWith(returnPromise, iterResult => { + if (!typeIsObject(iterResult)) { + throw new TypeError('The promise returned by the iterator.return() method must fulfill with an object'); + } + return undefined; + }); + } + stream = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, 0); + return stream; + } + function ReadableStreamFromDefaultReader(reader) { + let stream; + const startAlgorithm = noop; + function pullAlgorithm() { + let readPromise; + try { + readPromise = reader.read(); + } + catch (e) { + return promiseRejectedWith(e); + } + return transformPromiseWith(readPromise, readResult => { + if (!typeIsObject(readResult)) { + throw new TypeError('The promise returned by the reader.read() method must fulfill with an object'); + } + if (readResult.done) { + ReadableStreamDefaultControllerClose(stream._readableStreamController); + } + else { + const value = readResult.value; + ReadableStreamDefaultControllerEnqueue(stream._readableStreamController, value); + } + }); + } + function cancelAlgorithm(reason) { + try { + return promiseResolvedWith(reader.cancel(reason)); + } + catch (e) { + return promiseRejectedWith(e); + } + } + stream = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, 0); + return stream; + } + + function convertUnderlyingDefaultOrByteSource(source, context) { + assertDictionary(source, context); + const original = source; + const autoAllocateChunkSize = original === null || original === void 0 ? void 0 : original.autoAllocateChunkSize; + const cancel = original === null || original === void 0 ? void 0 : original.cancel; + const pull = original === null || original === void 0 ? void 0 : original.pull; + const start = original === null || original === void 0 ? void 0 : original.start; + const type = original === null || original === void 0 ? void 0 : original.type; + return { + autoAllocateChunkSize: autoAllocateChunkSize === undefined ? + undefined : + convertUnsignedLongLongWithEnforceRange(autoAllocateChunkSize, `${context} has member 'autoAllocateChunkSize' that`), + cancel: cancel === undefined ? + undefined : + convertUnderlyingSourceCancelCallback(cancel, original, `${context} has member 'cancel' that`), + pull: pull === undefined ? + undefined : + convertUnderlyingSourcePullCallback(pull, original, `${context} has member 'pull' that`), + start: start === undefined ? + undefined : + convertUnderlyingSourceStartCallback(start, original, `${context} has member 'start' that`), + type: type === undefined ? undefined : convertReadableStreamType(type, `${context} has member 'type' that`) + }; + } + function convertUnderlyingSourceCancelCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); + } + function convertUnderlyingSourcePullCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); + } + function convertUnderlyingSourceStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertReadableStreamType(type, context) { + type = `${type}`; + if (type !== 'bytes') { + throw new TypeError(`${context} '${type}' is not a valid enumeration value for ReadableStreamType`); + } + return type; + } + + function convertIteratorOptions(options, context) { + assertDictionary(options, context); + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + return { preventCancel: Boolean(preventCancel) }; + } + + function convertPipeOptions(options, context) { + assertDictionary(options, context); + const preventAbort = options === null || options === void 0 ? void 0 : options.preventAbort; + const preventCancel = options === null || options === void 0 ? void 0 : options.preventCancel; + const preventClose = options === null || options === void 0 ? void 0 : options.preventClose; + const signal = options === null || options === void 0 ? void 0 : options.signal; + if (signal !== undefined) { + assertAbortSignal(signal, `${context} has member 'signal' that`); + } + return { + preventAbort: Boolean(preventAbort), + preventCancel: Boolean(preventCancel), + preventClose: Boolean(preventClose), + signal + }; + } + function assertAbortSignal(signal, context) { + if (!isAbortSignal(signal)) { + throw new TypeError(`${context} is not an AbortSignal.`); + } + } + + function convertReadableWritablePair(pair, context) { + assertDictionary(pair, context); + const readable = pair === null || pair === void 0 ? void 0 : pair.readable; + assertRequiredField(readable, 'readable', 'ReadableWritablePair'); + assertReadableStream(readable, `${context} has member 'readable' that`); + const writable = pair === null || pair === void 0 ? void 0 : pair.writable; + assertRequiredField(writable, 'writable', 'ReadableWritablePair'); + assertWritableStream(writable, `${context} has member 'writable' that`); + return { readable, writable }; + } + + /** + * A readable stream represents a source of data, from which you can read. + * + * @public + */ + class ReadableStream { + constructor(rawUnderlyingSource = {}, rawStrategy = {}) { + if (rawUnderlyingSource === undefined) { + rawUnderlyingSource = null; + } + else { + assertObject(rawUnderlyingSource, 'First parameter'); + } + const strategy = convertQueuingStrategy(rawStrategy, 'Second parameter'); + const underlyingSource = convertUnderlyingDefaultOrByteSource(rawUnderlyingSource, 'First parameter'); + InitializeReadableStream(this); + if (underlyingSource.type === 'bytes') { + if (strategy.size !== undefined) { + throw new RangeError('The strategy for a byte stream cannot have a size function'); + } + const highWaterMark = ExtractHighWaterMark(strategy, 0); + SetUpReadableByteStreamControllerFromUnderlyingSource(this, underlyingSource, highWaterMark); + } + else { + const sizeAlgorithm = ExtractSizeAlgorithm(strategy); + const highWaterMark = ExtractHighWaterMark(strategy, 1); + SetUpReadableStreamDefaultControllerFromUnderlyingSource(this, underlyingSource, highWaterMark, sizeAlgorithm); + } + } + /** + * Whether or not the readable stream is locked to a {@link ReadableStreamDefaultReader | reader}. + */ + get locked() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('locked'); + } + return IsReadableStreamLocked(this); + } + /** + * Cancels the stream, signaling a loss of interest in the stream by a consumer. + * + * The supplied `reason` argument will be given to the underlying source's {@link UnderlyingSource.cancel | cancel()} + * method, which might or might not use it. + */ + cancel(reason = undefined) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('cancel')); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('Cannot cancel a stream that already has a reader')); + } + return ReadableStreamCancel(this, reason); + } + getReader(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('getReader'); + } + const options = convertReaderOptions(rawOptions, 'First parameter'); + if (options.mode === undefined) { + return AcquireReadableStreamDefaultReader(this); + } + return AcquireReadableStreamBYOBReader(this); + } + pipeThrough(rawTransform, rawOptions = {}) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('pipeThrough'); + } + assertRequiredArgument(rawTransform, 1, 'pipeThrough'); + const transform = convertReadableWritablePair(rawTransform, 'First parameter'); + const options = convertPipeOptions(rawOptions, 'Second parameter'); + if (IsReadableStreamLocked(this)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked ReadableStream'); + } + if (IsWritableStreamLocked(transform.writable)) { + throw new TypeError('ReadableStream.prototype.pipeThrough cannot be used on a locked WritableStream'); + } + const promise = ReadableStreamPipeTo(this, transform.writable, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + setPromiseIsHandledToTrue(promise); + return transform.readable; + } + pipeTo(destination, rawOptions = {}) { + if (!IsReadableStream(this)) { + return promiseRejectedWith(streamBrandCheckException$1('pipeTo')); + } + if (destination === undefined) { + return promiseRejectedWith(`Parameter 1 is required in 'pipeTo'.`); + } + if (!IsWritableStream(destination)) { + return promiseRejectedWith(new TypeError(`ReadableStream.prototype.pipeTo's first argument must be a WritableStream`)); + } + let options; + try { + options = convertPipeOptions(rawOptions, 'Second parameter'); + } + catch (e) { + return promiseRejectedWith(e); + } + if (IsReadableStreamLocked(this)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream')); + } + if (IsWritableStreamLocked(destination)) { + return promiseRejectedWith(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream')); + } + return ReadableStreamPipeTo(this, destination, options.preventClose, options.preventAbort, options.preventCancel, options.signal); + } + /** + * Tees this readable stream, returning a two-element array containing the two resulting branches as + * new {@link ReadableStream} instances. + * + * Teeing a stream will lock it, preventing any other consumer from acquiring a reader. + * To cancel the stream, cancel both of the resulting branches; a composite cancellation reason will then be + * propagated to the stream's underlying source. + * + * Note that the chunks seen in each branch will be the same object. If the chunks are not immutable, + * this could allow interference between the two branches. + */ + tee() { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('tee'); + } + const branches = ReadableStreamTee(this); + return CreateArrayFromList(branches); + } + values(rawOptions = undefined) { + if (!IsReadableStream(this)) { + throw streamBrandCheckException$1('values'); + } + const options = convertIteratorOptions(rawOptions, 'First parameter'); + return AcquireReadableStreamAsyncIterator(this, options.preventCancel); + } + [SymbolAsyncIterator](options) { + // Stub implementation, overridden below + return this.values(options); + } + /** + * Creates a new ReadableStream wrapping the provided iterable or async iterable. + * + * This can be used to adapt various kinds of objects into a readable stream, + * such as an array, an async generator, or a Node.js readable stream. + */ + static from(asyncIterable) { + return ReadableStreamFrom(asyncIterable); + } + } + Object.defineProperties(ReadableStream, { + from: { enumerable: true } + }); + Object.defineProperties(ReadableStream.prototype, { + cancel: { enumerable: true }, + getReader: { enumerable: true }, + pipeThrough: { enumerable: true }, + pipeTo: { enumerable: true }, + tee: { enumerable: true }, + values: { enumerable: true }, + locked: { enumerable: true } + }); + setFunctionName(ReadableStream.from, 'from'); + setFunctionName(ReadableStream.prototype.cancel, 'cancel'); + setFunctionName(ReadableStream.prototype.getReader, 'getReader'); + setFunctionName(ReadableStream.prototype.pipeThrough, 'pipeThrough'); + setFunctionName(ReadableStream.prototype.pipeTo, 'pipeTo'); + setFunctionName(ReadableStream.prototype.tee, 'tee'); + setFunctionName(ReadableStream.prototype.values, 'values'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(ReadableStream.prototype, Symbol.toStringTag, { + value: 'ReadableStream', + configurable: true + }); + } + Object.defineProperty(ReadableStream.prototype, SymbolAsyncIterator, { + value: ReadableStream.prototype.values, + writable: true, + configurable: true + }); + // Abstract operations for the ReadableStream. + // Throws if and only if startAlgorithm throws. + function CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark = 1, sizeAlgorithm = () => 1) { + const stream = Object.create(ReadableStream.prototype); + InitializeReadableStream(stream); + const controller = Object.create(ReadableStreamDefaultController.prototype); + SetUpReadableStreamDefaultController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark, sizeAlgorithm); + return stream; + } + // Throws if and only if startAlgorithm throws. + function CreateReadableByteStream(startAlgorithm, pullAlgorithm, cancelAlgorithm) { + const stream = Object.create(ReadableStream.prototype); + InitializeReadableStream(stream); + const controller = Object.create(ReadableByteStreamController.prototype); + SetUpReadableByteStreamController(stream, controller, startAlgorithm, pullAlgorithm, cancelAlgorithm, 0, undefined); + return stream; + } + function InitializeReadableStream(stream) { + stream._state = 'readable'; + stream._reader = undefined; + stream._storedError = undefined; + stream._disturbed = false; + } + function IsReadableStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) { + return false; + } + return x instanceof ReadableStream; + } + function IsReadableStreamLocked(stream) { + if (stream._reader === undefined) { + return false; + } + return true; + } + // ReadableStream API exposed for controllers. + function ReadableStreamCancel(stream, reason) { + stream._disturbed = true; + if (stream._state === 'closed') { + return promiseResolvedWith(undefined); + } + if (stream._state === 'errored') { + return promiseRejectedWith(stream._storedError); + } + ReadableStreamClose(stream); + const reader = stream._reader; + if (reader !== undefined && IsReadableStreamBYOBReader(reader)) { + const readIntoRequests = reader._readIntoRequests; + reader._readIntoRequests = new SimpleQueue(); + readIntoRequests.forEach(readIntoRequest => { + readIntoRequest._closeSteps(undefined); + }); + } + const sourceCancelPromise = stream._readableStreamController[CancelSteps](reason); + return transformPromiseWith(sourceCancelPromise, noop); + } + function ReadableStreamClose(stream) { + stream._state = 'closed'; + const reader = stream._reader; + if (reader === undefined) { + return; + } + defaultReaderClosedPromiseResolve(reader); + if (IsReadableStreamDefaultReader(reader)) { + const readRequests = reader._readRequests; + reader._readRequests = new SimpleQueue(); + readRequests.forEach(readRequest => { + readRequest._closeSteps(); + }); + } + } + function ReadableStreamError(stream, e) { + stream._state = 'errored'; + stream._storedError = e; + const reader = stream._reader; + if (reader === undefined) { + return; + } + defaultReaderClosedPromiseReject(reader, e); + if (IsReadableStreamDefaultReader(reader)) { + ReadableStreamDefaultReaderErrorReadRequests(reader, e); + } + else { + ReadableStreamBYOBReaderErrorReadIntoRequests(reader, e); + } + } + // Helper functions for the ReadableStream. + function streamBrandCheckException$1(name) { + return new TypeError(`ReadableStream.prototype.${name} can only be used on a ReadableStream`); + } + + function convertQueuingStrategyInit(init, context) { + assertDictionary(init, context); + const highWaterMark = init === null || init === void 0 ? void 0 : init.highWaterMark; + assertRequiredField(highWaterMark, 'highWaterMark', 'QueuingStrategyInit'); + return { + highWaterMark: convertUnrestrictedDouble(highWaterMark) + }; + } + + // The size function must not have a prototype property nor be a constructor + const byteLengthSizeFunction = (chunk) => { + return chunk.byteLength; + }; + setFunctionName(byteLengthSizeFunction, 'size'); + /** + * A queuing strategy that counts the number of bytes in each chunk. + * + * @public + */ + class ByteLengthQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'ByteLengthQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._byteLengthQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('highWaterMark'); + } + return this._byteLengthQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by returning the value of its `byteLength` property. + */ + get size() { + if (!IsByteLengthQueuingStrategy(this)) { + throw byteLengthBrandCheckException('size'); + } + return byteLengthSizeFunction; + } + } + Object.defineProperties(ByteLengthQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } + }); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(ByteLengthQueuingStrategy.prototype, Symbol.toStringTag, { + value: 'ByteLengthQueuingStrategy', + configurable: true + }); + } + // Helper functions for the ByteLengthQueuingStrategy. + function byteLengthBrandCheckException(name) { + return new TypeError(`ByteLengthQueuingStrategy.prototype.${name} can only be used on a ByteLengthQueuingStrategy`); + } + function IsByteLengthQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_byteLengthQueuingStrategyHighWaterMark')) { + return false; + } + return x instanceof ByteLengthQueuingStrategy; + } + + // The size function must not have a prototype property nor be a constructor + const countSizeFunction = () => { + return 1; + }; + setFunctionName(countSizeFunction, 'size'); + /** + * A queuing strategy that counts the number of chunks. + * + * @public + */ + class CountQueuingStrategy { + constructor(options) { + assertRequiredArgument(options, 1, 'CountQueuingStrategy'); + options = convertQueuingStrategyInit(options, 'First parameter'); + this._countQueuingStrategyHighWaterMark = options.highWaterMark; + } + /** + * Returns the high water mark provided to the constructor. + */ + get highWaterMark() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('highWaterMark'); + } + return this._countQueuingStrategyHighWaterMark; + } + /** + * Measures the size of `chunk` by always returning 1. + * This ensures that the total queue size is a count of the number of chunks in the queue. + */ + get size() { + if (!IsCountQueuingStrategy(this)) { + throw countBrandCheckException('size'); + } + return countSizeFunction; + } + } + Object.defineProperties(CountQueuingStrategy.prototype, { + highWaterMark: { enumerable: true }, + size: { enumerable: true } + }); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(CountQueuingStrategy.prototype, Symbol.toStringTag, { + value: 'CountQueuingStrategy', + configurable: true + }); + } + // Helper functions for the CountQueuingStrategy. + function countBrandCheckException(name) { + return new TypeError(`CountQueuingStrategy.prototype.${name} can only be used on a CountQueuingStrategy`); + } + function IsCountQueuingStrategy(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_countQueuingStrategyHighWaterMark')) { + return false; + } + return x instanceof CountQueuingStrategy; + } + + function convertTransformer(original, context) { + assertDictionary(original, context); + const cancel = original === null || original === void 0 ? void 0 : original.cancel; + const flush = original === null || original === void 0 ? void 0 : original.flush; + const readableType = original === null || original === void 0 ? void 0 : original.readableType; + const start = original === null || original === void 0 ? void 0 : original.start; + const transform = original === null || original === void 0 ? void 0 : original.transform; + const writableType = original === null || original === void 0 ? void 0 : original.writableType; + return { + cancel: cancel === undefined ? + undefined : + convertTransformerCancelCallback(cancel, original, `${context} has member 'cancel' that`), + flush: flush === undefined ? + undefined : + convertTransformerFlushCallback(flush, original, `${context} has member 'flush' that`), + readableType, + start: start === undefined ? + undefined : + convertTransformerStartCallback(start, original, `${context} has member 'start' that`), + transform: transform === undefined ? + undefined : + convertTransformerTransformCallback(transform, original, `${context} has member 'transform' that`), + writableType + }; + } + function convertTransformerFlushCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => promiseCall(fn, original, [controller]); + } + function convertTransformerStartCallback(fn, original, context) { + assertFunction(fn, context); + return (controller) => reflectCall(fn, original, [controller]); + } + function convertTransformerTransformCallback(fn, original, context) { + assertFunction(fn, context); + return (chunk, controller) => promiseCall(fn, original, [chunk, controller]); + } + function convertTransformerCancelCallback(fn, original, context) { + assertFunction(fn, context); + return (reason) => promiseCall(fn, original, [reason]); + } + + // Class TransformStream + /** + * A transform stream consists of a pair of streams: a {@link WritableStream | writable stream}, + * known as its writable side, and a {@link ReadableStream | readable stream}, known as its readable side. + * In a manner specific to the transform stream in question, writes to the writable side result in new data being + * made available for reading from the readable side. + * + * @public + */ + class TransformStream { + constructor(rawTransformer = {}, rawWritableStrategy = {}, rawReadableStrategy = {}) { + if (rawTransformer === undefined) { + rawTransformer = null; + } + const writableStrategy = convertQueuingStrategy(rawWritableStrategy, 'Second parameter'); + const readableStrategy = convertQueuingStrategy(rawReadableStrategy, 'Third parameter'); + const transformer = convertTransformer(rawTransformer, 'First parameter'); + if (transformer.readableType !== undefined) { + throw new RangeError('Invalid readableType specified'); + } + if (transformer.writableType !== undefined) { + throw new RangeError('Invalid writableType specified'); + } + const readableHighWaterMark = ExtractHighWaterMark(readableStrategy, 0); + const readableSizeAlgorithm = ExtractSizeAlgorithm(readableStrategy); + const writableHighWaterMark = ExtractHighWaterMark(writableStrategy, 1); + const writableSizeAlgorithm = ExtractSizeAlgorithm(writableStrategy); + let startPromise_resolve; + const startPromise = newPromise(resolve => { + startPromise_resolve = resolve; + }); + InitializeTransformStream(this, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + SetUpTransformStreamDefaultControllerFromTransformer(this, transformer); + if (transformer.start !== undefined) { + startPromise_resolve(transformer.start(this._transformStreamController)); + } + else { + startPromise_resolve(undefined); + } + } + /** + * The readable side of the transform stream. + */ + get readable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('readable'); + } + return this._readable; + } + /** + * The writable side of the transform stream. + */ + get writable() { + if (!IsTransformStream(this)) { + throw streamBrandCheckException('writable'); + } + return this._writable; + } + } + Object.defineProperties(TransformStream.prototype, { + readable: { enumerable: true }, + writable: { enumerable: true } + }); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(TransformStream.prototype, Symbol.toStringTag, { + value: 'TransformStream', + configurable: true + }); + } + function InitializeTransformStream(stream, startPromise, writableHighWaterMark, writableSizeAlgorithm, readableHighWaterMark, readableSizeAlgorithm) { + function startAlgorithm() { + return startPromise; + } + function writeAlgorithm(chunk) { + return TransformStreamDefaultSinkWriteAlgorithm(stream, chunk); + } + function abortAlgorithm(reason) { + return TransformStreamDefaultSinkAbortAlgorithm(stream, reason); + } + function closeAlgorithm() { + return TransformStreamDefaultSinkCloseAlgorithm(stream); + } + stream._writable = CreateWritableStream(startAlgorithm, writeAlgorithm, closeAlgorithm, abortAlgorithm, writableHighWaterMark, writableSizeAlgorithm); + function pullAlgorithm() { + return TransformStreamDefaultSourcePullAlgorithm(stream); + } + function cancelAlgorithm(reason) { + return TransformStreamDefaultSourceCancelAlgorithm(stream, reason); + } + stream._readable = CreateReadableStream(startAlgorithm, pullAlgorithm, cancelAlgorithm, readableHighWaterMark, readableSizeAlgorithm); + // The [[backpressure]] slot is set to undefined so that it can be initialised by TransformStreamSetBackpressure. + stream._backpressure = undefined; + stream._backpressureChangePromise = undefined; + stream._backpressureChangePromise_resolve = undefined; + TransformStreamSetBackpressure(stream, true); + stream._transformStreamController = undefined; + } + function IsTransformStream(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) { + return false; + } + return x instanceof TransformStream; + } + // This is a no-op if both sides are already errored. + function TransformStreamError(stream, e) { + ReadableStreamDefaultControllerError(stream._readable._readableStreamController, e); + TransformStreamErrorWritableAndUnblockWrite(stream, e); + } + function TransformStreamErrorWritableAndUnblockWrite(stream, e) { + TransformStreamDefaultControllerClearAlgorithms(stream._transformStreamController); + WritableStreamDefaultControllerErrorIfNeeded(stream._writable._writableStreamController, e); + TransformStreamUnblockWrite(stream); + } + function TransformStreamUnblockWrite(stream) { + if (stream._backpressure) { + // Pretend that pull() was called to permit any pending write() calls to complete. TransformStreamSetBackpressure() + // cannot be called from enqueue() or pull() once the ReadableStream is errored, so this will will be the final time + // _backpressure is set. + TransformStreamSetBackpressure(stream, false); + } + } + function TransformStreamSetBackpressure(stream, backpressure) { + // Passes also when called during construction. + if (stream._backpressureChangePromise !== undefined) { + stream._backpressureChangePromise_resolve(); + } + stream._backpressureChangePromise = newPromise(resolve => { + stream._backpressureChangePromise_resolve = resolve; + }); + stream._backpressure = backpressure; + } + // Class TransformStreamDefaultController + /** + * Allows control of the {@link ReadableStream} and {@link WritableStream} of the associated {@link TransformStream}. + * + * @public + */ + class TransformStreamDefaultController { + constructor() { + throw new TypeError('Illegal constructor'); + } + /** + * Returns the desired size to fill the readable sideā€™s internal queue. It can be negative, if the queue is over-full. + */ + get desiredSize() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('desiredSize'); + } + const readableController = this._controlledTransformStream._readable._readableStreamController; + return ReadableStreamDefaultControllerGetDesiredSize(readableController); + } + enqueue(chunk = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('enqueue'); + } + TransformStreamDefaultControllerEnqueue(this, chunk); + } + /** + * Errors both the readable side and the writable side of the controlled transform stream, making all future + * interactions with it fail with the given error `e`. Any chunks queued for transformation will be discarded. + */ + error(reason = undefined) { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('error'); + } + TransformStreamDefaultControllerError(this, reason); + } + /** + * Closes the readable side and errors the writable side of the controlled transform stream. This is useful when the + * transformer only needs to consume a portion of the chunks written to the writable side. + */ + terminate() { + if (!IsTransformStreamDefaultController(this)) { + throw defaultControllerBrandCheckException('terminate'); + } + TransformStreamDefaultControllerTerminate(this); + } + } + Object.defineProperties(TransformStreamDefaultController.prototype, { + enqueue: { enumerable: true }, + error: { enumerable: true }, + terminate: { enumerable: true }, + desiredSize: { enumerable: true } + }); + setFunctionName(TransformStreamDefaultController.prototype.enqueue, 'enqueue'); + setFunctionName(TransformStreamDefaultController.prototype.error, 'error'); + setFunctionName(TransformStreamDefaultController.prototype.terminate, 'terminate'); + if (typeof Symbol.toStringTag === 'symbol') { + Object.defineProperty(TransformStreamDefaultController.prototype, Symbol.toStringTag, { + value: 'TransformStreamDefaultController', + configurable: true + }); + } + // Transform Stream Default Controller Abstract Operations + function IsTransformStreamDefaultController(x) { + if (!typeIsObject(x)) { + return false; + } + if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) { + return false; + } + return x instanceof TransformStreamDefaultController; + } + function SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm, cancelAlgorithm) { + controller._controlledTransformStream = stream; + stream._transformStreamController = controller; + controller._transformAlgorithm = transformAlgorithm; + controller._flushAlgorithm = flushAlgorithm; + controller._cancelAlgorithm = cancelAlgorithm; + controller._finishPromise = undefined; + controller._finishPromise_resolve = undefined; + controller._finishPromise_reject = undefined; + } + function SetUpTransformStreamDefaultControllerFromTransformer(stream, transformer) { + const controller = Object.create(TransformStreamDefaultController.prototype); + let transformAlgorithm; + let flushAlgorithm; + let cancelAlgorithm; + if (transformer.transform !== undefined) { + transformAlgorithm = chunk => transformer.transform(chunk, controller); + } + else { + transformAlgorithm = chunk => { + try { + TransformStreamDefaultControllerEnqueue(controller, chunk); + return promiseResolvedWith(undefined); + } + catch (transformResultE) { + return promiseRejectedWith(transformResultE); + } + }; + } + if (transformer.flush !== undefined) { + flushAlgorithm = () => transformer.flush(controller); + } + else { + flushAlgorithm = () => promiseResolvedWith(undefined); + } + if (transformer.cancel !== undefined) { + cancelAlgorithm = reason => transformer.cancel(reason); + } + else { + cancelAlgorithm = () => promiseResolvedWith(undefined); + } + SetUpTransformStreamDefaultController(stream, controller, transformAlgorithm, flushAlgorithm, cancelAlgorithm); + } + function TransformStreamDefaultControllerClearAlgorithms(controller) { + controller._transformAlgorithm = undefined; + controller._flushAlgorithm = undefined; + controller._cancelAlgorithm = undefined; + } + function TransformStreamDefaultControllerEnqueue(controller, chunk) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + if (!ReadableStreamDefaultControllerCanCloseOrEnqueue(readableController)) { + throw new TypeError('Readable side is not in a state that permits enqueue'); + } + // We throttle transform invocations based on the backpressure of the ReadableStream, but we still + // accept TransformStreamDefaultControllerEnqueue() calls. + try { + ReadableStreamDefaultControllerEnqueue(readableController, chunk); + } + catch (e) { + // This happens when readableStrategy.size() throws. + TransformStreamErrorWritableAndUnblockWrite(stream, e); + throw stream._readable._storedError; + } + const backpressure = ReadableStreamDefaultControllerHasBackpressure(readableController); + if (backpressure !== stream._backpressure) { + TransformStreamSetBackpressure(stream, true); + } + } + function TransformStreamDefaultControllerError(controller, e) { + TransformStreamError(controller._controlledTransformStream, e); + } + function TransformStreamDefaultControllerPerformTransform(controller, chunk) { + const transformPromise = controller._transformAlgorithm(chunk); + return transformPromiseWith(transformPromise, undefined, r => { + TransformStreamError(controller._controlledTransformStream, r); + throw r; + }); + } + function TransformStreamDefaultControllerTerminate(controller) { + const stream = controller._controlledTransformStream; + const readableController = stream._readable._readableStreamController; + ReadableStreamDefaultControllerClose(readableController); + const error = new TypeError('TransformStream terminated'); + TransformStreamErrorWritableAndUnblockWrite(stream, error); + } + // TransformStreamDefaultSink Algorithms + function TransformStreamDefaultSinkWriteAlgorithm(stream, chunk) { + const controller = stream._transformStreamController; + if (stream._backpressure) { + const backpressureChangePromise = stream._backpressureChangePromise; + return transformPromiseWith(backpressureChangePromise, () => { + const writable = stream._writable; + const state = writable._state; + if (state === 'erroring') { + throw writable._storedError; + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + }); + } + return TransformStreamDefaultControllerPerformTransform(controller, chunk); + } + function TransformStreamDefaultSinkAbortAlgorithm(stream, reason) { + const controller = stream._transformStreamController; + if (controller._finishPromise !== undefined) { + return controller._finishPromise; + } + // stream._readable cannot change after construction, so caching it across a call to user code is safe. + const readable = stream._readable; + // Assign the _finishPromise now so that if _cancelAlgorithm calls readable.cancel() internally, + // we don't run the _cancelAlgorithm again. + controller._finishPromise = newPromise((resolve, reject) => { + controller._finishPromise_resolve = resolve; + controller._finishPromise_reject = reject; + }); + const cancelPromise = controller._cancelAlgorithm(reason); + TransformStreamDefaultControllerClearAlgorithms(controller); + uponPromise(cancelPromise, () => { + if (readable._state === 'errored') { + defaultControllerFinishPromiseReject(controller, readable._storedError); + } + else { + ReadableStreamDefaultControllerError(readable._readableStreamController, reason); + defaultControllerFinishPromiseResolve(controller); + } + return null; + }, r => { + ReadableStreamDefaultControllerError(readable._readableStreamController, r); + defaultControllerFinishPromiseReject(controller, r); + return null; + }); + return controller._finishPromise; + } + function TransformStreamDefaultSinkCloseAlgorithm(stream) { + const controller = stream._transformStreamController; + if (controller._finishPromise !== undefined) { + return controller._finishPromise; + } + // stream._readable cannot change after construction, so caching it across a call to user code is safe. + const readable = stream._readable; + // Assign the _finishPromise now so that if _flushAlgorithm calls readable.cancel() internally, + // we don't also run the _cancelAlgorithm. + controller._finishPromise = newPromise((resolve, reject) => { + controller._finishPromise_resolve = resolve; + controller._finishPromise_reject = reject; + }); + const flushPromise = controller._flushAlgorithm(); + TransformStreamDefaultControllerClearAlgorithms(controller); + uponPromise(flushPromise, () => { + if (readable._state === 'errored') { + defaultControllerFinishPromiseReject(controller, readable._storedError); + } + else { + ReadableStreamDefaultControllerClose(readable._readableStreamController); + defaultControllerFinishPromiseResolve(controller); + } + return null; + }, r => { + ReadableStreamDefaultControllerError(readable._readableStreamController, r); + defaultControllerFinishPromiseReject(controller, r); + return null; + }); + return controller._finishPromise; + } + // TransformStreamDefaultSource Algorithms + function TransformStreamDefaultSourcePullAlgorithm(stream) { + // Invariant. Enforced by the promises returned by start() and pull(). + TransformStreamSetBackpressure(stream, false); + // Prevent the next pull() call until there is backpressure. + return stream._backpressureChangePromise; + } + function TransformStreamDefaultSourceCancelAlgorithm(stream, reason) { + const controller = stream._transformStreamController; + if (controller._finishPromise !== undefined) { + return controller._finishPromise; + } + // stream._writable cannot change after construction, so caching it across a call to user code is safe. + const writable = stream._writable; + // Assign the _finishPromise now so that if _flushAlgorithm calls writable.abort() or + // writable.cancel() internally, we don't run the _cancelAlgorithm again, or also run the + // _flushAlgorithm. + controller._finishPromise = newPromise((resolve, reject) => { + controller._finishPromise_resolve = resolve; + controller._finishPromise_reject = reject; + }); + const cancelPromise = controller._cancelAlgorithm(reason); + TransformStreamDefaultControllerClearAlgorithms(controller); + uponPromise(cancelPromise, () => { + if (writable._state === 'errored') { + defaultControllerFinishPromiseReject(controller, writable._storedError); + } + else { + WritableStreamDefaultControllerErrorIfNeeded(writable._writableStreamController, reason); + TransformStreamUnblockWrite(stream); + defaultControllerFinishPromiseResolve(controller); + } + return null; + }, r => { + WritableStreamDefaultControllerErrorIfNeeded(writable._writableStreamController, r); + TransformStreamUnblockWrite(stream); + defaultControllerFinishPromiseReject(controller, r); + return null; + }); + return controller._finishPromise; + } + // Helper functions for the TransformStreamDefaultController. + function defaultControllerBrandCheckException(name) { + return new TypeError(`TransformStreamDefaultController.prototype.${name} can only be used on a TransformStreamDefaultController`); + } + function defaultControllerFinishPromiseResolve(controller) { + if (controller._finishPromise_resolve === undefined) { + return; + } + controller._finishPromise_resolve(); + controller._finishPromise_resolve = undefined; + controller._finishPromise_reject = undefined; + } + function defaultControllerFinishPromiseReject(controller, reason) { + if (controller._finishPromise_reject === undefined) { + return; + } + setPromiseIsHandledToTrue(controller._finishPromise); + controller._finishPromise_reject(reason); + controller._finishPromise_resolve = undefined; + controller._finishPromise_reject = undefined; + } + // Helper functions for the TransformStream. + function streamBrandCheckException(name) { + return new TypeError(`TransformStream.prototype.${name} can only be used on a TransformStream`); + } + + exports.ByteLengthQueuingStrategy = ByteLengthQueuingStrategy; + exports.CountQueuingStrategy = CountQueuingStrategy; + exports.ReadableByteStreamController = ReadableByteStreamController; + exports.ReadableStream = ReadableStream; + exports.ReadableStreamBYOBReader = ReadableStreamBYOBReader; + exports.ReadableStreamBYOBRequest = ReadableStreamBYOBRequest; + exports.ReadableStreamDefaultController = ReadableStreamDefaultController; + exports.ReadableStreamDefaultReader = ReadableStreamDefaultReader; + exports.TransformStream = TransformStream; + exports.TransformStreamDefaultController = TransformStreamDefaultController; + exports.WritableStream = WritableStream; + exports.WritableStreamDefaultController = WritableStreamDefaultController; + exports.WritableStreamDefaultWriter = WritableStreamDefaultWriter; + +})); +//# sourceMappingURL=ponyfill.es2018.js.map + + +/***/ }), + +/***/ 2940: +/***/ ((module) => { + +// Returns a wrapper function that returns a wrapped callback +// The wrapper function should do some stuff, and return a +// presumably different callback function. +// This makes sure that own properties are retained, so that +// decorations and such are not lost along the way. +module.exports = wrappy +function wrappy (fn, cb) { + if (fn && cb) return wrappy(fn)(cb) + + if (typeof fn !== 'function') + throw new TypeError('need wrapper function') + + Object.keys(fn).forEach(function (k) { + wrapper[k] = fn[k] + }) + + return wrapper + + function wrapper() { + var args = new Array(arguments.length) + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i] + } + var ret = fn.apply(this, args) + var cb = args[args.length-1] + if (typeof ret === 'function' && ret !== cb) { + Object.keys(cb).forEach(function (k) { + ret[k] = cb[k] + }) + } + return ret + } +} + + +/***/ }), + +/***/ 2644: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const core_1 = __nccwpck_require__(2186); +const github_1 = __nccwpck_require__(5438); +const CONST_1 = __importDefault(__nccwpck_require__(9873)); +const GithubUtils_1 = __importDefault(__nccwpck_require__(9296)); +const OpenAIUtils_1 = __importDefault(__nccwpck_require__(3)); +function isCommentCreatedOrEditedEvent(payload) { + return payload.action === CONST_1.default.ACTIONS.CREATED || payload.action === CONST_1.default.ACTIONS.EDIT; +} +function isCommentCreatedEvent(payload) { + return payload.action === CONST_1.default.ACTIONS.CREATED; +} +// Main function to process the workflow event +async function run() { + // Verify this is running for an expected webhook event + if (github_1.context.eventName !== CONST_1.default.EVENTS.ISSUE_COMMENT) { + throw new Error('ProposalPoliceā„¢ only supports the issue_comment webhook event'); + } + const payload = github_1.context.payload; + // check if the issue is open and the has labels + if (payload.issue?.state !== 'open' && !payload.issue?.labels.some((issueLabel) => issueLabel.name === CONST_1.default.LABELS.HELP_WANTED)) { + return; + } + // Verify that the comment is not empty and contains the case sensitive `Proposal` keyword + if (!payload.comment?.body.trim() || !payload.comment?.body.includes(CONST_1.default.PROPOSAL_KEYWORD)) { + console.log('Comment body is either empty or doesn\'t contain the keyword "Proposal": ', payload.comment?.body); + return; + } + console.log('ProposalPoliceā„¢ Action triggered for comment:', payload.comment?.body); + console.log('-> GitHub Action Type: ', payload.action?.toUpperCase()); + if (!isCommentCreatedOrEditedEvent(payload)) { + console.error('Unsupported action type:', payload?.action); + (0, core_1.setFailed)(new Error(`Unsupported action type ${payload?.action}`)); + return; + } + const prompt = isCommentCreatedEvent(payload) + ? `I NEED HELP WITH CASE (1.), CHECK IF COMMENT IS PROPOSAL AND IF TEMPLATE IS FOLLOWED AS PER INSTRUCTIONS. IT IS MANDATORY THAT YOU RESPOND ONLY WITH "${CONST_1.default.NO_ACTION}" IN CASE THE COMMENT IS NOT A PROPOSAL. Comment content: ${payload.comment?.body}` + : `I NEED HELP WITH CASE (2.) WHEN A USER THAT POSTED AN INITIAL PROPOSAL OR COMMENT (UNEDITED) THEN EDITS THE COMMENT - WE NEED TO CLASSIFY THE COMMENT BASED IN THE GIVEN INSTRUCTIONS AND IF TEMPLATE IS FOLLOWED AS PER INSTRUCTIONS. IT IS MANDATORY THAT YOU RESPOND ONLY WITH "${CONST_1.default.NO_ACTION}" IN CASE THE COMMENT IS NOT A PROPOSAL. \n\nPrevious comment content: ${payload.changes.body?.from}.\n\nEdited comment content: ${payload.comment?.body}`; + const assistantResponse = await OpenAIUtils_1.default.prompt(prompt); + // check if assistant response is either NO_ACTION or "NO_ACTION" strings + // as sometimes the assistant response varies + const isNoAction = assistantResponse.trim().replaceAll(' ', '_').replaceAll('"', '').toUpperCase() === CONST_1.default.NO_ACTION; + // If assistant response is NO_ACTION, do nothing + if (isNoAction) { + console.log('Detected NO_ACTION for comment, returning early'); + return; + } + // if the assistant responded with no action but there's some context in the response + if (assistantResponse.includes(`[${CONST_1.default.NO_ACTION}]`)) { + // extract the text after [NO_ACTION] from assistantResponse since this is a + // bot related action keyword + const noActionContext = assistantResponse.split(`[${CONST_1.default.NO_ACTION}] `)?.[1]?.replace('"', ''); + console.log('[NO_ACTION] w/ context: ', noActionContext); + return; + } + if (isCommentCreatedEvent(payload)) { + const formattedResponse = assistantResponse + // replace {user} from response template with @username + .replaceAll('{user}', `@${payload.comment?.user.login}`) + // replace {proposalLink} from response template with the link to the comment + .replaceAll('{proposalLink}', payload.comment?.html_url) + // remove any double quotes from the final comment because sometimes the assistant's + // response contains double quotes / sometimes it doesn't + .replaceAll('"', ''); + // Create a comment with the assistant's response + console.log('ProposalPoliceā„¢ commenting on issue...'); + await GithubUtils_1.default.createComment(CONST_1.default.APP_REPO, github_1.context.issue.number, formattedResponse); + // edit comment if assistant detected substantial changes and if the comment was not edited already by the bot + } + else if (assistantResponse.includes('[EDIT_COMMENT]') && !payload.comment?.body.includes('Edited by **proposal-police**')) { + // extract the text after [EDIT_COMMENT] from assistantResponse since this is a + // bot related action keyword + let extractedNotice = assistantResponse.split('[EDIT_COMMENT] ')?.[1]?.replace('"', ''); + // format the github's updated_at like: 2024-01-24 13:15:24 UTC not 2024-01-28 18:18:28.000 UTC + const date = new Date(payload.comment?.updated_at ?? ''); + const formattedDate = `${date.toISOString()?.split('.')?.[0]?.replace('T', ' ')} UTC`; + extractedNotice = extractedNotice.replace('{updated_timestamp}', formattedDate); + console.log('ProposalPoliceā„¢ editing issue comment...', payload.comment.id); + await GithubUtils_1.default.octokit.issues.updateComment({ + ...github_1.context.repo, + /* eslint-disable @typescript-eslint/naming-convention */ + comment_id: payload.comment.id, + body: `${extractedNotice}\n\n${payload.comment?.body}`, + }); + } +} +run().catch((error) => { + console.error(error); + process.exit(1); +}); + + +/***/ }), + +/***/ 9873: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const GITHUB_BASE_URL_REGEX = new RegExp('https?://(?:github\\.com|api\\.github\\.com)'); +const GIT_CONST = { + GITHUB_OWNER: 'Expensify', + APP_REPO: 'App', +}; +const CONST = { + ...GIT_CONST, + APPLAUSE_BOT: 'applausebot', + OS_BOTIFY: 'OSBotify', + LABELS: { + STAGING_DEPLOY: 'StagingDeployCash', + DEPLOY_BLOCKER: 'DeployBlockerCash', + INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', + }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', + DATE_FORMAT_STRING: 'yyyy-MM-dd', + PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), + ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), + ISSUE_OR_PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/(?:pull|issues)/([0-9]+).*`), + POLL_RATE: 10000, + APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, + APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, +}; +exports["default"] = CONST; + + +/***/ }), + +/***/ 9296: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +/* eslint-disable @typescript-eslint/naming-convention, import/no-import-module-exports */ +const core = __importStar(__nccwpck_require__(2186)); +const utils_1 = __nccwpck_require__(3030); +const plugin_paginate_rest_1 = __nccwpck_require__(4193); +const plugin_throttling_1 = __nccwpck_require__(9968); +const EmptyObject_1 = __nccwpck_require__(8227); +const arrayDifference_1 = __importDefault(__nccwpck_require__(7034)); +const CONST_1 = __importDefault(__nccwpck_require__(9873)); +class GithubUtils { + static internalOctokit; + /** + * Initialize internal octokit. + * NOTE: When using GithubUtils in CI, you don't need to call this manually. + */ + static initOctokitWithToken(token) { + const Octokit = utils_1.GitHub.plugin(plugin_throttling_1.throttling, plugin_paginate_rest_1.paginateRest); + // Save a copy of octokit used in this class + this.internalOctokit = new Octokit((0, utils_1.getOctokitOptions)(token, { + throttle: { + retryAfterBaseValue: 2000, + onRateLimit: (retryAfter, options) => { + console.warn(`Request quota exhausted for request ${options.method} ${options.url}`); + // Retry five times when hitting a rate limit error, then give up + if (options.request.retryCount <= 5) { + console.log(`Retrying after ${retryAfter} seconds!`); + return true; + } + }, + onAbuseLimit: (retryAfter, options) => { + // does not retry, only logs a warning + console.warn(`Abuse detected for request ${options.method} ${options.url}`); + }, + }, + })); + } + /** + * Default initialize method assuming running in CI, getting the token from an input. + * + * @private + */ + static initOctokit() { + const token = core.getInput('GITHUB_TOKEN', { required: true }); + this.initOctokitWithToken(token); + } + /** + * Either give an existing instance of Octokit rest or create a new one + * + * @readonly + * @static + */ + static get octokit() { + if (!this.internalOctokit) { + this.initOctokit(); + } + // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style + return this.internalOctokit.rest; + } + /** + * Get the graphql instance from internal octokit. + * @readonly + * @static + */ + static get graphql() { + if (!this.internalOctokit) { + this.initOctokit(); + } + // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style + return this.internalOctokit.graphql; + } + /** + * Either give an existing instance of Octokit paginate or create a new one + * + * @readonly + * @static + */ + static get paginate() { + if (!this.internalOctokit) { + this.initOctokit(); + } + // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style + return this.internalOctokit.paginate; + } + /** + * Finds one open `StagingDeployCash` issue via GitHub octokit library. + */ + static getStagingDeployCash() { + return this.octokit.issues + .listForRepo({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + labels: CONST_1.default.LABELS.STAGING_DEPLOY, + state: 'open', + }) + .then(({ data }) => { + if (!data.length) { + throw new Error(`Unable to find ${CONST_1.default.LABELS.STAGING_DEPLOY} issue.`); + } + if (data.length > 1) { + throw new Error(`Found more than one ${CONST_1.default.LABELS.STAGING_DEPLOY} issue.`); + } + return this.getStagingDeployCashData(data[0]); + }); + } + /** + * Takes in a GitHub issue object and returns the data we want. + */ + static getStagingDeployCashData(issue) { + try { + const versionRegex = new RegExp('([0-9]+)\\.([0-9]+)\\.([0-9]+)(?:-([0-9]+))?', 'g'); + const tag = issue.body?.match(versionRegex)?.[0].replace(/`/g, ''); + return { + title: issue.title, + url: issue.url, + number: this.getIssueOrPullRequestNumberFromURL(issue.url), + labels: issue.labels, + PRList: this.getStagingDeployCashPRList(issue), + deployBlockers: this.getStagingDeployCashDeployBlockers(issue), + internalQAPRList: this.getStagingDeployCashInternalQA(issue), + isTimingDashboardChecked: issue.body ? /-\s\[x]\sI checked the \[App Timing Dashboard]/.test(issue.body) : false, + isFirebaseChecked: issue.body ? /-\s\[x]\sI checked \[Firebase Crashlytics]/.test(issue.body) : false, + isGHStatusChecked: issue.body ? /-\s\[x]\sI checked \[GitHub Status]/.test(issue.body) : false, + tag, + }; + } + catch (exception) { + throw new Error(`Unable to find ${CONST_1.default.LABELS.STAGING_DEPLOY} issue with correct data.`); + } + } + /** + * Parse the PRList and Internal QA section of the StagingDeployCash issue body. + * + * @private + */ + static getStagingDeployCashPRList(issue) { + let PRListSection = issue.body?.match(/pull requests:\*\*\r?\n((?:-.*\r?\n)+)\r?\n\r?\n?/) ?? null; + if (PRListSection?.length !== 2) { + // No PRs, return an empty array + console.log('Hmmm...The open StagingDeployCash does not list any pull requests, continuing...'); + return []; + } + PRListSection = PRListSection[1]; + const PRList = [...PRListSection.matchAll(new RegExp(`- \\[([ x])] (${CONST_1.default.PULL_REQUEST_REGEX.source})`, 'g'))].map((match) => ({ + url: match[2], + number: Number.parseInt(match[3], 10), + isVerified: match[1] === 'x', + })); + return PRList.sort((a, b) => a.number - b.number); + } + /** + * Parse DeployBlocker section of the StagingDeployCash issue body. + * + * @private + */ + static getStagingDeployCashDeployBlockers(issue) { + let deployBlockerSection = issue.body?.match(/Deploy Blockers:\*\*\r?\n((?:-.*\r?\n)+)/) ?? null; + if (deployBlockerSection?.length !== 2) { + return []; + } + deployBlockerSection = deployBlockerSection[1]; + const deployBlockers = [...deployBlockerSection.matchAll(new RegExp(`- \\[([ x])]\\s(${CONST_1.default.ISSUE_OR_PULL_REQUEST_REGEX.source})`, 'g'))].map((match) => ({ + url: match[2], + number: Number.parseInt(match[3], 10), + isResolved: match[1] === 'x', + })); + return deployBlockers.sort((a, b) => a.number - b.number); + } + /** + * Parse InternalQA section of the StagingDeployCash issue body. + * + * @private + */ + static getStagingDeployCashInternalQA(issue) { + let internalQASection = issue.body?.match(/Internal QA:\*\*\r?\n((?:- \[[ x]].*\r?\n)+)/) ?? null; + if (internalQASection?.length !== 2) { + return []; + } + internalQASection = internalQASection[1]; + const internalQAPRs = [...internalQASection.matchAll(new RegExp(`- \\[([ x])]\\s(${CONST_1.default.PULL_REQUEST_REGEX.source})`, 'g'))].map((match) => ({ + url: match[2].split('-')[0].trim(), + number: Number.parseInt(match[3], 10), + isResolved: match[1] === 'x', + })); + return internalQAPRs.sort((a, b) => a.number - b.number); + } + /** + * Generate the issue body and assignees for a StagingDeployCash. + */ + static generateStagingDeployCashBodyAndAssignees(tag, PRList, verifiedPRList = [], deployBlockers = [], resolvedDeployBlockers = [], resolvedInternalQAPRs = [], isTimingDashboardChecked = false, isFirebaseChecked = false, isGHStatusChecked = false) { + return this.fetchAllPullRequests(PRList.map((pr) => this.getPullRequestNumberFromURL(pr))) + .then((data) => { + const internalQAPRs = Array.isArray(data) ? data.filter((pr) => !(0, EmptyObject_1.isEmptyObject)(pr.labels.find((item) => item.name === CONST_1.default.LABELS.INTERNAL_QA))) : []; + return Promise.all(internalQAPRs.map((pr) => this.getPullRequestMergerLogin(pr.number).then((mergerLogin) => ({ url: pr.html_url, mergerLogin })))).then((results) => { + // The format of this map is following: + // { + // 'https://github.com/Expensify/App/pull/9641': 'PauloGasparSv', + // 'https://github.com/Expensify/App/pull/9642': 'mountiny' + // } + const internalQAPRMap = results.reduce((acc, { url, mergerLogin }) => { + acc[url] = mergerLogin; + return acc; + }, {}); + console.log('Found the following Internal QA PRs:', internalQAPRMap); + const noQAPRs = Array.isArray(data) ? data.filter((PR) => /\[No\s?QA]/i.test(PR.title)).map((item) => item.html_url) : []; + console.log('Found the following NO QA PRs:', noQAPRs); + const verifiedOrNoQAPRs = [...new Set([...verifiedPRList, ...noQAPRs])]; + const sortedPRList = [...new Set((0, arrayDifference_1.default)(PRList, Object.keys(internalQAPRMap)))].sort((a, b) => GithubUtils.getPullRequestNumberFromURL(a) - GithubUtils.getPullRequestNumberFromURL(b)); + const sortedDeployBlockers = [...new Set(deployBlockers)].sort((a, b) => GithubUtils.getIssueOrPullRequestNumberFromURL(a) - GithubUtils.getIssueOrPullRequestNumberFromURL(b)); + // Tag version and comparison URL + // eslint-disable-next-line max-len + let issueBody = `**Release Version:** \`${tag}\`\r\n**Compare Changes:** https://github.com/Expensify/App/compare/production...staging\r\n`; + // PR list + if (sortedPRList.length > 0) { + issueBody += '\r\n**This release contains changes from the following pull requests:**\r\n'; + sortedPRList.forEach((URL) => { + issueBody += verifiedOrNoQAPRs.includes(URL) ? '- [x]' : '- [ ]'; + issueBody += ` ${URL}\r\n`; + }); + issueBody += '\r\n\r\n'; + } + // Internal QA PR list + if (!(0, EmptyObject_1.isEmptyObject)(internalQAPRMap)) { + console.log('Found the following verified Internal QA PRs:', resolvedInternalQAPRs); + issueBody += '**Internal QA:**\r\n'; + Object.keys(internalQAPRMap).forEach((URL) => { + const merger = internalQAPRMap[URL]; + const mergerMention = `@${merger}`; + issueBody += `${resolvedInternalQAPRs.includes(URL) ? '- [x]' : '- [ ]'} `; + issueBody += `${URL}`; + issueBody += ` - ${mergerMention}`; + issueBody += '\r\n'; + }); + issueBody += '\r\n\r\n'; + } + // Deploy blockers + if (deployBlockers.length > 0) { + issueBody += '**Deploy Blockers:**\r\n'; + sortedDeployBlockers.forEach((URL) => { + issueBody += resolvedDeployBlockers.includes(URL) ? '- [x] ' : '- [ ] '; + issueBody += URL; + issueBody += '\r\n'; + }); + issueBody += '\r\n\r\n'; + } + issueBody += '**Deployer verifications:**'; + // eslint-disable-next-line max-len + issueBody += `\r\n- [${isTimingDashboardChecked ? 'x' : ' '}] I checked the [App Timing Dashboard](https://graphs.expensify.com/grafana/d/yj2EobAGz/app-timing?orgId=1) and verified this release does not cause a noticeable performance regression.`; + // eslint-disable-next-line max-len + issueBody += `\r\n- [${isFirebaseChecked ? 'x' : ' '}] I checked [Firebase Crashlytics](https://console.firebase.google.com/u/0/project/expensify-chat/crashlytics/app/android:com.expensify.chat/issues?state=open&time=last-seven-days&tag=all) and verified that this release does not introduce any new crashes. More detailed instructions on this verification can be found [here](https://stackoverflowteams.com/c/expensify/questions/15095/15096).`; + // eslint-disable-next-line max-len + issueBody += `\r\n- [${isGHStatusChecked ? 'x' : ' '}] I checked [GitHub Status](https://www.githubstatus.com/) and verified there is no reported incident with Actions.`; + issueBody += '\r\n\r\ncc @Expensify/applauseleads\r\n'; + const issueAssignees = [...new Set(Object.values(internalQAPRMap))]; + const issue = { issueBody, issueAssignees }; + return issue; + }); + }) + .catch((err) => console.warn('Error generating StagingDeployCash issue body! Continuing...', err)); + } + /** + * Fetch all pull requests given a list of PR numbers. + */ + static fetchAllPullRequests(pullRequestNumbers) { + const oldestPR = pullRequestNumbers.sort((a, b) => a - b)[0]; + return this.paginate(this.octokit.pulls.list, { + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + state: 'all', + sort: 'created', + direction: 'desc', + per_page: 100, + }, ({ data }, done) => { + if (data.find((pr) => pr.number === oldestPR)) { + done(); + } + return data; + }) + .then((prList) => prList.filter((pr) => pullRequestNumbers.includes(pr.number))) + .catch((err) => console.error('Failed to get PR list', err)); + } + static getPullRequestMergerLogin(pullRequestNumber) { + return this.octokit.pulls + .get({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + pull_number: pullRequestNumber, + }) + .then(({ data: pullRequest }) => pullRequest.merged_by?.login); + } + static getPullRequestBody(pullRequestNumber) { + return this.octokit.pulls + .get({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + pull_number: pullRequestNumber, + }) + .then(({ data: pullRequestComment }) => pullRequestComment.body); + } + static getAllReviewComments(pullRequestNumber) { + return this.paginate(this.octokit.pulls.listReviews, { + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + pull_number: pullRequestNumber, + per_page: 100, + }, (response) => response.data.map((review) => review.body)); + } + static getAllComments(issueNumber) { + return this.paginate(this.octokit.issues.listComments, { + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + issue_number: issueNumber, + per_page: 100, + }, (response) => response.data.map((comment) => comment.body)); + } + /** + * Create comment on pull request + */ + static createComment(repo, number, messageBody) { + console.log(`Writing comment on #${number}`); + return this.octokit.issues.createComment({ + owner: CONST_1.default.GITHUB_OWNER, + repo, + issue_number: number, + body: messageBody, + }); + } + /** + * Get the most recent workflow run for the given New Expensify workflow. + */ + static getLatestWorkflowRunID(workflow) { + console.log(`Fetching New Expensify workflow runs for ${workflow}...`); + return this.octokit.actions + .listWorkflowRuns({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + workflow_id: workflow, + }) + .then((response) => response.data.workflow_runs[0]?.id); + } + /** + * Generate the URL of an New Expensify pull request given the PR number. + */ + static getPullRequestURLFromNumber(value) { + return `${CONST_1.default.APP_REPO_URL}/pull/${value}`; + } + /** + * Parse the pull request number from a URL. + * + * @throws {Error} If the URL is not a valid Github Pull Request. + */ + static getPullRequestNumberFromURL(URL) { + const matches = URL.match(CONST_1.default.PULL_REQUEST_REGEX); + if (!Array.isArray(matches) || matches.length !== 2) { + throw new Error(`Provided URL ${URL} is not a Github Pull Request!`); + } + return Number.parseInt(matches[1], 10); + } + /** + * Parse the issue number from a URL. + * + * @throws {Error} If the URL is not a valid Github Issue. + */ + static getIssueNumberFromURL(URL) { + const matches = URL.match(CONST_1.default.ISSUE_REGEX); + if (!Array.isArray(matches) || matches.length !== 2) { + throw new Error(`Provided URL ${URL} is not a Github Issue!`); + } + return Number.parseInt(matches[1], 10); + } + /** + * Parse the issue or pull request number from a URL. + * + * @throws {Error} If the URL is not a valid Github Issue or Pull Request. + */ + static getIssueOrPullRequestNumberFromURL(URL) { + const matches = URL.match(CONST_1.default.ISSUE_OR_PULL_REQUEST_REGEX); + if (!Array.isArray(matches) || matches.length !== 2) { + throw new Error(`Provided URL ${URL} is not a valid Github Issue or Pull Request!`); + } + return Number.parseInt(matches[1], 10); + } + /** + * Return the login of the actor who closed an issue or PR. If the issue is not closed, return an empty string. + */ + static getActorWhoClosedIssue(issueNumber) { + return this.paginate(this.octokit.issues.listEvents, { + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + issue_number: issueNumber, + per_page: 100, + }) + .then((events) => events.filter((event) => event.event === 'closed')) + .then((closedEvents) => closedEvents.at(-1)?.actor?.login ?? ''); + } + /** + * Returns a single artifact by name. If none is found, it returns undefined. + */ + static getArtifactByName(artifactName) { + return this.octokit.actions + .listArtifactsForRepo({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + per_page: 1, + name: artifactName, + }) + .then((response) => response.data.artifacts[0]); + } + /** + * Given an artifact ID, returns the download URL to a zip file containing the artifact. + */ + static getArtifactDownloadURL(artifactId) { + return this.octokit.actions + .downloadArtifact({ + owner: CONST_1.default.GITHUB_OWNER, + repo: CONST_1.default.APP_REPO, + artifact_id: artifactId, + archive_format: 'zip', + }) + .then((response) => response.url); + } +} +exports["default"] = GithubUtils; + + +/***/ }), + +/***/ 3: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const core_1 = __nccwpck_require__(2186); +const openai_1 = __importDefault(__nccwpck_require__(47)); +const CONST_1 = __importDefault(__nccwpck_require__(9873)); +const MAX_POLL_COUNT = Math.floor(CONST_1.default.OPENAI_POLL_TIMEOUT / CONST_1.default.OPENAI_POLL_RATE); +class OpenAIUtils { + static ai; + static assistantID; + static init(apiKey, assistantID) { + const key = apiKey ?? (0, core_1.getInput)('PROPOSAL_POLICE_API_KEY', { required: true }); + if (!key) { + throw new Error('Could not initialize OpenAI: No key provided.'); + } + this.ai = new openai_1.default({ apiKey: key }); + this.assistantID = assistantID ?? (0, core_1.getInput)('PROPOSAL_POLICE_ASSISTANT_ID', { required: true }); + } + static get openAI() { + if (!this.ai) { + this.init(); + } + return this.ai; + } + static async prompt(userMessage) { + // start a thread run + let threadRun = await this.openAI.beta.threads.createAndRun({ + /* eslint-disable @typescript-eslint/naming-convention */ + assistant_id: this.assistantID, + thread: { messages: [{ role: CONST_1.default.OPENAI_ROLES.USER, content: userMessage }] }, + }); + // poll for run completion + let response = ''; + let count = 0; + while (!response && count < MAX_POLL_COUNT) { + // await thread run completion + threadRun = await this.openAI.beta.threads.runs.retrieve(threadRun.thread_id, threadRun.id); + if (threadRun.status !== CONST_1.default.OPENAI_THREAD_COMPLETED) { + count++; + await new Promise((resolve) => { + setTimeout(resolve, CONST_1.default.OPENAI_POLL_RATE); + }); + continue; + } + for await (const message of this.openAI.beta.threads.messages.list(threadRun.thread_id)) { + if (message.role !== CONST_1.default.OPENAI_ROLES.ASSISTANT) { + continue; + } + response += message.content + .map((contentBlock) => this.isTextContentBlock(contentBlock)) + .join('\n') + .trim(); + console.log('Parsed assistant response:', response); + } + if (!response) { + throw new Error('Assistant response is empty or had no text content. This is unexpected.'); + } + } + return response; + } + static isTextContentBlock(contentBlock) { + return contentBlock?.type === 'text'; + } +} +exports["default"] = OpenAIUtils; + + +/***/ }), + +/***/ 8227: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isEmptyObject = void 0; +function isEmptyObject(obj) { + return Object.keys(obj ?? {}).length === 0; +} +exports.isEmptyObject = isEmptyObject; + + +/***/ }), + +/***/ 7034: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +/** + * This function is an equivalent of _.difference, it takes two arrays and returns the difference between them. + * It returns an array of items that are in the first array but not in the second array. + */ +function arrayDifference(array1, array2) { + return [array1, array2].reduce((a, b) => a.filter((c) => !b.includes(c))); +} +exports["default"] = arrayDifference; + + +/***/ }), + +/***/ 9491: +/***/ ((module) => { + +"use strict"; +module.exports = require("assert"); + +/***/ }), + +/***/ 6113: +/***/ ((module) => { + +"use strict"; +module.exports = require("crypto"); + +/***/ }), + +/***/ 3975: +/***/ ((module) => { + +"use strict"; +module.exports = require("encoding"); + +/***/ }), + +/***/ 2361: +/***/ ((module) => { + +"use strict"; +module.exports = require("events"); + +/***/ }), + +/***/ 7147: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs"); + +/***/ }), + +/***/ 3685: +/***/ ((module) => { + +"use strict"; +module.exports = require("http"); + +/***/ }), + +/***/ 5687: +/***/ ((module) => { + +"use strict"; +module.exports = require("https"); + +/***/ }), + +/***/ 1808: +/***/ ((module) => { + +"use strict"; +module.exports = require("net"); + +/***/ }), + +/***/ 7561: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:fs"); + +/***/ }), + +/***/ 4492: +/***/ ((module) => { + +"use strict"; +module.exports = require("node:stream"); + +/***/ }), + +/***/ 2037: +/***/ ((module) => { + +"use strict"; +module.exports = require("os"); + +/***/ }), + +/***/ 1017: +/***/ ((module) => { + +"use strict"; +module.exports = require("path"); + +/***/ }), + +/***/ 5477: +/***/ ((module) => { + +"use strict"; +module.exports = require("punycode"); + +/***/ }), + +/***/ 2781: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream"); + +/***/ }), + +/***/ 4404: +/***/ ((module) => { + +"use strict"; +module.exports = require("tls"); + +/***/ }), + +/***/ 7310: +/***/ ((module) => { + +"use strict"; +module.exports = require("url"); + +/***/ }), + +/***/ 3837: +/***/ ((module) => { + +"use strict"; +module.exports = require("util"); + +/***/ }), + +/***/ 1267: +/***/ ((module) => { + +"use strict"; +module.exports = require("worker_threads"); + +/***/ }), + +/***/ 9796: +/***/ ((module) => { + +"use strict"; +module.exports = require("zlib"); + +/***/ }), + +/***/ 1778: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); + + +/***/ }), + +/***/ 5860: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _FormDataEncoder_instances, _FormDataEncoder_CRLF, _FormDataEncoder_CRLF_BYTES, _FormDataEncoder_CRLF_BYTES_LENGTH, _FormDataEncoder_DASHES, _FormDataEncoder_encoder, _FormDataEncoder_footer, _FormDataEncoder_form, _FormDataEncoder_options, _FormDataEncoder_getFieldHeader; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Encoder = exports.FormDataEncoder = void 0; +const createBoundary_1 = __importDefault(__nccwpck_require__(7956)); +const isPlainObject_1 = __importDefault(__nccwpck_require__(5240)); +const normalizeValue_1 = __importDefault(__nccwpck_require__(1391)); +const escapeName_1 = __importDefault(__nccwpck_require__(3864)); +const isFileLike_1 = __nccwpck_require__(6860); +const isFormData_1 = __nccwpck_require__(1633); +const defaultOptions = { + enableAdditionalHeaders: false +}; +class FormDataEncoder { + constructor(form, boundaryOrOptions, options) { + _FormDataEncoder_instances.add(this); + _FormDataEncoder_CRLF.set(this, "\r\n"); + _FormDataEncoder_CRLF_BYTES.set(this, void 0); + _FormDataEncoder_CRLF_BYTES_LENGTH.set(this, void 0); + _FormDataEncoder_DASHES.set(this, "-".repeat(2)); + _FormDataEncoder_encoder.set(this, new TextEncoder()); + _FormDataEncoder_footer.set(this, void 0); + _FormDataEncoder_form.set(this, void 0); + _FormDataEncoder_options.set(this, void 0); + if (!(0, isFormData_1.isFormData)(form)) { + throw new TypeError("Expected first argument to be a FormData instance."); + } + let boundary; + if ((0, isPlainObject_1.default)(boundaryOrOptions)) { + options = boundaryOrOptions; + } + else { + boundary = boundaryOrOptions; + } + if (!boundary) { + boundary = (0, createBoundary_1.default)(); + } + if (typeof boundary !== "string") { + throw new TypeError("Expected boundary argument to be a string."); + } + if (options && !(0, isPlainObject_1.default)(options)) { + throw new TypeError("Expected options argument to be an object."); + } + __classPrivateFieldSet(this, _FormDataEncoder_form, form, "f"); + __classPrivateFieldSet(this, _FormDataEncoder_options, { ...defaultOptions, ...options }, "f"); + __classPrivateFieldSet(this, _FormDataEncoder_CRLF_BYTES, __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")), "f"); + __classPrivateFieldSet(this, _FormDataEncoder_CRLF_BYTES_LENGTH, __classPrivateFieldGet(this, _FormDataEncoder_CRLF_BYTES, "f").byteLength, "f"); + this.boundary = `form-data-boundary-${boundary}`; + this.contentType = `multipart/form-data; boundary=${this.boundary}`; + __classPrivateFieldSet(this, _FormDataEncoder_footer, __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(`${__classPrivateFieldGet(this, _FormDataEncoder_DASHES, "f")}${this.boundary}${__classPrivateFieldGet(this, _FormDataEncoder_DASHES, "f")}${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f").repeat(2)}`), "f"); + this.contentLength = String(this.getContentLength()); + this.headers = Object.freeze({ + "Content-Type": this.contentType, + "Content-Length": this.contentLength + }); + Object.defineProperties(this, { + boundary: { writable: false, configurable: false }, + contentType: { writable: false, configurable: false }, + contentLength: { writable: false, configurable: false }, + headers: { writable: false, configurable: false } + }); + } + getContentLength() { + let length = 0; + for (const [name, raw] of __classPrivateFieldGet(this, _FormDataEncoder_form, "f")) { + const value = (0, isFileLike_1.isFileLike)(raw) ? raw : __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode((0, normalizeValue_1.default)(raw)); + length += __classPrivateFieldGet(this, _FormDataEncoder_instances, "m", _FormDataEncoder_getFieldHeader).call(this, name, value).byteLength; + length += (0, isFileLike_1.isFileLike)(value) ? value.size : value.byteLength; + length += __classPrivateFieldGet(this, _FormDataEncoder_CRLF_BYTES_LENGTH, "f"); + } + return length + __classPrivateFieldGet(this, _FormDataEncoder_footer, "f").byteLength; + } + *values() { + for (const [name, raw] of __classPrivateFieldGet(this, _FormDataEncoder_form, "f").entries()) { + const value = (0, isFileLike_1.isFileLike)(raw) ? raw : __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode((0, normalizeValue_1.default)(raw)); + yield __classPrivateFieldGet(this, _FormDataEncoder_instances, "m", _FormDataEncoder_getFieldHeader).call(this, name, value); + yield value; + yield __classPrivateFieldGet(this, _FormDataEncoder_CRLF_BYTES, "f"); + } + yield __classPrivateFieldGet(this, _FormDataEncoder_footer, "f"); + } + async *encode() { + for (const part of this.values()) { + if ((0, isFileLike_1.isFileLike)(part)) { + yield* part.stream(); + } + else { + yield part; + } + } + } + [(_FormDataEncoder_CRLF = new WeakMap(), _FormDataEncoder_CRLF_BYTES = new WeakMap(), _FormDataEncoder_CRLF_BYTES_LENGTH = new WeakMap(), _FormDataEncoder_DASHES = new WeakMap(), _FormDataEncoder_encoder = new WeakMap(), _FormDataEncoder_footer = new WeakMap(), _FormDataEncoder_form = new WeakMap(), _FormDataEncoder_options = new WeakMap(), _FormDataEncoder_instances = new WeakSet(), _FormDataEncoder_getFieldHeader = function _FormDataEncoder_getFieldHeader(name, value) { + let header = ""; + header += `${__classPrivateFieldGet(this, _FormDataEncoder_DASHES, "f")}${this.boundary}${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")}`; + header += `Content-Disposition: form-data; name="${(0, escapeName_1.default)(name)}"`; + if ((0, isFileLike_1.isFileLike)(value)) { + header += `; filename="${(0, escapeName_1.default)(value.name)}"${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")}`; + header += `Content-Type: ${value.type || "application/octet-stream"}`; + } + if (__classPrivateFieldGet(this, _FormDataEncoder_options, "f").enableAdditionalHeaders === true) { + header += `${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f")}Content-Length: ${(0, isFileLike_1.isFileLike)(value) ? value.size : value.byteLength}`; + } + return __classPrivateFieldGet(this, _FormDataEncoder_encoder, "f").encode(`${header}${__classPrivateFieldGet(this, _FormDataEncoder_CRLF, "f").repeat(2)}`); + }, Symbol.iterator)]() { + return this.values(); + } + [Symbol.asyncIterator]() { + return this.encode(); + } +} +exports.FormDataEncoder = FormDataEncoder; +exports.Encoder = FormDataEncoder; + + +/***/ }), + +/***/ 6921: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); + + +/***/ }), + +/***/ 8824: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__nccwpck_require__(5860), exports); +__exportStar(__nccwpck_require__(1778), exports); +__exportStar(__nccwpck_require__(6921), exports); +__exportStar(__nccwpck_require__(6860), exports); +__exportStar(__nccwpck_require__(1633), exports); + + +/***/ }), + +/***/ 7956: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789"; +function createBoundary() { + let size = 16; + let res = ""; + while (size--) { + res += alphabet[(Math.random() * alphabet.length) << 0]; + } + return res; +} +exports["default"] = createBoundary; + + +/***/ }), + +/***/ 3864: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const escapeName = (name) => String(name) + .replace(/\r/g, "%0D") + .replace(/\n/g, "%0A") + .replace(/"/g, "%22"); +exports["default"] = escapeName; + + +/***/ }), + +/***/ 6860: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isFileLike = void 0; +const isFunction_1 = __importDefault(__nccwpck_require__(2498)); +const isFileLike = (value) => Boolean(value + && typeof value === "object" + && (0, isFunction_1.default)(value.constructor) + && value[Symbol.toStringTag] === "File" + && (0, isFunction_1.default)(value.stream) + && value.name != null + && value.size != null + && value.lastModified != null); +exports.isFileLike = isFileLike; + + +/***/ }), + +/***/ 1633: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isFormDataLike = exports.isFormData = void 0; +const isFunction_1 = __importDefault(__nccwpck_require__(2498)); +const isFormData = (value) => Boolean(value + && (0, isFunction_1.default)(value.constructor) + && value[Symbol.toStringTag] === "FormData" + && (0, isFunction_1.default)(value.append) + && (0, isFunction_1.default)(value.getAll) + && (0, isFunction_1.default)(value.entries) + && (0, isFunction_1.default)(value[Symbol.iterator])); +exports.isFormData = isFormData; +exports.isFormDataLike = exports.isFormData; + + +/***/ }), + +/***/ 2498: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const isFunction = (value) => (typeof value === "function"); +exports["default"] = isFunction; + + +/***/ }), + +/***/ 5240: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const getType = (value) => (Object.prototype.toString.call(value).slice(8, -1).toLowerCase()); +function isPlainObject(value) { + if (getType(value) !== "object") { + return false; + } + const pp = Object.getPrototypeOf(value); + if (pp === null || pp === undefined) { + return true; + } + const Ctor = pp.constructor && pp.constructor.toString(); + return Ctor === Object.toString(); +} +exports["default"] = isPlainObject; + + +/***/ }), + +/***/ 1391: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const normalizeValue = (value) => String(value) + .replace(/\r|\n/g, (match, i, str) => { + if ((match === "\r" && str[i + 1] !== "\n") + || (match === "\n" && str[i - 1] !== "\r")) { + return "\r\n"; + } + return match; +}); +exports["default"] = normalizeValue; + + +/***/ }), + +/***/ 6637: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +/*! Based on fetch-blob. MIT License. Jimmy WƤrting & David Frank */ +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _Blob_parts, _Blob_type, _Blob_size; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Blob = void 0; +const web_streams_polyfill_1 = __nccwpck_require__(6993); +const isFunction_1 = __nccwpck_require__(4245); +const blobHelpers_1 = __nccwpck_require__(7058); +class Blob { + constructor(blobParts = [], options = {}) { + _Blob_parts.set(this, []); + _Blob_type.set(this, ""); + _Blob_size.set(this, 0); + options !== null && options !== void 0 ? options : (options = {}); + if (typeof blobParts !== "object" || blobParts === null) { + throw new TypeError("Failed to construct 'Blob': " + + "The provided value cannot be converted to a sequence."); + } + if (!(0, isFunction_1.isFunction)(blobParts[Symbol.iterator])) { + throw new TypeError("Failed to construct 'Blob': " + + "The object must have a callable @@iterator property."); + } + if (typeof options !== "object" && !(0, isFunction_1.isFunction)(options)) { + throw new TypeError("Failed to construct 'Blob': parameter 2 cannot convert to dictionary."); + } + const encoder = new TextEncoder(); + for (const raw of blobParts) { + let part; + if (ArrayBuffer.isView(raw)) { + part = new Uint8Array(raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength)); + } + else if (raw instanceof ArrayBuffer) { + part = new Uint8Array(raw.slice(0)); + } + else if (raw instanceof Blob) { + part = raw; + } + else { + part = encoder.encode(String(raw)); + } + __classPrivateFieldSet(this, _Blob_size, __classPrivateFieldGet(this, _Blob_size, "f") + (ArrayBuffer.isView(part) ? part.byteLength : part.size), "f"); + __classPrivateFieldGet(this, _Blob_parts, "f").push(part); + } + const type = options.type === undefined ? "" : String(options.type); + __classPrivateFieldSet(this, _Blob_type, /^[\x20-\x7E]*$/.test(type) ? type : "", "f"); + } + static [(_Blob_parts = new WeakMap(), _Blob_type = new WeakMap(), _Blob_size = new WeakMap(), Symbol.hasInstance)](value) { + return Boolean(value + && typeof value === "object" + && (0, isFunction_1.isFunction)(value.constructor) + && ((0, isFunction_1.isFunction)(value.stream) + || (0, isFunction_1.isFunction)(value.arrayBuffer)) + && /^(Blob|File)$/.test(value[Symbol.toStringTag])); + } + get type() { + return __classPrivateFieldGet(this, _Blob_type, "f"); + } + get size() { + return __classPrivateFieldGet(this, _Blob_size, "f"); + } + slice(start, end, contentType) { + return new Blob((0, blobHelpers_1.sliceBlob)(__classPrivateFieldGet(this, _Blob_parts, "f"), this.size, start, end), { + type: contentType + }); + } + async text() { + const decoder = new TextDecoder(); + let result = ""; + for await (const chunk of (0, blobHelpers_1.consumeBlobParts)(__classPrivateFieldGet(this, _Blob_parts, "f"))) { + result += decoder.decode(chunk, { stream: true }); + } + result += decoder.decode(); + return result; + } + async arrayBuffer() { + const view = new Uint8Array(this.size); + let offset = 0; + for await (const chunk of (0, blobHelpers_1.consumeBlobParts)(__classPrivateFieldGet(this, _Blob_parts, "f"))) { + view.set(chunk, offset); + offset += chunk.length; + } + return view.buffer; + } + stream() { + const iterator = (0, blobHelpers_1.consumeBlobParts)(__classPrivateFieldGet(this, _Blob_parts, "f"), true); + return new web_streams_polyfill_1.ReadableStream({ + async pull(controller) { + const { value, done } = await iterator.next(); + if (done) { + return queueMicrotask(() => controller.close()); + } + controller.enqueue(value); + }, + async cancel() { + await iterator.return(); + } + }); + } + get [Symbol.toStringTag]() { + return "Blob"; + } +} +exports.Blob = Blob; +Object.defineProperties(Blob.prototype, { + type: { enumerable: true }, + size: { enumerable: true }, + slice: { enumerable: true }, + stream: { enumerable: true }, + text: { enumerable: true }, + arrayBuffer: { enumerable: true } +}); + + +/***/ }), + +/***/ 3637: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _File_name, _File_lastModified; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.File = void 0; +const Blob_1 = __nccwpck_require__(6637); +class File extends Blob_1.Blob { + constructor(fileBits, name, options = {}) { + super(fileBits, options); + _File_name.set(this, void 0); + _File_lastModified.set(this, 0); + if (arguments.length < 2) { + throw new TypeError("Failed to construct 'File': 2 arguments required, " + + `but only ${arguments.length} present.`); + } + __classPrivateFieldSet(this, _File_name, String(name), "f"); + const lastModified = options.lastModified === undefined + ? Date.now() + : Number(options.lastModified); + if (!Number.isNaN(lastModified)) { + __classPrivateFieldSet(this, _File_lastModified, lastModified, "f"); + } + } + static [(_File_name = new WeakMap(), _File_lastModified = new WeakMap(), Symbol.hasInstance)](value) { + return value instanceof Blob_1.Blob + && value[Symbol.toStringTag] === "File" + && typeof value.name === "string"; + } + get name() { + return __classPrivateFieldGet(this, _File_name, "f"); + } + get lastModified() { + return __classPrivateFieldGet(this, _File_lastModified, "f"); + } + get webkitRelativePath() { + return ""; + } + get [Symbol.toStringTag]() { + return "File"; + } +} +exports.File = File; + + +/***/ }), + +/***/ 7268: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _FormData_instances, _FormData_entries, _FormData_setEntry; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.FormData = void 0; +const util_1 = __nccwpck_require__(3837); +const File_1 = __nccwpck_require__(3637); +const isFile_1 = __nccwpck_require__(4529); +const isBlob_1 = __nccwpck_require__(5493); +const isFunction_1 = __nccwpck_require__(4245); +const deprecateConstructorEntries_1 = __nccwpck_require__(2689); +class FormData { + constructor(entries) { + _FormData_instances.add(this); + _FormData_entries.set(this, new Map()); + if (entries) { + (0, deprecateConstructorEntries_1.deprecateConstructorEntries)(); + entries.forEach(({ name, value, fileName }) => this.append(name, value, fileName)); + } + } + static [(_FormData_entries = new WeakMap(), _FormData_instances = new WeakSet(), Symbol.hasInstance)](value) { + return Boolean(value + && (0, isFunction_1.isFunction)(value.constructor) + && value[Symbol.toStringTag] === "FormData" + && (0, isFunction_1.isFunction)(value.append) + && (0, isFunction_1.isFunction)(value.set) + && (0, isFunction_1.isFunction)(value.get) + && (0, isFunction_1.isFunction)(value.getAll) + && (0, isFunction_1.isFunction)(value.has) + && (0, isFunction_1.isFunction)(value.delete) + && (0, isFunction_1.isFunction)(value.entries) + && (0, isFunction_1.isFunction)(value.values) + && (0, isFunction_1.isFunction)(value.keys) + && (0, isFunction_1.isFunction)(value[Symbol.iterator]) + && (0, isFunction_1.isFunction)(value.forEach)); + } + append(name, value, fileName) { + __classPrivateFieldGet(this, _FormData_instances, "m", _FormData_setEntry).call(this, { + name, + fileName, + append: true, + rawValue: value, + argsLength: arguments.length + }); + } + set(name, value, fileName) { + __classPrivateFieldGet(this, _FormData_instances, "m", _FormData_setEntry).call(this, { + name, + fileName, + append: false, + rawValue: value, + argsLength: arguments.length + }); + } + get(name) { + const field = __classPrivateFieldGet(this, _FormData_entries, "f").get(String(name)); + if (!field) { + return null; + } + return field[0]; + } + getAll(name) { + const field = __classPrivateFieldGet(this, _FormData_entries, "f").get(String(name)); + if (!field) { + return []; + } + return field.slice(); + } + has(name) { + return __classPrivateFieldGet(this, _FormData_entries, "f").has(String(name)); + } + delete(name) { + __classPrivateFieldGet(this, _FormData_entries, "f").delete(String(name)); + } + *keys() { + for (const key of __classPrivateFieldGet(this, _FormData_entries, "f").keys()) { + yield key; + } + } + *entries() { + for (const name of this.keys()) { + const values = this.getAll(name); + for (const value of values) { + yield [name, value]; + } + } + } + *values() { + for (const [, value] of this) { + yield value; + } + } + [(_FormData_setEntry = function _FormData_setEntry({ name, rawValue, append, fileName, argsLength }) { + const methodName = append ? "append" : "set"; + if (argsLength < 2) { + throw new TypeError(`Failed to execute '${methodName}' on 'FormData': ` + + `2 arguments required, but only ${argsLength} present.`); + } + name = String(name); + let value; + if ((0, isFile_1.isFile)(rawValue)) { + value = fileName === undefined + ? rawValue + : new File_1.File([rawValue], fileName, { + type: rawValue.type, + lastModified: rawValue.lastModified + }); + } + else if ((0, isBlob_1.isBlob)(rawValue)) { + value = new File_1.File([rawValue], fileName === undefined ? "blob" : fileName, { + type: rawValue.type + }); + } + else if (fileName) { + throw new TypeError(`Failed to execute '${methodName}' on 'FormData': ` + + "parameter 2 is not of type 'Blob'."); + } + else { + value = String(rawValue); + } + const values = __classPrivateFieldGet(this, _FormData_entries, "f").get(name); + if (!values) { + return void __classPrivateFieldGet(this, _FormData_entries, "f").set(name, [value]); + } + if (!append) { + return void __classPrivateFieldGet(this, _FormData_entries, "f").set(name, [value]); + } + values.push(value); + }, Symbol.iterator)]() { + return this.entries(); + } + forEach(callback, thisArg) { + for (const [name, value] of this) { + callback.call(thisArg, value, name, this); + } + } + get [Symbol.toStringTag]() { + return "FormData"; + } + [util_1.inspect.custom]() { + return this[Symbol.toStringTag]; + } +} +exports.FormData = FormData; + + +/***/ }), + +/***/ 7058: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +/*! Based on fetch-blob. MIT License. Jimmy WƤrting & David Frank */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.sliceBlob = exports.consumeBlobParts = void 0; +const isFunction_1 = __nccwpck_require__(4245); +const CHUNK_SIZE = 65536; +async function* clonePart(part) { + const end = part.byteOffset + part.byteLength; + let position = part.byteOffset; + while (position !== end) { + const size = Math.min(end - position, CHUNK_SIZE); + const chunk = part.buffer.slice(position, position + size); + position += chunk.byteLength; + yield new Uint8Array(chunk); + } +} +async function* consumeNodeBlob(blob) { + let position = 0; + while (position !== blob.size) { + const chunk = blob.slice(position, Math.min(blob.size, position + CHUNK_SIZE)); + const buffer = await chunk.arrayBuffer(); + position += buffer.byteLength; + yield new Uint8Array(buffer); + } +} +async function* consumeBlobParts(parts, clone = false) { + for (const part of parts) { + if (ArrayBuffer.isView(part)) { + if (clone) { + yield* clonePart(part); + } + else { + yield part; + } + } + else if ((0, isFunction_1.isFunction)(part.stream)) { + yield* part.stream(); + } + else { + yield* consumeNodeBlob(part); + } + } +} +exports.consumeBlobParts = consumeBlobParts; +function* sliceBlob(blobParts, blobSize, start = 0, end) { + end !== null && end !== void 0 ? end : (end = blobSize); + let relativeStart = start < 0 + ? Math.max(blobSize + start, 0) + : Math.min(start, blobSize); + let relativeEnd = end < 0 + ? Math.max(blobSize + end, 0) + : Math.min(end, blobSize); + const span = Math.max(relativeEnd - relativeStart, 0); + let added = 0; + for (const part of blobParts) { + if (added >= span) { + break; + } + const partSize = ArrayBuffer.isView(part) ? part.byteLength : part.size; + if (relativeStart && partSize <= relativeStart) { + relativeStart -= partSize; + relativeEnd -= partSize; + } + else { + let chunk; + if (ArrayBuffer.isView(part)) { + chunk = part.subarray(relativeStart, Math.min(partSize, relativeEnd)); + added += chunk.byteLength; + } + else { + chunk = part.slice(relativeStart, Math.min(partSize, relativeEnd)); + added += chunk.size; + } + relativeEnd -= partSize; + relativeStart = 0; + yield chunk; + } + } +} +exports.sliceBlob = sliceBlob; + + +/***/ }), + +/***/ 2689: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.deprecateConstructorEntries = void 0; +const util_1 = __nccwpck_require__(3837); +exports.deprecateConstructorEntries = (0, util_1.deprecate)(() => { }, "Constructor \"entries\" argument is not spec-compliant " + + "and will be removed in next major release."); + + +/***/ }), + +/***/ 8735: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +var _FileFromPath_path, _FileFromPath_start; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.fileFromPath = exports.fileFromPathSync = void 0; +const fs_1 = __nccwpck_require__(7147); +const path_1 = __nccwpck_require__(1017); +const node_domexception_1 = __importDefault(__nccwpck_require__(7760)); +const File_1 = __nccwpck_require__(3637); +const isPlainObject_1 = __importDefault(__nccwpck_require__(4722)); +__exportStar(__nccwpck_require__(4529), exports); +const MESSAGE = "The requested file could not be read, " + + "typically due to permission problems that have occurred after a reference " + + "to a file was acquired."; +class FileFromPath { + constructor(input) { + _FileFromPath_path.set(this, void 0); + _FileFromPath_start.set(this, void 0); + __classPrivateFieldSet(this, _FileFromPath_path, input.path, "f"); + __classPrivateFieldSet(this, _FileFromPath_start, input.start || 0, "f"); + this.name = (0, path_1.basename)(__classPrivateFieldGet(this, _FileFromPath_path, "f")); + this.size = input.size; + this.lastModified = input.lastModified; + } + slice(start, end) { + return new FileFromPath({ + path: __classPrivateFieldGet(this, _FileFromPath_path, "f"), + lastModified: this.lastModified, + size: end - start, + start + }); + } + async *stream() { + const { mtimeMs } = await fs_1.promises.stat(__classPrivateFieldGet(this, _FileFromPath_path, "f")); + if (mtimeMs > this.lastModified) { + throw new node_domexception_1.default(MESSAGE, "NotReadableError"); + } + if (this.size) { + yield* (0, fs_1.createReadStream)(__classPrivateFieldGet(this, _FileFromPath_path, "f"), { + start: __classPrivateFieldGet(this, _FileFromPath_start, "f"), + end: __classPrivateFieldGet(this, _FileFromPath_start, "f") + this.size - 1 + }); + } + } + get [(_FileFromPath_path = new WeakMap(), _FileFromPath_start = new WeakMap(), Symbol.toStringTag)]() { + return "File"; + } +} +function createFileFromPath(path, { mtimeMs, size }, filenameOrOptions, options = {}) { + let filename; + if ((0, isPlainObject_1.default)(filenameOrOptions)) { + [options, filename] = [filenameOrOptions, undefined]; + } + else { + filename = filenameOrOptions; + } + const file = new FileFromPath({ path, size, lastModified: mtimeMs }); + if (!filename) { + filename = file.name; + } + return new File_1.File([file], filename, { + ...options, lastModified: file.lastModified + }); +} +function fileFromPathSync(path, filenameOrOptions, options = {}) { + const stats = (0, fs_1.statSync)(path); + return createFileFromPath(path, stats, filenameOrOptions, options); +} +exports.fileFromPathSync = fileFromPathSync; +async function fileFromPath(path, filenameOrOptions, options) { + const stats = await fs_1.promises.stat(path); + return createFileFromPath(path, stats, filenameOrOptions, options); +} +exports.fileFromPath = fileFromPath; + + +/***/ }), + +/***/ 880: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +__exportStar(__nccwpck_require__(7268), exports); +__exportStar(__nccwpck_require__(6637), exports); +__exportStar(__nccwpck_require__(3637), exports); + + +/***/ }), + +/***/ 5493: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isBlob = void 0; +const Blob_1 = __nccwpck_require__(6637); +const isBlob = (value) => value instanceof Blob_1.Blob; +exports.isBlob = isBlob; + + +/***/ }), + +/***/ 4529: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isFile = void 0; +const File_1 = __nccwpck_require__(3637); +const isFile = (value) => value instanceof File_1.File; +exports.isFile = isFile; + + +/***/ }), + +/***/ 4245: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isFunction = void 0; +const isFunction = (value) => (typeof value === "function"); +exports.isFunction = isFunction; + + +/***/ }), + +/***/ 4722: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +const getType = (value) => (Object.prototype.toString.call(value).slice(8, -1).toLowerCase()); +function isPlainObject(value) { + if (getType(value) !== "object") { + return false; + } + const pp = Object.getPrototypeOf(value); + if (pp === null || pp === undefined) { + return true; + } + const Ctor = pp.constructor && pp.constructor.toString(); + return Ctor === Object.toString(); +} +exports["default"] = isPlainObject; + + +/***/ }), + +/***/ 4595: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.MultipartBody = void 0; +/** + * Disclaimer: modules in _shims aren't intended to be imported by SDK users. + */ +class MultipartBody { + constructor(body) { + this.body = body; + } + get [Symbol.toStringTag]() { + return 'MultipartBody'; + } +} +exports.MultipartBody = MultipartBody; +//# sourceMappingURL=MultipartBody.js.map + +/***/ }), + +/***/ 3506: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +/** + * Disclaimer: modules in _shims aren't intended to be imported by SDK users. + */ +__exportStar(__nccwpck_require__(1749), exports); +//# sourceMappingURL=runtime-node.js.map + +/***/ }), + +/***/ 6678: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +/** + * Disclaimer: modules in _shims aren't intended to be imported by SDK users. + */ +const shims = __nccwpck_require__(4437); +const auto = __nccwpck_require__(3506); +if (!shims.kind) shims.setShims(auto.getRuntime(), { auto: true }); +for (const property of Object.keys(shims)) { + Object.defineProperty(exports, property, { + get() { + return shims[property]; + }, + }); +} + + +/***/ }), + +/***/ 1749: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.getRuntime = void 0; +/** + * Disclaimer: modules in _shims aren't intended to be imported by SDK users. + */ +const nf = __importStar(__nccwpck_require__(467)); +const fd = __importStar(__nccwpck_require__(880)); +const agentkeepalive_1 = __importDefault(__nccwpck_require__(4623)); +const abort_controller_1 = __nccwpck_require__(1659); +const node_fs_1 = __nccwpck_require__(7561); +const form_data_encoder_1 = __nccwpck_require__(8824); +const node_stream_1 = __nccwpck_require__(4492); +const MultipartBody_1 = __nccwpck_require__(4595); +// @ts-ignore (this package does not have proper export maps for this export) +const ponyfill_es2018_js_1 = __nccwpck_require__(1452); +let fileFromPathWarned = false; +async function fileFromPath(path, ...args) { + // this import fails in environments that don't handle export maps correctly, like old versions of Jest + const { fileFromPath: _fileFromPath } = await Promise.resolve().then(() => __importStar(__nccwpck_require__(8735))); + if (!fileFromPathWarned) { + console.warn(`fileFromPath is deprecated; use fs.createReadStream(${JSON.stringify(path)}) instead`); + fileFromPathWarned = true; + } + // @ts-ignore + return await _fileFromPath(path, ...args); +} +const defaultHttpAgent = new agentkeepalive_1.default({ keepAlive: true, timeout: 5 * 60 * 1000 }); +const defaultHttpsAgent = new agentkeepalive_1.default.HttpsAgent({ keepAlive: true, timeout: 5 * 60 * 1000 }); +async function getMultipartRequestOptions(form, opts) { + const encoder = new form_data_encoder_1.FormDataEncoder(form); + const readable = node_stream_1.Readable.from(encoder); + const body = new MultipartBody_1.MultipartBody(readable); + const headers = { + ...opts.headers, + ...encoder.headers, + 'Content-Length': encoder.contentLength, + }; + return { ...opts, body: body, headers }; +} +function getRuntime() { + // Polyfill global object if needed. + if (typeof AbortController === 'undefined') { + // @ts-expect-error (the types are subtly different, but compatible in practice) + globalThis.AbortController = abort_controller_1.AbortController; + } + return { + kind: 'node', + fetch: nf.default, + Request: nf.Request, + Response: nf.Response, + Headers: nf.Headers, + FormData: fd.FormData, + Blob: fd.Blob, + File: fd.File, + ReadableStream: ponyfill_es2018_js_1.ReadableStream, + getMultipartRequestOptions, + getDefaultAgent: (url) => (url.startsWith('https') ? defaultHttpsAgent : defaultHttpAgent), + fileFromPath, + isFsReadStream: (value) => value instanceof node_fs_1.ReadStream, + }; +} +exports.getRuntime = getRuntime; +//# sourceMappingURL=node-runtime.js.map + +/***/ }), + +/***/ 4437: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.setShims = exports.isFsReadStream = exports.fileFromPath = exports.getDefaultAgent = exports.getMultipartRequestOptions = exports.ReadableStream = exports.File = exports.Blob = exports.FormData = exports.Headers = exports.Response = exports.Request = exports.fetch = exports.kind = exports.auto = void 0; +exports.auto = false; +exports.kind = undefined; +exports.fetch = undefined; +exports.Request = undefined; +exports.Response = undefined; +exports.Headers = undefined; +exports.FormData = undefined; +exports.Blob = undefined; +exports.File = undefined; +exports.ReadableStream = undefined; +exports.getMultipartRequestOptions = undefined; +exports.getDefaultAgent = undefined; +exports.fileFromPath = undefined; +exports.isFsReadStream = undefined; +function setShims(shims, options = { auto: false }) { + if (exports.auto) { + throw new Error(`you must \`import 'openai/shims/${shims.kind}'\` before importing anything else from openai`); + } + if (exports.kind) { + throw new Error(`can't \`import 'openai/shims/${shims.kind}'\` after \`import 'openai/shims/${exports.kind}'\``); + } + exports.auto = options.auto; + exports.kind = shims.kind; + exports.fetch = shims.fetch; + exports.Request = shims.Request; + exports.Response = shims.Response; + exports.Headers = shims.Headers; + exports.FormData = shims.FormData; + exports.Blob = shims.Blob; + exports.File = shims.File; + exports.ReadableStream = shims.ReadableStream; + exports.getMultipartRequestOptions = shims.getMultipartRequestOptions; + exports.getDefaultAgent = shims.getDefaultAgent; + exports.fileFromPath = shims.fileFromPath; + exports.isFsReadStream = shims.isFsReadStream; +} +exports.setShims = setShims; +//# sourceMappingURL=registry.js.map + +/***/ }), + +/***/ 1798: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _AbstractPage_client; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isObj = exports.toBase64 = exports.getRequiredHeader = exports.isHeadersProtocol = exports.isRunningInBrowser = exports.debug = exports.hasOwn = exports.isEmptyObj = exports.maybeCoerceBoolean = exports.maybeCoerceFloat = exports.maybeCoerceInteger = exports.coerceBoolean = exports.coerceFloat = exports.coerceInteger = exports.readEnv = exports.ensurePresent = exports.castToError = exports.sleep = exports.safeJSON = exports.isRequestOptions = exports.createResponseHeaders = exports.PagePromise = exports.AbstractPage = exports.APIClient = exports.APIPromise = exports.createForm = exports.multipartFormRequestOptions = exports.maybeMultipartFormRequestOptions = void 0; +const version_1 = __nccwpck_require__(6417); +const streaming_1 = __nccwpck_require__(884); +const error_1 = __nccwpck_require__(8905); +const index_1 = __nccwpck_require__(6678); +const uploads_1 = __nccwpck_require__(3394); +var uploads_2 = __nccwpck_require__(3394); +Object.defineProperty(exports, "maybeMultipartFormRequestOptions", ({ enumerable: true, get: function () { return uploads_2.maybeMultipartFormRequestOptions; } })); +Object.defineProperty(exports, "multipartFormRequestOptions", ({ enumerable: true, get: function () { return uploads_2.multipartFormRequestOptions; } })); +Object.defineProperty(exports, "createForm", ({ enumerable: true, get: function () { return uploads_2.createForm; } })); +async function defaultParseResponse(props) { + const { response } = props; + if (props.options.stream) { + debug('response', response.status, response.url, response.headers, response.body); + // Note: there is an invariant here that isn't represented in the type system + // that if you set `stream: true` the response type must also be `Stream` + if (props.options.__streamClass) { + return props.options.__streamClass.fromSSEResponse(response, props.controller); + } + return streaming_1.Stream.fromSSEResponse(response, props.controller); + } + // fetch refuses to read the body when the status code is 204. + if (response.status === 204) { + return null; + } + if (props.options.__binaryResponse) { + return response; + } + const contentType = response.headers.get('content-type'); + const isJSON = contentType?.includes('application/json') || contentType?.includes('application/vnd.api+json'); + if (isJSON) { + const json = await response.json(); + debug('response', response.status, response.url, response.headers, json); + return json; + } + const text = await response.text(); + debug('response', response.status, response.url, response.headers, text); + // TODO handle blob, arraybuffer, other content types, etc. + return text; +} +/** + * A subclass of `Promise` providing additional helper methods + * for interacting with the SDK. + */ +class APIPromise extends Promise { + constructor(responsePromise, parseResponse = defaultParseResponse) { + super((resolve) => { + // this is maybe a bit weird but this has to be a no-op to not implicitly + // parse the response body; instead .then, .catch, .finally are overridden + // to parse the response + resolve(null); + }); + this.responsePromise = responsePromise; + this.parseResponse = parseResponse; + } + _thenUnwrap(transform) { + return new APIPromise(this.responsePromise, async (props) => transform(await this.parseResponse(props))); + } + /** + * Gets the raw `Response` instance instead of parsing the response + * data. + * + * If you want to parse the response body but still get the `Response` + * instance, you can use {@link withResponse()}. + * + * šŸ‘‹ Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` if you can, + * or add one of these imports before your first `import ā€¦ from 'openai'`: + * - `import 'openai/shims/node'` (if you're running on Node) + * - `import 'openai/shims/web'` (otherwise) + */ + asResponse() { + return this.responsePromise.then((p) => p.response); + } + /** + * Gets the parsed response data and the raw `Response` instance. + * + * If you just want to get the raw `Response` instance without parsing it, + * you can use {@link asResponse()}. + * + * + * šŸ‘‹ Getting the wrong TypeScript type for `Response`? + * Try setting `"moduleResolution": "NodeNext"` if you can, + * or add one of these imports before your first `import ā€¦ from 'openai'`: + * - `import 'openai/shims/node'` (if you're running on Node) + * - `import 'openai/shims/web'` (otherwise) + */ + async withResponse() { + const [data, response] = await Promise.all([this.parse(), this.asResponse()]); + return { data, response }; + } + parse() { + if (!this.parsedPromise) { + this.parsedPromise = this.responsePromise.then(this.parseResponse); + } + return this.parsedPromise; + } + then(onfulfilled, onrejected) { + return this.parse().then(onfulfilled, onrejected); + } + catch(onrejected) { + return this.parse().catch(onrejected); + } + finally(onfinally) { + return this.parse().finally(onfinally); + } +} +exports.APIPromise = APIPromise; +class APIClient { + constructor({ baseURL, maxRetries = 2, timeout = 600000, // 10 minutes + httpAgent, fetch: overridenFetch, }) { + this.baseURL = baseURL; + this.maxRetries = validatePositiveInteger('maxRetries', maxRetries); + this.timeout = validatePositiveInteger('timeout', timeout); + this.httpAgent = httpAgent; + this.fetch = overridenFetch ?? index_1.fetch; + } + authHeaders(opts) { + return {}; + } + /** + * Override this to add your own default headers, for example: + * + * { + * ...super.defaultHeaders(), + * Authorization: 'Bearer 123', + * } + */ + defaultHeaders(opts) { + return { + Accept: 'application/json', + 'Content-Type': 'application/json', + 'User-Agent': this.getUserAgent(), + ...getPlatformHeaders(), + ...this.authHeaders(opts), + }; + } + /** + * Override this to add your own headers validation: + */ + validateHeaders(headers, customHeaders) { } + defaultIdempotencyKey() { + return `stainless-node-retry-${uuid4()}`; + } + get(path, opts) { + return this.methodRequest('get', path, opts); + } + post(path, opts) { + return this.methodRequest('post', path, opts); + } + patch(path, opts) { + return this.methodRequest('patch', path, opts); + } + put(path, opts) { + return this.methodRequest('put', path, opts); + } + delete(path, opts) { + return this.methodRequest('delete', path, opts); + } + methodRequest(method, path, opts) { + return this.request(Promise.resolve(opts).then((opts) => ({ method, path, ...opts }))); + } + getAPIList(path, Page, opts) { + return this.requestAPIList(Page, { method: 'get', path, ...opts }); + } + calculateContentLength(body) { + if (typeof body === 'string') { + if (typeof Buffer !== 'undefined') { + return Buffer.byteLength(body, 'utf8').toString(); + } + if (typeof TextEncoder !== 'undefined') { + const encoder = new TextEncoder(); + const encoded = encoder.encode(body); + return encoded.length.toString(); + } + } + return null; + } + buildRequest(options) { + const { method, path, query, headers: headers = {} } = options; + const body = (0, uploads_1.isMultipartBody)(options.body) ? options.body.body + : options.body ? JSON.stringify(options.body, null, 2) + : null; + const contentLength = this.calculateContentLength(body); + const url = this.buildURL(path, query); + if ('timeout' in options) + validatePositiveInteger('timeout', options.timeout); + const timeout = options.timeout ?? this.timeout; + const httpAgent = options.httpAgent ?? this.httpAgent ?? (0, index_1.getDefaultAgent)(url); + const minAgentTimeout = timeout + 1000; + if (typeof httpAgent?.options?.timeout === 'number' && + minAgentTimeout > (httpAgent.options.timeout ?? 0)) { + // Allow any given request to bump our agent active socket timeout. + // This may seem strange, but leaking active sockets should be rare and not particularly problematic, + // and without mutating agent we would need to create more of them. + // This tradeoff optimizes for performance. + httpAgent.options.timeout = minAgentTimeout; + } + if (this.idempotencyHeader && method !== 'get') { + if (!options.idempotencyKey) + options.idempotencyKey = this.defaultIdempotencyKey(); + headers[this.idempotencyHeader] = options.idempotencyKey; + } + const reqHeaders = this.buildHeaders({ options, headers, contentLength }); + const req = { + method, + ...(body && { body: body }), + headers: reqHeaders, + ...(httpAgent && { agent: httpAgent }), + // @ts-ignore node-fetch uses a custom AbortSignal type that is + // not compatible with standard web types + signal: options.signal ?? null, + }; + return { req, url, timeout }; + } + buildHeaders({ options, headers, contentLength, }) { + const reqHeaders = {}; + if (contentLength) { + reqHeaders['content-length'] = contentLength; + } + const defaultHeaders = this.defaultHeaders(options); + applyHeadersMut(reqHeaders, defaultHeaders); + applyHeadersMut(reqHeaders, headers); + // let builtin fetch set the Content-Type for multipart bodies + if ((0, uploads_1.isMultipartBody)(options.body) && index_1.kind !== 'node') { + delete reqHeaders['content-type']; + } + this.validateHeaders(reqHeaders, headers); + return reqHeaders; + } + /** + * Used as a callback for mutating the given `FinalRequestOptions` object. + */ + async prepareOptions(options) { } + /** + * Used as a callback for mutating the given `RequestInit` object. + * + * This is useful for cases where you want to add certain headers based off of + * the request properties, e.g. `method` or `url`. + */ + async prepareRequest(request, { url, options }) { } + parseHeaders(headers) { + return (!headers ? {} + : Symbol.iterator in headers ? + Object.fromEntries(Array.from(headers).map((header) => [...header])) + : { ...headers }); + } + makeStatusError(status, error, message, headers) { + return error_1.APIError.generate(status, error, message, headers); + } + request(options, remainingRetries = null) { + return new APIPromise(this.makeRequest(options, remainingRetries)); + } + async makeRequest(optionsInput, retriesRemaining) { + const options = await optionsInput; + if (retriesRemaining == null) { + retriesRemaining = options.maxRetries ?? this.maxRetries; + } + await this.prepareOptions(options); + const { req, url, timeout } = this.buildRequest(options); + await this.prepareRequest(req, { url, options }); + debug('request', url, options, req.headers); + if (options.signal?.aborted) { + throw new error_1.APIUserAbortError(); + } + const controller = new AbortController(); + const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(exports.castToError); + if (response instanceof Error) { + if (options.signal?.aborted) { + throw new error_1.APIUserAbortError(); + } + if (retriesRemaining) { + return this.retryRequest(options, retriesRemaining); + } + if (response.name === 'AbortError') { + throw new error_1.APIConnectionTimeoutError(); + } + throw new error_1.APIConnectionError({ cause: response }); + } + const responseHeaders = (0, exports.createResponseHeaders)(response.headers); + if (!response.ok) { + if (retriesRemaining && this.shouldRetry(response)) { + const retryMessage = `retrying, ${retriesRemaining} attempts remaining`; + debug(`response (error; ${retryMessage})`, response.status, url, responseHeaders); + return this.retryRequest(options, retriesRemaining, responseHeaders); + } + const errText = await response.text().catch((e) => (0, exports.castToError)(e).message); + const errJSON = (0, exports.safeJSON)(errText); + const errMessage = errJSON ? undefined : errText; + const retryMessage = retriesRemaining ? `(error; no more retries left)` : `(error; not retryable)`; + debug(`response (error; ${retryMessage})`, response.status, url, responseHeaders, errMessage); + const err = this.makeStatusError(response.status, errJSON, errMessage, responseHeaders); + throw err; + } + return { response, options, controller }; + } + requestAPIList(Page, options) { + const request = this.makeRequest(options, null); + return new PagePromise(this, request, Page); + } + buildURL(path, query) { + const url = isAbsoluteURL(path) ? + new URL(path) + : new URL(this.baseURL + (this.baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path)); + const defaultQuery = this.defaultQuery(); + if (!isEmptyObj(defaultQuery)) { + query = { ...defaultQuery, ...query }; + } + if (typeof query === 'object' && query && !Array.isArray(query)) { + url.search = this.stringifyQuery(query); + } + return url.toString(); + } + stringifyQuery(query) { + return Object.entries(query) + .filter(([_, value]) => typeof value !== 'undefined') + .map(([key, value]) => { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`; + } + if (value === null) { + return `${encodeURIComponent(key)}=`; + } + throw new error_1.OpenAIError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`); + }) + .join('&'); + } + async fetchWithTimeout(url, init, ms, controller) { + const { signal, ...options } = init || {}; + if (signal) + signal.addEventListener('abort', () => controller.abort()); + const timeout = setTimeout(() => controller.abort(), ms); + return (this.getRequestClient() + // use undefined this binding; fetch errors if bound to something else in browser/cloudflare + .fetch.call(undefined, url, { signal: controller.signal, ...options }) + .finally(() => { + clearTimeout(timeout); + })); + } + getRequestClient() { + return { fetch: this.fetch }; + } + shouldRetry(response) { + // Note this is not a standard header. + const shouldRetryHeader = response.headers.get('x-should-retry'); + // If the server explicitly says whether or not to retry, obey. + if (shouldRetryHeader === 'true') + return true; + if (shouldRetryHeader === 'false') + return false; + // Retry on request timeouts. + if (response.status === 408) + return true; + // Retry on lock timeouts. + if (response.status === 409) + return true; + // Retry on rate limits. + if (response.status === 429) + return true; + // Retry internal errors. + if (response.status >= 500) + return true; + return false; + } + async retryRequest(options, retriesRemaining, responseHeaders) { + let timeoutMillis; + // Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it. + const retryAfterMillisHeader = responseHeaders?.['retry-after-ms']; + if (retryAfterMillisHeader) { + const timeoutMs = parseFloat(retryAfterMillisHeader); + if (!Number.isNaN(timeoutMs)) { + timeoutMillis = timeoutMs; + } + } + // About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After + const retryAfterHeader = responseHeaders?.['retry-after']; + if (retryAfterHeader && !timeoutMillis) { + const timeoutSeconds = parseFloat(retryAfterHeader); + if (!Number.isNaN(timeoutSeconds)) { + timeoutMillis = timeoutSeconds * 1000; + } + else { + timeoutMillis = Date.parse(retryAfterHeader) - Date.now(); + } + } + // If the API asks us to wait a certain amount of time (and it's a reasonable amount), + // just do what it says, but otherwise calculate a default + if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) { + const maxRetries = options.maxRetries ?? this.maxRetries; + timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries); + } + await (0, exports.sleep)(timeoutMillis); + return this.makeRequest(options, retriesRemaining - 1); + } + calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) { + const initialRetryDelay = 0.5; + const maxRetryDelay = 8.0; + const numRetries = maxRetries - retriesRemaining; + // Apply exponential backoff, but not more than the max. + const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay); + // Apply some jitter, take up to at most 25 percent of the retry time. + const jitter = 1 - Math.random() * 0.25; + return sleepSeconds * jitter * 1000; + } + getUserAgent() { + return `${this.constructor.name}/JS ${version_1.VERSION}`; + } +} +exports.APIClient = APIClient; +class AbstractPage { + constructor(client, response, body, options) { + _AbstractPage_client.set(this, void 0); + __classPrivateFieldSet(this, _AbstractPage_client, client, "f"); + this.options = options; + this.response = response; + this.body = body; + } + hasNextPage() { + const items = this.getPaginatedItems(); + if (!items.length) + return false; + return this.nextPageInfo() != null; + } + async getNextPage() { + const nextInfo = this.nextPageInfo(); + if (!nextInfo) { + throw new error_1.OpenAIError('No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.'); + } + const nextOptions = { ...this.options }; + if ('params' in nextInfo && typeof nextOptions.query === 'object') { + nextOptions.query = { ...nextOptions.query, ...nextInfo.params }; + } + else if ('url' in nextInfo) { + const params = [...Object.entries(nextOptions.query || {}), ...nextInfo.url.searchParams.entries()]; + for (const [key, value] of params) { + nextInfo.url.searchParams.set(key, value); + } + nextOptions.query = undefined; + nextOptions.path = nextInfo.url.toString(); + } + return await __classPrivateFieldGet(this, _AbstractPage_client, "f").requestAPIList(this.constructor, nextOptions); + } + async *iterPages() { + // eslint-disable-next-line @typescript-eslint/no-this-alias + let page = this; + yield page; + while (page.hasNextPage()) { + page = await page.getNextPage(); + yield page; + } + } + async *[(_AbstractPage_client = new WeakMap(), Symbol.asyncIterator)]() { + for await (const page of this.iterPages()) { + for (const item of page.getPaginatedItems()) { + yield item; + } + } + } +} +exports.AbstractPage = AbstractPage; +/** + * This subclass of Promise will resolve to an instantiated Page once the request completes. + * + * It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg: + * + * for await (const item of client.items.list()) { + * console.log(item) + * } + */ +class PagePromise extends APIPromise { + constructor(client, request, Page) { + super(request, async (props) => new Page(client, props.response, await defaultParseResponse(props), props.options)); + } + /** + * Allow auto-paginating iteration on an unawaited list call, eg: + * + * for await (const item of client.items.list()) { + * console.log(item) + * } + */ + async *[Symbol.asyncIterator]() { + const page = await this; + for await (const item of page) { + yield item; + } + } +} +exports.PagePromise = PagePromise; +const createResponseHeaders = (headers) => { + return new Proxy(Object.fromEntries( + // @ts-ignore + headers.entries()), { + get(target, name) { + const key = name.toString(); + return target[key.toLowerCase()] || target[key]; + }, + }); +}; +exports.createResponseHeaders = createResponseHeaders; +// This is required so that we can determine if a given object matches the RequestOptions +// type at runtime. While this requires duplication, it is enforced by the TypeScript +// compiler such that any missing / extraneous keys will cause an error. +const requestOptionsKeys = { + method: true, + path: true, + query: true, + body: true, + headers: true, + maxRetries: true, + stream: true, + timeout: true, + httpAgent: true, + signal: true, + idempotencyKey: true, + __binaryResponse: true, + __streamClass: true, +}; +const isRequestOptions = (obj) => { + return (typeof obj === 'object' && + obj !== null && + !isEmptyObj(obj) && + Object.keys(obj).every((k) => hasOwn(requestOptionsKeys, k))); +}; +exports.isRequestOptions = isRequestOptions; +const getPlatformProperties = () => { + if (typeof Deno !== 'undefined' && Deno.build != null) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': version_1.VERSION, + 'X-Stainless-OS': normalizePlatform(Deno.build.os), + 'X-Stainless-Arch': normalizeArch(Deno.build.arch), + 'X-Stainless-Runtime': 'deno', + 'X-Stainless-Runtime-Version': typeof Deno.version === 'string' ? Deno.version : Deno.version?.deno ?? 'unknown', + }; + } + if (typeof EdgeRuntime !== 'undefined') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': version_1.VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': `other:${EdgeRuntime}`, + 'X-Stainless-Runtime': 'edge', + 'X-Stainless-Runtime-Version': process.version, + }; + } + // Check if Node.js + if (Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]') { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': version_1.VERSION, + 'X-Stainless-OS': normalizePlatform(process.platform), + 'X-Stainless-Arch': normalizeArch(process.arch), + 'X-Stainless-Runtime': 'node', + 'X-Stainless-Runtime-Version': process.version, + }; + } + const browserInfo = getBrowserInfo(); + if (browserInfo) { + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': version_1.VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': `browser:${browserInfo.browser}`, + 'X-Stainless-Runtime-Version': browserInfo.version, + }; + } + // TODO add support for Cloudflare workers, etc. + return { + 'X-Stainless-Lang': 'js', + 'X-Stainless-Package-Version': version_1.VERSION, + 'X-Stainless-OS': 'Unknown', + 'X-Stainless-Arch': 'unknown', + 'X-Stainless-Runtime': 'unknown', + 'X-Stainless-Runtime-Version': 'unknown', + }; +}; +// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts +function getBrowserInfo() { + if (typeof navigator === 'undefined' || !navigator) { + return null; + } + // NOTE: The order matters here! + const browserPatterns = [ + { key: 'edge', pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'ie', pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'chrome', pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'firefox', pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ }, + { key: 'safari', pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ }, + ]; + // Find the FIRST matching browser + for (const { key, pattern } of browserPatterns) { + const match = pattern.exec(navigator.userAgent); + if (match) { + const major = match[1] || 0; + const minor = match[2] || 0; + const patch = match[3] || 0; + return { browser: key, version: `${major}.${minor}.${patch}` }; + } + } + return null; +} +const normalizeArch = (arch) => { + // Node docs: + // - https://nodejs.org/api/process.html#processarch + // Deno docs: + // - https://doc.deno.land/deno/stable/~/Deno.build + if (arch === 'x32') + return 'x32'; + if (arch === 'x86_64' || arch === 'x64') + return 'x64'; + if (arch === 'arm') + return 'arm'; + if (arch === 'aarch64' || arch === 'arm64') + return 'arm64'; + if (arch) + return `other:${arch}`; + return 'unknown'; +}; +const normalizePlatform = (platform) => { + // Node platforms: + // - https://nodejs.org/api/process.html#processplatform + // Deno platforms: + // - https://doc.deno.land/deno/stable/~/Deno.build + // - https://github.com/denoland/deno/issues/14799 + platform = platform.toLowerCase(); + // NOTE: this iOS check is untested and may not work + // Node does not work natively on IOS, there is a fork at + // https://github.com/nodejs-mobile/nodejs-mobile + // however it is unknown at the time of writing how to detect if it is running + if (platform.includes('ios')) + return 'iOS'; + if (platform === 'android') + return 'Android'; + if (platform === 'darwin') + return 'MacOS'; + if (platform === 'win32') + return 'Windows'; + if (platform === 'freebsd') + return 'FreeBSD'; + if (platform === 'openbsd') + return 'OpenBSD'; + if (platform === 'linux') + return 'Linux'; + if (platform) + return `Other:${platform}`; + return 'Unknown'; +}; +let _platformHeaders; +const getPlatformHeaders = () => { + return (_platformHeaders ?? (_platformHeaders = getPlatformProperties())); +}; +const safeJSON = (text) => { + try { + return JSON.parse(text); + } + catch (err) { + return undefined; + } +}; +exports.safeJSON = safeJSON; +// https://stackoverflow.com/a/19709846 +const startsWithSchemeRegexp = new RegExp('^(?:[a-z]+:)?//', 'i'); +const isAbsoluteURL = (url) => { + return startsWithSchemeRegexp.test(url); +}; +const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); +exports.sleep = sleep; +const validatePositiveInteger = (name, n) => { + if (typeof n !== 'number' || !Number.isInteger(n)) { + throw new error_1.OpenAIError(`${name} must be an integer`); + } + if (n < 0) { + throw new error_1.OpenAIError(`${name} must be a positive integer`); + } + return n; +}; +const castToError = (err) => { + if (err instanceof Error) + return err; + return new Error(err); +}; +exports.castToError = castToError; +const ensurePresent = (value) => { + if (value == null) + throw new error_1.OpenAIError(`Expected a value to be given but received ${value} instead.`); + return value; +}; +exports.ensurePresent = ensurePresent; +/** + * Read an environment variable. + * + * Trims beginning and trailing whitespace. + * + * Will return undefined if the environment variable doesn't exist or cannot be accessed. + */ +const readEnv = (env) => { + if (typeof process !== 'undefined') { + return process.env?.[env]?.trim() ?? undefined; + } + if (typeof Deno !== 'undefined') { + return Deno.env?.get?.(env)?.trim(); + } + return undefined; +}; +exports.readEnv = readEnv; +const coerceInteger = (value) => { + if (typeof value === 'number') + return Math.round(value); + if (typeof value === 'string') + return parseInt(value, 10); + throw new error_1.OpenAIError(`Could not coerce ${value} (type: ${typeof value}) into a number`); +}; +exports.coerceInteger = coerceInteger; +const coerceFloat = (value) => { + if (typeof value === 'number') + return value; + if (typeof value === 'string') + return parseFloat(value); + throw new error_1.OpenAIError(`Could not coerce ${value} (type: ${typeof value}) into a number`); +}; +exports.coerceFloat = coerceFloat; +const coerceBoolean = (value) => { + if (typeof value === 'boolean') + return value; + if (typeof value === 'string') + return value === 'true'; + return Boolean(value); +}; +exports.coerceBoolean = coerceBoolean; +const maybeCoerceInteger = (value) => { + if (value === undefined) { + return undefined; + } + return (0, exports.coerceInteger)(value); +}; +exports.maybeCoerceInteger = maybeCoerceInteger; +const maybeCoerceFloat = (value) => { + if (value === undefined) { + return undefined; + } + return (0, exports.coerceFloat)(value); +}; +exports.maybeCoerceFloat = maybeCoerceFloat; +const maybeCoerceBoolean = (value) => { + if (value === undefined) { + return undefined; + } + return (0, exports.coerceBoolean)(value); +}; +exports.maybeCoerceBoolean = maybeCoerceBoolean; +// https://stackoverflow.com/a/34491287 +function isEmptyObj(obj) { + if (!obj) + return true; + for (const _k in obj) + return false; + return true; +} +exports.isEmptyObj = isEmptyObj; +// https://eslint.org/docs/latest/rules/no-prototype-builtins +function hasOwn(obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key); +} +exports.hasOwn = hasOwn; +/** + * Copies headers from "newHeaders" onto "targetHeaders", + * using lower-case for all properties, + * ignoring any keys with undefined values, + * and deleting any keys with null values. + */ +function applyHeadersMut(targetHeaders, newHeaders) { + for (const k in newHeaders) { + if (!hasOwn(newHeaders, k)) + continue; + const lowerKey = k.toLowerCase(); + if (!lowerKey) + continue; + const val = newHeaders[k]; + if (val === null) { + delete targetHeaders[lowerKey]; + } + else if (val !== undefined) { + targetHeaders[lowerKey] = val; + } + } +} +function debug(action, ...args) { + if (typeof process !== 'undefined' && process?.env?.['DEBUG'] === 'true') { + console.log(`OpenAI:DEBUG:${action}`, ...args); + } +} +exports.debug = debug; +/** + * https://stackoverflow.com/a/2117523 + */ +const uuid4 = () => { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0; + const v = c === 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); +}; +const isRunningInBrowser = () => { + return ( + // @ts-ignore + typeof window !== 'undefined' && + // @ts-ignore + typeof window.document !== 'undefined' && + // @ts-ignore + typeof navigator !== 'undefined'); +}; +exports.isRunningInBrowser = isRunningInBrowser; +const isHeadersProtocol = (headers) => { + return typeof headers?.get === 'function'; +}; +exports.isHeadersProtocol = isHeadersProtocol; +const getRequiredHeader = (headers, header) => { + const lowerCasedHeader = header.toLowerCase(); + if ((0, exports.isHeadersProtocol)(headers)) { + // to deal with the case where the header looks like Stainless-Event-Id + const intercapsHeader = header[0]?.toUpperCase() + + header.substring(1).replace(/([^\w])(\w)/g, (_m, g1, g2) => g1 + g2.toUpperCase()); + for (const key of [header, lowerCasedHeader, header.toUpperCase(), intercapsHeader]) { + const value = headers.get(key); + if (value) { + return value; + } + } + } + for (const [key, value] of Object.entries(headers)) { + if (key.toLowerCase() === lowerCasedHeader) { + if (Array.isArray(value)) { + if (value.length <= 1) + return value[0]; + console.warn(`Received ${value.length} entries for the ${header} header, using the first entry.`); + return value[0]; + } + return value; + } + } + throw new Error(`Could not find ${header} header`); +}; +exports.getRequiredHeader = getRequiredHeader; +/** + * Encodes a string to Base64 format. + */ +const toBase64 = (str) => { + if (!str) + return ''; + if (typeof Buffer !== 'undefined') { + return Buffer.from(str).toString('base64'); + } + if (typeof btoa !== 'undefined') { + return btoa(str); + } + throw new error_1.OpenAIError('Cannot generate b64 string; Expected `Buffer` or `btoa` to be defined'); +}; +exports.toBase64 = toBase64; +function isObj(obj) { + return obj != null && typeof obj === 'object' && !Array.isArray(obj); +} +exports.isObj = isObj; +//# sourceMappingURL=core.js.map + +/***/ }), + +/***/ 8905: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.InternalServerError = exports.RateLimitError = exports.UnprocessableEntityError = exports.ConflictError = exports.NotFoundError = exports.PermissionDeniedError = exports.AuthenticationError = exports.BadRequestError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIUserAbortError = exports.APIError = exports.OpenAIError = void 0; +const core_1 = __nccwpck_require__(1798); +class OpenAIError extends Error { +} +exports.OpenAIError = OpenAIError; +class APIError extends OpenAIError { + constructor(status, error, message, headers) { + super(`${APIError.makeMessage(status, error, message)}`); + this.status = status; + this.headers = headers; + this.request_id = headers?.['x-request-id']; + const data = error; + this.error = data; + this.code = data?.['code']; + this.param = data?.['param']; + this.type = data?.['type']; + } + static makeMessage(status, error, message) { + const msg = error?.message ? + typeof error.message === 'string' ? + error.message + : JSON.stringify(error.message) + : error ? JSON.stringify(error) + : message; + if (status && msg) { + return `${status} ${msg}`; + } + if (status) { + return `${status} status code (no body)`; + } + if (msg) { + return msg; + } + return '(no status code or body)'; + } + static generate(status, errorResponse, message, headers) { + if (!status) { + return new APIConnectionError({ cause: (0, core_1.castToError)(errorResponse) }); + } + const error = errorResponse?.['error']; + if (status === 400) { + return new BadRequestError(status, error, message, headers); + } + if (status === 401) { + return new AuthenticationError(status, error, message, headers); + } + if (status === 403) { + return new PermissionDeniedError(status, error, message, headers); + } + if (status === 404) { + return new NotFoundError(status, error, message, headers); + } + if (status === 409) { + return new ConflictError(status, error, message, headers); + } + if (status === 422) { + return new UnprocessableEntityError(status, error, message, headers); + } + if (status === 429) { + return new RateLimitError(status, error, message, headers); + } + if (status >= 500) { + return new InternalServerError(status, error, message, headers); + } + return new APIError(status, error, message, headers); + } +} +exports.APIError = APIError; +class APIUserAbortError extends APIError { + constructor({ message } = {}) { + super(undefined, undefined, message || 'Request was aborted.', undefined); + this.status = undefined; + } +} +exports.APIUserAbortError = APIUserAbortError; +class APIConnectionError extends APIError { + constructor({ message, cause }) { + super(undefined, undefined, message || 'Connection error.', undefined); + this.status = undefined; + // in some environments the 'cause' property is already declared + // @ts-ignore + if (cause) + this.cause = cause; + } +} +exports.APIConnectionError = APIConnectionError; +class APIConnectionTimeoutError extends APIConnectionError { + constructor({ message } = {}) { + super({ message: message ?? 'Request timed out.' }); + } +} +exports.APIConnectionTimeoutError = APIConnectionTimeoutError; +class BadRequestError extends APIError { + constructor() { + super(...arguments); + this.status = 400; + } +} +exports.BadRequestError = BadRequestError; +class AuthenticationError extends APIError { + constructor() { + super(...arguments); + this.status = 401; + } +} +exports.AuthenticationError = AuthenticationError; +class PermissionDeniedError extends APIError { + constructor() { + super(...arguments); + this.status = 403; + } +} +exports.PermissionDeniedError = PermissionDeniedError; +class NotFoundError extends APIError { + constructor() { + super(...arguments); + this.status = 404; + } +} +exports.NotFoundError = NotFoundError; +class ConflictError extends APIError { + constructor() { + super(...arguments); + this.status = 409; + } +} +exports.ConflictError = ConflictError; +class UnprocessableEntityError extends APIError { + constructor() { + super(...arguments); + this.status = 422; + } +} +exports.UnprocessableEntityError = UnprocessableEntityError; +class RateLimitError extends APIError { + constructor() { + super(...arguments); + this.status = 429; + } +} +exports.RateLimitError = RateLimitError; +class InternalServerError extends APIError { +} +exports.InternalServerError = InternalServerError; +//# sourceMappingURL=error.js.map + +/***/ }), + +/***/ 47: +/***/ (function(module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var _a; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AzureOpenAI = exports.fileFromPath = exports.toFile = exports.UnprocessableEntityError = exports.PermissionDeniedError = exports.InternalServerError = exports.AuthenticationError = exports.BadRequestError = exports.RateLimitError = exports.ConflictError = exports.NotFoundError = exports.APIUserAbortError = exports.APIConnectionTimeoutError = exports.APIConnectionError = exports.APIError = exports.OpenAIError = exports.OpenAI = void 0; +const Core = __importStar(__nccwpck_require__(1798)); +const Errors = __importStar(__nccwpck_require__(8905)); +const Uploads = __importStar(__nccwpck_require__(3394)); +const Pagination = __importStar(__nccwpck_require__(7401)); +const API = __importStar(__nccwpck_require__(5690)); +/** API Client for interfacing with the OpenAI API. */ +class OpenAI extends Core.APIClient { + /** + * API Client for interfacing with the OpenAI API. + * + * @param {string | undefined} [opts.apiKey=process.env['OPENAI_API_KEY'] ?? undefined] + * @param {string | null | undefined} [opts.organization=process.env['OPENAI_ORG_ID'] ?? null] + * @param {string | null | undefined} [opts.project=process.env['OPENAI_PROJECT_ID'] ?? null] + * @param {string} [opts.baseURL=process.env['OPENAI_BASE_URL'] ?? https://api.openai.com/v1] - Override the default base URL for the API. + * @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections. + * @param {Core.Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {Core.Headers} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Core.DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API. + * @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers. + */ + constructor({ baseURL = Core.readEnv('OPENAI_BASE_URL'), apiKey = Core.readEnv('OPENAI_API_KEY'), organization = Core.readEnv('OPENAI_ORG_ID') ?? null, project = Core.readEnv('OPENAI_PROJECT_ID') ?? null, ...opts } = {}) { + if (apiKey === undefined) { + throw new Errors.OpenAIError("The OPENAI_API_KEY environment variable is missing or empty; either provide it, or instantiate the OpenAI client with an apiKey option, like new OpenAI({ apiKey: 'My API Key' })."); + } + const options = { + apiKey, + organization, + project, + ...opts, + baseURL: baseURL || `https://api.openai.com/v1`, + }; + if (!options.dangerouslyAllowBrowser && Core.isRunningInBrowser()) { + throw new Errors.OpenAIError("It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew OpenAI({ apiKey, dangerouslyAllowBrowser: true });\n\nhttps://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety\n"); + } + super({ + baseURL: options.baseURL, + timeout: options.timeout ?? 600000 /* 10 minutes */, + httpAgent: options.httpAgent, + maxRetries: options.maxRetries, + fetch: options.fetch, + }); + this.completions = new API.Completions(this); + this.chat = new API.Chat(this); + this.embeddings = new API.Embeddings(this); + this.files = new API.Files(this); + this.images = new API.Images(this); + this.audio = new API.Audio(this); + this.moderations = new API.Moderations(this); + this.models = new API.Models(this); + this.fineTuning = new API.FineTuning(this); + this.beta = new API.Beta(this); + this.batches = new API.Batches(this); + this._options = options; + this.apiKey = apiKey; + this.organization = organization; + this.project = project; + } + defaultQuery() { + return this._options.defaultQuery; + } + defaultHeaders(opts) { + return { + ...super.defaultHeaders(opts), + 'OpenAI-Organization': this.organization, + 'OpenAI-Project': this.project, + ...this._options.defaultHeaders, + }; + } + authHeaders(opts) { + return { Authorization: `Bearer ${this.apiKey}` }; + } +} +exports.OpenAI = OpenAI; +_a = OpenAI; +OpenAI.OpenAI = _a; +OpenAI.OpenAIError = Errors.OpenAIError; +OpenAI.APIError = Errors.APIError; +OpenAI.APIConnectionError = Errors.APIConnectionError; +OpenAI.APIConnectionTimeoutError = Errors.APIConnectionTimeoutError; +OpenAI.APIUserAbortError = Errors.APIUserAbortError; +OpenAI.NotFoundError = Errors.NotFoundError; +OpenAI.ConflictError = Errors.ConflictError; +OpenAI.RateLimitError = Errors.RateLimitError; +OpenAI.BadRequestError = Errors.BadRequestError; +OpenAI.AuthenticationError = Errors.AuthenticationError; +OpenAI.InternalServerError = Errors.InternalServerError; +OpenAI.PermissionDeniedError = Errors.PermissionDeniedError; +OpenAI.UnprocessableEntityError = Errors.UnprocessableEntityError; +OpenAI.toFile = Uploads.toFile; +OpenAI.fileFromPath = Uploads.fileFromPath; +exports.OpenAIError = Errors.OpenAIError, exports.APIError = Errors.APIError, exports.APIConnectionError = Errors.APIConnectionError, exports.APIConnectionTimeoutError = Errors.APIConnectionTimeoutError, exports.APIUserAbortError = Errors.APIUserAbortError, exports.NotFoundError = Errors.NotFoundError, exports.ConflictError = Errors.ConflictError, exports.RateLimitError = Errors.RateLimitError, exports.BadRequestError = Errors.BadRequestError, exports.AuthenticationError = Errors.AuthenticationError, exports.InternalServerError = Errors.InternalServerError, exports.PermissionDeniedError = Errors.PermissionDeniedError, exports.UnprocessableEntityError = Errors.UnprocessableEntityError; +exports.toFile = Uploads.toFile; +exports.fileFromPath = Uploads.fileFromPath; +(function (OpenAI) { + OpenAI.Page = Pagination.Page; + OpenAI.CursorPage = Pagination.CursorPage; + OpenAI.Completions = API.Completions; + OpenAI.Chat = API.Chat; + OpenAI.Embeddings = API.Embeddings; + OpenAI.Files = API.Files; + OpenAI.FileObjectsPage = API.FileObjectsPage; + OpenAI.Images = API.Images; + OpenAI.Audio = API.Audio; + OpenAI.Moderations = API.Moderations; + OpenAI.Models = API.Models; + OpenAI.ModelsPage = API.ModelsPage; + OpenAI.FineTuning = API.FineTuning; + OpenAI.Beta = API.Beta; + OpenAI.Batches = API.Batches; + OpenAI.BatchesPage = API.BatchesPage; +})(OpenAI = exports.OpenAI || (exports.OpenAI = {})); +/** API Client for interfacing with the Azure OpenAI API. */ +class AzureOpenAI extends OpenAI { + /** + * API Client for interfacing with the Azure OpenAI API. + * + * @param {string | undefined} [opts.apiVersion=process.env['OPENAI_API_VERSION'] ?? undefined] + * @param {string | undefined} [opts.endpoint=process.env['AZURE_OPENAI_ENDPOINT'] ?? undefined] - Your Azure endpoint, including the resource, e.g. `https://example-resource.azure.openai.com/` + * @param {string | undefined} [opts.apiKey=process.env['AZURE_OPENAI_API_KEY'] ?? undefined] + * @param {string | undefined} opts.deployment - A model deployment, if given, sets the base client URL to include `/deployments/{deployment}`. + * @param {string | null | undefined} [opts.organization=process.env['OPENAI_ORG_ID'] ?? null] + * @param {string} [opts.baseURL=process.env['OPENAI_BASE_URL']] - Sets the base URL for the API. + * @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. + * @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections. + * @param {Core.Fetch} [opts.fetch] - Specify a custom `fetch` function implementation. + * @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request. + * @param {Core.Headers} opts.defaultHeaders - Default headers to include with every request to the API. + * @param {Core.DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API. + * @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers. + */ + constructor({ baseURL = Core.readEnv('OPENAI_BASE_URL'), apiKey = Core.readEnv('AZURE_OPENAI_API_KEY'), apiVersion = Core.readEnv('OPENAI_API_VERSION'), endpoint, deployment, azureADTokenProvider, dangerouslyAllowBrowser, ...opts } = {}) { + if (!apiVersion) { + throw new Errors.OpenAIError("The OPENAI_API_VERSION environment variable is missing or empty; either provide it, or instantiate the AzureOpenAI client with an apiVersion option, like new AzureOpenAI({ apiVersion: 'My API Version' })."); + } + if (typeof azureADTokenProvider === 'function') { + dangerouslyAllowBrowser = true; + } + if (!azureADTokenProvider && !apiKey) { + throw new Errors.OpenAIError('Missing credentials. Please pass one of `apiKey` and `azureADTokenProvider`, or set the `AZURE_OPENAI_API_KEY` environment variable.'); + } + if (azureADTokenProvider && apiKey) { + throw new Errors.OpenAIError('The `apiKey` and `azureADTokenProvider` arguments are mutually exclusive; only one can be passed at a time.'); + } + // define a sentinel value to avoid any typing issues + apiKey ?? (apiKey = API_KEY_SENTINEL); + opts.defaultQuery = { ...opts.defaultQuery, 'api-version': apiVersion }; + if (!baseURL) { + if (!endpoint) { + endpoint = process.env['AZURE_OPENAI_ENDPOINT']; + } + if (!endpoint) { + throw new Errors.OpenAIError('Must provide one of the `baseURL` or `endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable'); + } + baseURL = `${endpoint}/openai`; + } + else { + if (endpoint) { + throw new Errors.OpenAIError('baseURL and endpoint are mutually exclusive'); + } + } + super({ + apiKey, + baseURL, + ...opts, + ...(dangerouslyAllowBrowser !== undefined ? { dangerouslyAllowBrowser } : {}), + }); + this.apiVersion = ''; + this._azureADTokenProvider = azureADTokenProvider; + this.apiVersion = apiVersion; + this._deployment = deployment; + } + buildRequest(options) { + if (_deployments_endpoints.has(options.path) && options.method === 'post' && options.body !== undefined) { + if (!Core.isObj(options.body)) { + throw new Error('Expected request body to be an object'); + } + const model = this._deployment || options.body['model']; + delete options.body['model']; + if (model !== undefined && !this.baseURL.includes('/deployments')) { + options.path = `/deployments/${model}${options.path}`; + } + } + return super.buildRequest(options); + } + async _getAzureADToken() { + if (typeof this._azureADTokenProvider === 'function') { + const token = await this._azureADTokenProvider(); + if (!token || typeof token !== 'string') { + throw new Errors.OpenAIError(`Expected 'azureADTokenProvider' argument to return a string but it returned ${token}`); + } + return token; + } + return undefined; + } + authHeaders(opts) { + return {}; + } + async prepareOptions(opts) { + if (opts.headers?.['Authorization'] || opts.headers?.['api-key']) { + return super.prepareOptions(opts); + } + const token = await this._getAzureADToken(); + opts.headers ?? (opts.headers = {}); + if (token) { + opts.headers['Authorization'] = `Bearer ${token}`; + } + else if (this.apiKey !== API_KEY_SENTINEL) { + opts.headers['api-key'] = this.apiKey; + } + else { + throw new Errors.OpenAIError('Unable to handle auth'); + } + return super.prepareOptions(opts); + } +} +exports.AzureOpenAI = AzureOpenAI; +const _deployments_endpoints = new Set([ + '/completions', + '/chat/completions', + '/embeddings', + '/audio/transcriptions', + '/audio/translations', + '/audio/speech', + '/images/generations', + '/batches', +]); +const API_KEY_SENTINEL = ''; +// ---------------------- End Azure ---------------------- +exports = module.exports = OpenAI; +module.exports.AzureOpenAI = AzureOpenAI; +exports["default"] = OpenAI; +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 9365: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _AbstractAssistantStreamRunner_connectedPromise, _AbstractAssistantStreamRunner_resolveConnectedPromise, _AbstractAssistantStreamRunner_rejectConnectedPromise, _AbstractAssistantStreamRunner_endPromise, _AbstractAssistantStreamRunner_resolveEndPromise, _AbstractAssistantStreamRunner_rejectEndPromise, _AbstractAssistantStreamRunner_listeners, _AbstractAssistantStreamRunner_ended, _AbstractAssistantStreamRunner_errored, _AbstractAssistantStreamRunner_aborted, _AbstractAssistantStreamRunner_catchingPromiseCreated, _AbstractAssistantStreamRunner_handleError; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AbstractAssistantStreamRunner = void 0; +const error_1 = __nccwpck_require__(8905); +class AbstractAssistantStreamRunner { + constructor() { + this.controller = new AbortController(); + _AbstractAssistantStreamRunner_connectedPromise.set(this, void 0); + _AbstractAssistantStreamRunner_resolveConnectedPromise.set(this, () => { }); + _AbstractAssistantStreamRunner_rejectConnectedPromise.set(this, () => { }); + _AbstractAssistantStreamRunner_endPromise.set(this, void 0); + _AbstractAssistantStreamRunner_resolveEndPromise.set(this, () => { }); + _AbstractAssistantStreamRunner_rejectEndPromise.set(this, () => { }); + _AbstractAssistantStreamRunner_listeners.set(this, {}); + _AbstractAssistantStreamRunner_ended.set(this, false); + _AbstractAssistantStreamRunner_errored.set(this, false); + _AbstractAssistantStreamRunner_aborted.set(this, false); + _AbstractAssistantStreamRunner_catchingPromiseCreated.set(this, false); + _AbstractAssistantStreamRunner_handleError.set(this, (error) => { + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_errored, true, "f"); + if (error instanceof Error && error.name === 'AbortError') { + error = new error_1.APIUserAbortError(); + } + if (error instanceof error_1.APIUserAbortError) { + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_aborted, true, "f"); + return this._emit('abort', error); + } + if (error instanceof error_1.OpenAIError) { + return this._emit('error', error); + } + if (error instanceof Error) { + const openAIError = new error_1.OpenAIError(error.message); + // @ts-ignore + openAIError.cause = error; + return this._emit('error', openAIError); + } + return this._emit('error', new error_1.OpenAIError(String(error))); + }); + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_connectedPromise, new Promise((resolve, reject) => { + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_resolveConnectedPromise, resolve, "f"); + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_rejectConnectedPromise, reject, "f"); + }), "f"); + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_endPromise, new Promise((resolve, reject) => { + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_resolveEndPromise, resolve, "f"); + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_rejectEndPromise, reject, "f"); + }), "f"); + // Don't let these promises cause unhandled rejection errors. + // we will manually cause an unhandled rejection error later + // if the user hasn't registered any error listener or called + // any promise-returning method. + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_connectedPromise, "f").catch(() => { }); + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_endPromise, "f").catch(() => { }); + } + _run(executor) { + // Unfortunately if we call `executor()` immediately we get runtime errors about + // references to `this` before the `super()` constructor call returns. + setTimeout(() => { + executor().then(() => { + // this._emitFinal(); + this._emit('end'); + }, __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_handleError, "f")); + }, 0); + } + _addRun(run) { + return run; + } + _connected() { + if (this.ended) + return; + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_resolveConnectedPromise, "f").call(this); + this._emit('connect'); + } + get ended() { + return __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_ended, "f"); + } + get errored() { + return __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_errored, "f"); + } + get aborted() { + return __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_aborted, "f"); + } + abort() { + this.controller.abort(); + } + /** + * Adds the listener function to the end of the listeners array for the event. + * No checks are made to see if the listener has already been added. Multiple calls passing + * the same combination of event and listener will result in the listener being added, and + * called, multiple times. + * @returns this ChatCompletionStream, so that calls can be chained + */ + on(event, listener) { + const listeners = __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_listeners, "f")[event] || (__classPrivateFieldGet(this, _AbstractAssistantStreamRunner_listeners, "f")[event] = []); + listeners.push({ listener }); + return this; + } + /** + * Removes the specified listener from the listener array for the event. + * off() will remove, at most, one instance of a listener from the listener array. If any single + * listener has been added multiple times to the listener array for the specified event, then + * off() must be called multiple times to remove each instance. + * @returns this ChatCompletionStream, so that calls can be chained + */ + off(event, listener) { + const listeners = __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_listeners, "f")[event]; + if (!listeners) + return this; + const index = listeners.findIndex((l) => l.listener === listener); + if (index >= 0) + listeners.splice(index, 1); + return this; + } + /** + * Adds a one-time listener function for the event. The next time the event is triggered, + * this listener is removed and then invoked. + * @returns this ChatCompletionStream, so that calls can be chained + */ + once(event, listener) { + const listeners = __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_listeners, "f")[event] || (__classPrivateFieldGet(this, _AbstractAssistantStreamRunner_listeners, "f")[event] = []); + listeners.push({ listener, once: true }); + return this; + } + /** + * This is similar to `.once()`, but returns a Promise that resolves the next time + * the event is triggered, instead of calling a listener callback. + * @returns a Promise that resolves the next time given event is triggered, + * or rejects if an error is emitted. (If you request the 'error' event, + * returns a promise that resolves with the error). + * + * Example: + * + * const message = await stream.emitted('message') // rejects if the stream errors + */ + emitted(event) { + return new Promise((resolve, reject) => { + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_catchingPromiseCreated, true, "f"); + if (event !== 'error') + this.once('error', reject); + this.once(event, resolve); + }); + } + async done() { + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_catchingPromiseCreated, true, "f"); + await __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_endPromise, "f"); + } + _emit(event, ...args) { + // make sure we don't emit any events after end + if (__classPrivateFieldGet(this, _AbstractAssistantStreamRunner_ended, "f")) { + return; + } + if (event === 'end') { + __classPrivateFieldSet(this, _AbstractAssistantStreamRunner_ended, true, "f"); + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_resolveEndPromise, "f").call(this); + } + const listeners = __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_listeners, "f")[event]; + if (listeners) { + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_listeners, "f")[event] = listeners.filter((l) => !l.once); + listeners.forEach(({ listener }) => listener(...args)); + } + if (event === 'abort') { + const error = args[0]; + if (!__classPrivateFieldGet(this, _AbstractAssistantStreamRunner_catchingPromiseCreated, "f") && !listeners?.length) { + Promise.reject(error); + } + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_rejectConnectedPromise, "f").call(this, error); + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_rejectEndPromise, "f").call(this, error); + this._emit('end'); + return; + } + if (event === 'error') { + // NOTE: _emit('error', error) should only be called from #handleError(). + const error = args[0]; + if (!__classPrivateFieldGet(this, _AbstractAssistantStreamRunner_catchingPromiseCreated, "f") && !listeners?.length) { + // Trigger an unhandled rejection if the user hasn't registered any error handlers. + // If you are seeing stack traces here, make sure to handle errors via either: + // - runner.on('error', () => ...) + // - await runner.done() + // - await runner.finalChatCompletion() + // - etc. + Promise.reject(error); + } + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_rejectConnectedPromise, "f").call(this, error); + __classPrivateFieldGet(this, _AbstractAssistantStreamRunner_rejectEndPromise, "f").call(this, error); + this._emit('end'); + } + } + async _threadAssistantStream(body, thread, options) { + return await this._createThreadAssistantStream(thread, body, options); + } + async _runAssistantStream(threadId, runs, params, options) { + return await this._createAssistantStream(runs, threadId, params, options); + } + async _runToolAssistantStream(threadId, runId, runs, params, options) { + return await this._createToolAssistantStream(runs, threadId, runId, params, options); + } + async _createThreadAssistantStream(thread, body, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + // this.#validateParams(params); + const runResult = await thread.createAndRun({ ...body, stream: false }, { ...options, signal: this.controller.signal }); + this._connected(); + return this._addRun(runResult); + } + async _createToolAssistantStream(run, threadId, runId, params, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + const runResult = await run.submitToolOutputs(threadId, runId, { ...params, stream: false }, { ...options, signal: this.controller.signal }); + this._connected(); + return this._addRun(runResult); + } + async _createAssistantStream(run, threadId, params, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + // this.#validateParams(params); + const runResult = await run.create(threadId, { ...params, stream: false }, { ...options, signal: this.controller.signal }); + this._connected(); + return this._addRun(runResult); + } +} +exports.AbstractAssistantStreamRunner = AbstractAssistantStreamRunner; +_AbstractAssistantStreamRunner_connectedPromise = new WeakMap(), _AbstractAssistantStreamRunner_resolveConnectedPromise = new WeakMap(), _AbstractAssistantStreamRunner_rejectConnectedPromise = new WeakMap(), _AbstractAssistantStreamRunner_endPromise = new WeakMap(), _AbstractAssistantStreamRunner_resolveEndPromise = new WeakMap(), _AbstractAssistantStreamRunner_rejectEndPromise = new WeakMap(), _AbstractAssistantStreamRunner_listeners = new WeakMap(), _AbstractAssistantStreamRunner_ended = new WeakMap(), _AbstractAssistantStreamRunner_errored = new WeakMap(), _AbstractAssistantStreamRunner_aborted = new WeakMap(), _AbstractAssistantStreamRunner_catchingPromiseCreated = new WeakMap(), _AbstractAssistantStreamRunner_handleError = new WeakMap(); +//# sourceMappingURL=AbstractAssistantStreamRunner.js.map + +/***/ }), + +/***/ 8398: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var _AbstractChatCompletionRunner_instances, _AbstractChatCompletionRunner_connectedPromise, _AbstractChatCompletionRunner_resolveConnectedPromise, _AbstractChatCompletionRunner_rejectConnectedPromise, _AbstractChatCompletionRunner_endPromise, _AbstractChatCompletionRunner_resolveEndPromise, _AbstractChatCompletionRunner_rejectEndPromise, _AbstractChatCompletionRunner_listeners, _AbstractChatCompletionRunner_ended, _AbstractChatCompletionRunner_errored, _AbstractChatCompletionRunner_aborted, _AbstractChatCompletionRunner_catchingPromiseCreated, _AbstractChatCompletionRunner_getFinalContent, _AbstractChatCompletionRunner_getFinalMessage, _AbstractChatCompletionRunner_getFinalFunctionCall, _AbstractChatCompletionRunner_getFinalFunctionCallResult, _AbstractChatCompletionRunner_calculateTotalUsage, _AbstractChatCompletionRunner_handleError, _AbstractChatCompletionRunner_validateParams, _AbstractChatCompletionRunner_stringifyFunctionCallResult; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AbstractChatCompletionRunner = void 0; +const error_1 = __nccwpck_require__(8905); +const RunnableFunction_1 = __nccwpck_require__(5464); +const chatCompletionUtils_1 = __nccwpck_require__(7858); +const DEFAULT_MAX_CHAT_COMPLETIONS = 10; +class AbstractChatCompletionRunner { + constructor() { + _AbstractChatCompletionRunner_instances.add(this); + this.controller = new AbortController(); + _AbstractChatCompletionRunner_connectedPromise.set(this, void 0); + _AbstractChatCompletionRunner_resolveConnectedPromise.set(this, () => { }); + _AbstractChatCompletionRunner_rejectConnectedPromise.set(this, () => { }); + _AbstractChatCompletionRunner_endPromise.set(this, void 0); + _AbstractChatCompletionRunner_resolveEndPromise.set(this, () => { }); + _AbstractChatCompletionRunner_rejectEndPromise.set(this, () => { }); + _AbstractChatCompletionRunner_listeners.set(this, {}); + this._chatCompletions = []; + this.messages = []; + _AbstractChatCompletionRunner_ended.set(this, false); + _AbstractChatCompletionRunner_errored.set(this, false); + _AbstractChatCompletionRunner_aborted.set(this, false); + _AbstractChatCompletionRunner_catchingPromiseCreated.set(this, false); + _AbstractChatCompletionRunner_handleError.set(this, (error) => { + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_errored, true, "f"); + if (error instanceof Error && error.name === 'AbortError') { + error = new error_1.APIUserAbortError(); + } + if (error instanceof error_1.APIUserAbortError) { + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_aborted, true, "f"); + return this._emit('abort', error); + } + if (error instanceof error_1.OpenAIError) { + return this._emit('error', error); + } + if (error instanceof Error) { + const openAIError = new error_1.OpenAIError(error.message); + // @ts-ignore + openAIError.cause = error; + return this._emit('error', openAIError); + } + return this._emit('error', new error_1.OpenAIError(String(error))); + }); + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_connectedPromise, new Promise((resolve, reject) => { + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_resolveConnectedPromise, resolve, "f"); + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_rejectConnectedPromise, reject, "f"); + }), "f"); + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_endPromise, new Promise((resolve, reject) => { + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_resolveEndPromise, resolve, "f"); + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_rejectEndPromise, reject, "f"); + }), "f"); + // Don't let these promises cause unhandled rejection errors. + // we will manually cause an unhandled rejection error later + // if the user hasn't registered any error listener or called + // any promise-returning method. + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_connectedPromise, "f").catch(() => { }); + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_endPromise, "f").catch(() => { }); + } + _run(executor) { + // Unfortunately if we call `executor()` immediately we get runtime errors about + // references to `this` before the `super()` constructor call returns. + setTimeout(() => { + executor().then(() => { + this._emitFinal(); + this._emit('end'); + }, __classPrivateFieldGet(this, _AbstractChatCompletionRunner_handleError, "f")); + }, 0); + } + _addChatCompletion(chatCompletion) { + this._chatCompletions.push(chatCompletion); + this._emit('chatCompletion', chatCompletion); + const message = chatCompletion.choices[0]?.message; + if (message) + this._addMessage(message); + return chatCompletion; + } + _addMessage(message, emit = true) { + if (!('content' in message)) + message.content = null; + this.messages.push(message); + if (emit) { + this._emit('message', message); + if (((0, chatCompletionUtils_1.isFunctionMessage)(message) || (0, chatCompletionUtils_1.isToolMessage)(message)) && message.content) { + // Note, this assumes that {role: 'tool', content: ā€¦} is always the result of a call of tool of type=function. + this._emit('functionCallResult', message.content); + } + else if ((0, chatCompletionUtils_1.isAssistantMessage)(message) && message.function_call) { + this._emit('functionCall', message.function_call); + } + else if ((0, chatCompletionUtils_1.isAssistantMessage)(message) && message.tool_calls) { + for (const tool_call of message.tool_calls) { + if (tool_call.type === 'function') { + this._emit('functionCall', tool_call.function); + } + } + } + } + } + _connected() { + if (this.ended) + return; + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_resolveConnectedPromise, "f").call(this); + this._emit('connect'); + } + get ended() { + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_ended, "f"); + } + get errored() { + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_errored, "f"); + } + get aborted() { + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_aborted, "f"); + } + abort() { + this.controller.abort(); + } + /** + * Adds the listener function to the end of the listeners array for the event. + * No checks are made to see if the listener has already been added. Multiple calls passing + * the same combination of event and listener will result in the listener being added, and + * called, multiple times. + * @returns this ChatCompletionStream, so that calls can be chained + */ + on(event, listener) { + const listeners = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] || (__classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] = []); + listeners.push({ listener }); + return this; + } + /** + * Removes the specified listener from the listener array for the event. + * off() will remove, at most, one instance of a listener from the listener array. If any single + * listener has been added multiple times to the listener array for the specified event, then + * off() must be called multiple times to remove each instance. + * @returns this ChatCompletionStream, so that calls can be chained + */ + off(event, listener) { + const listeners = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event]; + if (!listeners) + return this; + const index = listeners.findIndex((l) => l.listener === listener); + if (index >= 0) + listeners.splice(index, 1); + return this; + } + /** + * Adds a one-time listener function for the event. The next time the event is triggered, + * this listener is removed and then invoked. + * @returns this ChatCompletionStream, so that calls can be chained + */ + once(event, listener) { + const listeners = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] || (__classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] = []); + listeners.push({ listener, once: true }); + return this; + } + /** + * This is similar to `.once()`, but returns a Promise that resolves the next time + * the event is triggered, instead of calling a listener callback. + * @returns a Promise that resolves the next time given event is triggered, + * or rejects if an error is emitted. (If you request the 'error' event, + * returns a promise that resolves with the error). + * + * Example: + * + * const message = await stream.emitted('message') // rejects if the stream errors + */ + emitted(event) { + return new Promise((resolve, reject) => { + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_catchingPromiseCreated, true, "f"); + if (event !== 'error') + this.once('error', reject); + this.once(event, resolve); + }); + } + async done() { + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_catchingPromiseCreated, true, "f"); + await __classPrivateFieldGet(this, _AbstractChatCompletionRunner_endPromise, "f"); + } + /** + * @returns a promise that resolves with the final ChatCompletion, or rejects + * if an error occurred or the stream ended prematurely without producing a ChatCompletion. + */ + async finalChatCompletion() { + await this.done(); + const completion = this._chatCompletions[this._chatCompletions.length - 1]; + if (!completion) + throw new error_1.OpenAIError('stream ended without producing a ChatCompletion'); + return completion; + } + /** + * @returns a promise that resolves with the content of the final ChatCompletionMessage, or rejects + * if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage. + */ + async finalContent() { + await this.done(); + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalContent).call(this); + } + /** + * @returns a promise that resolves with the the final assistant ChatCompletionMessage response, + * or rejects if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage. + */ + async finalMessage() { + await this.done(); + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this); + } + /** + * @returns a promise that resolves with the content of the final FunctionCall, or rejects + * if an error occurred or the stream ended prematurely without producing a ChatCompletionMessage. + */ + async finalFunctionCall() { + await this.done(); + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCall).call(this); + } + async finalFunctionCallResult() { + await this.done(); + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCallResult).call(this); + } + async totalUsage() { + await this.done(); + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_calculateTotalUsage).call(this); + } + allChatCompletions() { + return [...this._chatCompletions]; + } + _emit(event, ...args) { + // make sure we don't emit any events after end + if (__classPrivateFieldGet(this, _AbstractChatCompletionRunner_ended, "f")) { + return; + } + if (event === 'end') { + __classPrivateFieldSet(this, _AbstractChatCompletionRunner_ended, true, "f"); + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_resolveEndPromise, "f").call(this); + } + const listeners = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event]; + if (listeners) { + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_listeners, "f")[event] = listeners.filter((l) => !l.once); + listeners.forEach(({ listener }) => listener(...args)); + } + if (event === 'abort') { + const error = args[0]; + if (!__classPrivateFieldGet(this, _AbstractChatCompletionRunner_catchingPromiseCreated, "f") && !listeners?.length) { + Promise.reject(error); + } + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_rejectConnectedPromise, "f").call(this, error); + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_rejectEndPromise, "f").call(this, error); + this._emit('end'); + return; + } + if (event === 'error') { + // NOTE: _emit('error', error) should only be called from #handleError(). + const error = args[0]; + if (!__classPrivateFieldGet(this, _AbstractChatCompletionRunner_catchingPromiseCreated, "f") && !listeners?.length) { + // Trigger an unhandled rejection if the user hasn't registered any error handlers. + // If you are seeing stack traces here, make sure to handle errors via either: + // - runner.on('error', () => ...) + // - await runner.done() + // - await runner.finalChatCompletion() + // - etc. + Promise.reject(error); + } + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_rejectConnectedPromise, "f").call(this, error); + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_rejectEndPromise, "f").call(this, error); + this._emit('end'); + } + } + _emitFinal() { + const completion = this._chatCompletions[this._chatCompletions.length - 1]; + if (completion) + this._emit('finalChatCompletion', completion); + const finalMessage = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this); + if (finalMessage) + this._emit('finalMessage', finalMessage); + const finalContent = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalContent).call(this); + if (finalContent) + this._emit('finalContent', finalContent); + const finalFunctionCall = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCall).call(this); + if (finalFunctionCall) + this._emit('finalFunctionCall', finalFunctionCall); + const finalFunctionCallResult = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalFunctionCallResult).call(this); + if (finalFunctionCallResult != null) + this._emit('finalFunctionCallResult', finalFunctionCallResult); + if (this._chatCompletions.some((c) => c.usage)) { + this._emit('totalUsage', __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_calculateTotalUsage).call(this)); + } + } + async _createChatCompletion(completions, params, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_validateParams).call(this, params); + const chatCompletion = await completions.create({ ...params, stream: false }, { ...options, signal: this.controller.signal }); + this._connected(); + return this._addChatCompletion(chatCompletion); + } + async _runChatCompletion(completions, params, options) { + for (const message of params.messages) { + this._addMessage(message, false); + } + return await this._createChatCompletion(completions, params, options); + } + async _runFunctions(completions, params, options) { + const role = 'function'; + const { function_call = 'auto', stream, ...restParams } = params; + const singleFunctionToCall = typeof function_call !== 'string' && function_call?.name; + const { maxChatCompletions = DEFAULT_MAX_CHAT_COMPLETIONS } = options || {}; + const functionsByName = {}; + for (const f of params.functions) { + functionsByName[f.name || f.function.name] = f; + } + const functions = params.functions.map((f) => ({ + name: f.name || f.function.name, + parameters: f.parameters, + description: f.description, + })); + for (const message of params.messages) { + this._addMessage(message, false); + } + for (let i = 0; i < maxChatCompletions; ++i) { + const chatCompletion = await this._createChatCompletion(completions, { + ...restParams, + function_call, + functions, + messages: [...this.messages], + }, options); + const message = chatCompletion.choices[0]?.message; + if (!message) { + throw new error_1.OpenAIError(`missing message in ChatCompletion response`); + } + if (!message.function_call) + return; + const { name, arguments: args } = message.function_call; + const fn = functionsByName[name]; + if (!fn) { + const content = `Invalid function_call: ${JSON.stringify(name)}. Available options are: ${functions + .map((f) => JSON.stringify(f.name)) + .join(', ')}. Please try again`; + this._addMessage({ role, name, content }); + continue; + } + else if (singleFunctionToCall && singleFunctionToCall !== name) { + const content = `Invalid function_call: ${JSON.stringify(name)}. ${JSON.stringify(singleFunctionToCall)} requested. Please try again`; + this._addMessage({ role, name, content }); + continue; + } + let parsed; + try { + parsed = (0, RunnableFunction_1.isRunnableFunctionWithParse)(fn) ? await fn.parse(args) : args; + } + catch (error) { + this._addMessage({ + role, + name, + content: error instanceof Error ? error.message : String(error), + }); + continue; + } + // @ts-expect-error it can't rule out `never` type. + const rawContent = await fn.function(parsed, this); + const content = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_stringifyFunctionCallResult).call(this, rawContent); + this._addMessage({ role, name, content }); + if (singleFunctionToCall) + return; + } + } + async _runTools(completions, params, options) { + const role = 'tool'; + const { tool_choice = 'auto', stream, ...restParams } = params; + const singleFunctionToCall = typeof tool_choice !== 'string' && tool_choice?.function?.name; + const { maxChatCompletions = DEFAULT_MAX_CHAT_COMPLETIONS } = options || {}; + const functionsByName = {}; + for (const f of params.tools) { + if (f.type === 'function') { + functionsByName[f.function.name || f.function.function.name] = f.function; + } + } + const tools = 'tools' in params ? + params.tools.map((t) => t.type === 'function' ? + { + type: 'function', + function: { + name: t.function.name || t.function.function.name, + parameters: t.function.parameters, + description: t.function.description, + }, + } + : t) + : undefined; + for (const message of params.messages) { + this._addMessage(message, false); + } + for (let i = 0; i < maxChatCompletions; ++i) { + const chatCompletion = await this._createChatCompletion(completions, { + ...restParams, + tool_choice, + tools, + messages: [...this.messages], + }, options); + const message = chatCompletion.choices[0]?.message; + if (!message) { + throw new error_1.OpenAIError(`missing message in ChatCompletion response`); + } + if (!message.tool_calls) { + return; + } + for (const tool_call of message.tool_calls) { + if (tool_call.type !== 'function') + continue; + const tool_call_id = tool_call.id; + const { name, arguments: args } = tool_call.function; + const fn = functionsByName[name]; + if (!fn) { + const content = `Invalid tool_call: ${JSON.stringify(name)}. Available options are: ${tools + .map((f) => JSON.stringify(f.function.name)) + .join(', ')}. Please try again`; + this._addMessage({ role, tool_call_id, content }); + continue; + } + else if (singleFunctionToCall && singleFunctionToCall !== name) { + const content = `Invalid tool_call: ${JSON.stringify(name)}. ${JSON.stringify(singleFunctionToCall)} requested. Please try again`; + this._addMessage({ role, tool_call_id, content }); + continue; + } + let parsed; + try { + parsed = (0, RunnableFunction_1.isRunnableFunctionWithParse)(fn) ? await fn.parse(args) : args; + } + catch (error) { + const content = error instanceof Error ? error.message : String(error); + this._addMessage({ role, tool_call_id, content }); + continue; + } + // @ts-expect-error it can't rule out `never` type. + const rawContent = await fn.function(parsed, this); + const content = __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_stringifyFunctionCallResult).call(this, rawContent); + this._addMessage({ role, tool_call_id, content }); + if (singleFunctionToCall) { + return; + } + } + } + return; + } +} +exports.AbstractChatCompletionRunner = AbstractChatCompletionRunner; +_AbstractChatCompletionRunner_connectedPromise = new WeakMap(), _AbstractChatCompletionRunner_resolveConnectedPromise = new WeakMap(), _AbstractChatCompletionRunner_rejectConnectedPromise = new WeakMap(), _AbstractChatCompletionRunner_endPromise = new WeakMap(), _AbstractChatCompletionRunner_resolveEndPromise = new WeakMap(), _AbstractChatCompletionRunner_rejectEndPromise = new WeakMap(), _AbstractChatCompletionRunner_listeners = new WeakMap(), _AbstractChatCompletionRunner_ended = new WeakMap(), _AbstractChatCompletionRunner_errored = new WeakMap(), _AbstractChatCompletionRunner_aborted = new WeakMap(), _AbstractChatCompletionRunner_catchingPromiseCreated = new WeakMap(), _AbstractChatCompletionRunner_handleError = new WeakMap(), _AbstractChatCompletionRunner_instances = new WeakSet(), _AbstractChatCompletionRunner_getFinalContent = function _AbstractChatCompletionRunner_getFinalContent() { + return __classPrivateFieldGet(this, _AbstractChatCompletionRunner_instances, "m", _AbstractChatCompletionRunner_getFinalMessage).call(this).content ?? null; +}, _AbstractChatCompletionRunner_getFinalMessage = function _AbstractChatCompletionRunner_getFinalMessage() { + let i = this.messages.length; + while (i-- > 0) { + const message = this.messages[i]; + if ((0, chatCompletionUtils_1.isAssistantMessage)(message)) { + return { ...message, content: message.content ?? null }; + } + } + throw new error_1.OpenAIError('stream ended without producing a ChatCompletionMessage with role=assistant'); +}, _AbstractChatCompletionRunner_getFinalFunctionCall = function _AbstractChatCompletionRunner_getFinalFunctionCall() { + for (let i = this.messages.length - 1; i >= 0; i--) { + const message = this.messages[i]; + if ((0, chatCompletionUtils_1.isAssistantMessage)(message) && message?.function_call) { + return message.function_call; + } + if ((0, chatCompletionUtils_1.isAssistantMessage)(message) && message?.tool_calls?.length) { + return message.tool_calls.at(-1)?.function; + } + } + return; +}, _AbstractChatCompletionRunner_getFinalFunctionCallResult = function _AbstractChatCompletionRunner_getFinalFunctionCallResult() { + for (let i = this.messages.length - 1; i >= 0; i--) { + const message = this.messages[i]; + if ((0, chatCompletionUtils_1.isFunctionMessage)(message) && message.content != null) { + return message.content; + } + if ((0, chatCompletionUtils_1.isToolMessage)(message) && + message.content != null && + this.messages.some((x) => x.role === 'assistant' && + x.tool_calls?.some((y) => y.type === 'function' && y.id === message.tool_call_id))) { + return message.content; + } + } + return; +}, _AbstractChatCompletionRunner_calculateTotalUsage = function _AbstractChatCompletionRunner_calculateTotalUsage() { + const total = { + completion_tokens: 0, + prompt_tokens: 0, + total_tokens: 0, + }; + for (const { usage } of this._chatCompletions) { + if (usage) { + total.completion_tokens += usage.completion_tokens; + total.prompt_tokens += usage.prompt_tokens; + total.total_tokens += usage.total_tokens; + } + } + return total; +}, _AbstractChatCompletionRunner_validateParams = function _AbstractChatCompletionRunner_validateParams(params) { + if (params.n != null && params.n > 1) { + throw new error_1.OpenAIError('ChatCompletion convenience helpers only support n=1 at this time. To use n>1, please use chat.completions.create() directly.'); + } +}, _AbstractChatCompletionRunner_stringifyFunctionCallResult = function _AbstractChatCompletionRunner_stringifyFunctionCallResult(rawContent) { + return (typeof rawContent === 'string' ? rawContent + : rawContent === undefined ? 'undefined' + : JSON.stringify(rawContent)); +}; +//# sourceMappingURL=AbstractChatCompletionRunner.js.map + +/***/ }), + +/***/ 7514: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _AssistantStream_instances, _AssistantStream_events, _AssistantStream_runStepSnapshots, _AssistantStream_messageSnapshots, _AssistantStream_messageSnapshot, _AssistantStream_finalRun, _AssistantStream_currentContentIndex, _AssistantStream_currentContent, _AssistantStream_currentToolCallIndex, _AssistantStream_currentToolCall, _AssistantStream_currentEvent, _AssistantStream_currentRunSnapshot, _AssistantStream_currentRunStepSnapshot, _AssistantStream_addEvent, _AssistantStream_endRequest, _AssistantStream_handleMessage, _AssistantStream_handleRunStep, _AssistantStream_handleEvent, _AssistantStream_accumulateRunStep, _AssistantStream_accumulateMessage, _AssistantStream_accumulateContent, _AssistantStream_handleRun; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AssistantStream = void 0; +const Core = __importStar(__nccwpck_require__(1798)); +const AbstractAssistantStreamRunner_1 = __nccwpck_require__(9365); +const streaming_1 = __nccwpck_require__(884); +const error_1 = __nccwpck_require__(8905); +class AssistantStream extends AbstractAssistantStreamRunner_1.AbstractAssistantStreamRunner { + constructor() { + super(...arguments); + _AssistantStream_instances.add(this); + //Track all events in a single list for reference + _AssistantStream_events.set(this, []); + //Used to accumulate deltas + //We are accumulating many types so the value here is not strict + _AssistantStream_runStepSnapshots.set(this, {}); + _AssistantStream_messageSnapshots.set(this, {}); + _AssistantStream_messageSnapshot.set(this, void 0); + _AssistantStream_finalRun.set(this, void 0); + _AssistantStream_currentContentIndex.set(this, void 0); + _AssistantStream_currentContent.set(this, void 0); + _AssistantStream_currentToolCallIndex.set(this, void 0); + _AssistantStream_currentToolCall.set(this, void 0); + //For current snapshot methods + _AssistantStream_currentEvent.set(this, void 0); + _AssistantStream_currentRunSnapshot.set(this, void 0); + _AssistantStream_currentRunStepSnapshot.set(this, void 0); + } + [(_AssistantStream_events = new WeakMap(), _AssistantStream_runStepSnapshots = new WeakMap(), _AssistantStream_messageSnapshots = new WeakMap(), _AssistantStream_messageSnapshot = new WeakMap(), _AssistantStream_finalRun = new WeakMap(), _AssistantStream_currentContentIndex = new WeakMap(), _AssistantStream_currentContent = new WeakMap(), _AssistantStream_currentToolCallIndex = new WeakMap(), _AssistantStream_currentToolCall = new WeakMap(), _AssistantStream_currentEvent = new WeakMap(), _AssistantStream_currentRunSnapshot = new WeakMap(), _AssistantStream_currentRunStepSnapshot = new WeakMap(), _AssistantStream_instances = new WeakSet(), Symbol.asyncIterator)]() { + const pushQueue = []; + const readQueue = []; + let done = false; + //Catch all for passing along all events + this.on('event', (event) => { + const reader = readQueue.shift(); + if (reader) { + reader.resolve(event); + } + else { + pushQueue.push(event); + } + }); + this.on('end', () => { + done = true; + for (const reader of readQueue) { + reader.resolve(undefined); + } + readQueue.length = 0; + }); + this.on('abort', (err) => { + done = true; + for (const reader of readQueue) { + reader.reject(err); + } + readQueue.length = 0; + }); + this.on('error', (err) => { + done = true; + for (const reader of readQueue) { + reader.reject(err); + } + readQueue.length = 0; + }); + return { + next: async () => { + if (!pushQueue.length) { + if (done) { + return { value: undefined, done: true }; + } + return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((chunk) => (chunk ? { value: chunk, done: false } : { value: undefined, done: true })); + } + const chunk = pushQueue.shift(); + return { value: chunk, done: false }; + }, + return: async () => { + this.abort(); + return { value: undefined, done: true }; + }, + }; + } + static fromReadableStream(stream) { + const runner = new AssistantStream(); + runner._run(() => runner._fromReadableStream(stream)); + return runner; + } + async _fromReadableStream(readableStream, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + this._connected(); + const stream = streaming_1.Stream.fromReadableStream(readableStream, this.controller); + for await (const event of stream) { + __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event); + } + if (stream.controller.signal?.aborted) { + throw new error_1.APIUserAbortError(); + } + return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this)); + } + toReadableStream() { + const stream = new streaming_1.Stream(this[Symbol.asyncIterator].bind(this), this.controller); + return stream.toReadableStream(); + } + static createToolAssistantStream(threadId, runId, runs, body, options) { + const runner = new AssistantStream(); + runner._run(() => runner._runToolAssistantStream(threadId, runId, runs, body, { + ...options, + headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' }, + })); + return runner; + } + async _createToolAssistantStream(run, threadId, runId, params, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + const body = { ...params, stream: true }; + const stream = await run.submitToolOutputs(threadId, runId, body, { + ...options, + signal: this.controller.signal, + }); + this._connected(); + for await (const event of stream) { + __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event); + } + if (stream.controller.signal?.aborted) { + throw new error_1.APIUserAbortError(); + } + return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this)); + } + static createThreadAssistantStream(body, thread, options) { + const runner = new AssistantStream(); + runner._run(() => runner._threadAssistantStream(body, thread, { + ...options, + headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' }, + })); + return runner; + } + static createAssistantStream(threadId, runs, params, options) { + const runner = new AssistantStream(); + runner._run(() => runner._runAssistantStream(threadId, runs, params, { + ...options, + headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' }, + })); + return runner; + } + currentEvent() { + return __classPrivateFieldGet(this, _AssistantStream_currentEvent, "f"); + } + currentRun() { + return __classPrivateFieldGet(this, _AssistantStream_currentRunSnapshot, "f"); + } + currentMessageSnapshot() { + return __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f"); + } + currentRunStepSnapshot() { + return __classPrivateFieldGet(this, _AssistantStream_currentRunStepSnapshot, "f"); + } + async finalRunSteps() { + await this.done(); + return Object.values(__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")); + } + async finalMessages() { + await this.done(); + return Object.values(__classPrivateFieldGet(this, _AssistantStream_messageSnapshots, "f")); + } + async finalRun() { + await this.done(); + if (!__classPrivateFieldGet(this, _AssistantStream_finalRun, "f")) + throw Error('Final run was not received.'); + return __classPrivateFieldGet(this, _AssistantStream_finalRun, "f"); + } + async _createThreadAssistantStream(thread, params, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + const body = { ...params, stream: true }; + const stream = await thread.createAndRun(body, { ...options, signal: this.controller.signal }); + this._connected(); + for await (const event of stream) { + __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event); + } + if (stream.controller.signal?.aborted) { + throw new error_1.APIUserAbortError(); + } + return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this)); + } + async _createAssistantStream(run, threadId, params, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + const body = { ...params, stream: true }; + const stream = await run.create(threadId, body, { ...options, signal: this.controller.signal }); + this._connected(); + for await (const event of stream) { + __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_addEvent).call(this, event); + } + if (stream.controller.signal?.aborted) { + throw new error_1.APIUserAbortError(); + } + return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this)); + } + static accumulateDelta(acc, delta) { + for (const [key, deltaValue] of Object.entries(delta)) { + if (!acc.hasOwnProperty(key)) { + acc[key] = deltaValue; + continue; + } + let accValue = acc[key]; + if (accValue === null || accValue === undefined) { + acc[key] = deltaValue; + continue; + } + // We don't accumulate these special properties + if (key === 'index' || key === 'type') { + acc[key] = deltaValue; + continue; + } + // Type-specific accumulation logic + if (typeof accValue === 'string' && typeof deltaValue === 'string') { + accValue += deltaValue; + } + else if (typeof accValue === 'number' && typeof deltaValue === 'number') { + accValue += deltaValue; + } + else if (Core.isObj(accValue) && Core.isObj(deltaValue)) { + accValue = this.accumulateDelta(accValue, deltaValue); + } + else if (Array.isArray(accValue) && Array.isArray(deltaValue)) { + if (accValue.every((x) => typeof x === 'string' || typeof x === 'number')) { + accValue.push(...deltaValue); // Use spread syntax for efficient addition + continue; + } + } + else { + throw Error(`Unhandled record type: ${key}, deltaValue: ${deltaValue}, accValue: ${accValue}`); + } + acc[key] = accValue; + } + return acc; + } +} +exports.AssistantStream = AssistantStream; +_AssistantStream_addEvent = function _AssistantStream_addEvent(event) { + if (this.ended) + return; + __classPrivateFieldSet(this, _AssistantStream_currentEvent, event, "f"); + __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_handleEvent).call(this, event); + switch (event.event) { + case 'thread.created': + //No action on this event. + break; + case 'thread.run.created': + case 'thread.run.queued': + case 'thread.run.in_progress': + case 'thread.run.requires_action': + case 'thread.run.completed': + case 'thread.run.failed': + case 'thread.run.cancelling': + case 'thread.run.cancelled': + case 'thread.run.expired': + __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_handleRun).call(this, event); + break; + case 'thread.run.step.created': + case 'thread.run.step.in_progress': + case 'thread.run.step.delta': + case 'thread.run.step.completed': + case 'thread.run.step.failed': + case 'thread.run.step.cancelled': + case 'thread.run.step.expired': + __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_handleRunStep).call(this, event); + break; + case 'thread.message.created': + case 'thread.message.in_progress': + case 'thread.message.delta': + case 'thread.message.completed': + case 'thread.message.incomplete': + __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_handleMessage).call(this, event); + break; + case 'error': + //This is included for completeness, but errors are processed in the SSE event processing so this should not occur + throw new Error('Encountered an error event in event processing - errors should be processed earlier'); + } +}, _AssistantStream_endRequest = function _AssistantStream_endRequest() { + if (this.ended) { + throw new error_1.OpenAIError(`stream has ended, this shouldn't happen`); + } + if (!__classPrivateFieldGet(this, _AssistantStream_finalRun, "f")) + throw Error('Final run has not been received'); + return __classPrivateFieldGet(this, _AssistantStream_finalRun, "f"); +}, _AssistantStream_handleMessage = function _AssistantStream_handleMessage(event) { + const [accumulatedMessage, newContent] = __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_accumulateMessage).call(this, event, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")); + __classPrivateFieldSet(this, _AssistantStream_messageSnapshot, accumulatedMessage, "f"); + __classPrivateFieldGet(this, _AssistantStream_messageSnapshots, "f")[accumulatedMessage.id] = accumulatedMessage; + for (const content of newContent) { + const snapshotContent = accumulatedMessage.content[content.index]; + if (snapshotContent?.type == 'text') { + this._emit('textCreated', snapshotContent.text); + } + } + switch (event.event) { + case 'thread.message.created': + this._emit('messageCreated', event.data); + break; + case 'thread.message.in_progress': + break; + case 'thread.message.delta': + this._emit('messageDelta', event.data.delta, accumulatedMessage); + if (event.data.delta.content) { + for (const content of event.data.delta.content) { + //If it is text delta, emit a text delta event + if (content.type == 'text' && content.text) { + let textDelta = content.text; + let snapshot = accumulatedMessage.content[content.index]; + if (snapshot && snapshot.type == 'text') { + this._emit('textDelta', textDelta, snapshot.text); + } + else { + throw Error('The snapshot associated with this text delta is not text or missing'); + } + } + if (content.index != __classPrivateFieldGet(this, _AssistantStream_currentContentIndex, "f")) { + //See if we have in progress content + if (__classPrivateFieldGet(this, _AssistantStream_currentContent, "f")) { + switch (__classPrivateFieldGet(this, _AssistantStream_currentContent, "f").type) { + case 'text': + this._emit('textDone', __classPrivateFieldGet(this, _AssistantStream_currentContent, "f").text, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")); + break; + case 'image_file': + this._emit('imageFileDone', __classPrivateFieldGet(this, _AssistantStream_currentContent, "f").image_file, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")); + break; + } + } + __classPrivateFieldSet(this, _AssistantStream_currentContentIndex, content.index, "f"); + } + __classPrivateFieldSet(this, _AssistantStream_currentContent, accumulatedMessage.content[content.index], "f"); + } + } + break; + case 'thread.message.completed': + case 'thread.message.incomplete': + //We emit the latest content we were working on on completion (including incomplete) + if (__classPrivateFieldGet(this, _AssistantStream_currentContentIndex, "f") !== undefined) { + const currentContent = event.data.content[__classPrivateFieldGet(this, _AssistantStream_currentContentIndex, "f")]; + if (currentContent) { + switch (currentContent.type) { + case 'image_file': + this._emit('imageFileDone', currentContent.image_file, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")); + break; + case 'text': + this._emit('textDone', currentContent.text, __classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")); + break; + } + } + } + if (__classPrivateFieldGet(this, _AssistantStream_messageSnapshot, "f")) { + this._emit('messageDone', event.data); + } + __classPrivateFieldSet(this, _AssistantStream_messageSnapshot, undefined, "f"); + } +}, _AssistantStream_handleRunStep = function _AssistantStream_handleRunStep(event) { + const accumulatedRunStep = __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_accumulateRunStep).call(this, event); + __classPrivateFieldSet(this, _AssistantStream_currentRunStepSnapshot, accumulatedRunStep, "f"); + switch (event.event) { + case 'thread.run.step.created': + this._emit('runStepCreated', event.data); + break; + case 'thread.run.step.delta': + const delta = event.data.delta; + if (delta.step_details && + delta.step_details.type == 'tool_calls' && + delta.step_details.tool_calls && + accumulatedRunStep.step_details.type == 'tool_calls') { + for (const toolCall of delta.step_details.tool_calls) { + if (toolCall.index == __classPrivateFieldGet(this, _AssistantStream_currentToolCallIndex, "f")) { + this._emit('toolCallDelta', toolCall, accumulatedRunStep.step_details.tool_calls[toolCall.index]); + } + else { + if (__classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")) { + this._emit('toolCallDone', __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")); + } + __classPrivateFieldSet(this, _AssistantStream_currentToolCallIndex, toolCall.index, "f"); + __classPrivateFieldSet(this, _AssistantStream_currentToolCall, accumulatedRunStep.step_details.tool_calls[toolCall.index], "f"); + if (__classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")) + this._emit('toolCallCreated', __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")); + } + } + } + this._emit('runStepDelta', event.data.delta, accumulatedRunStep); + break; + case 'thread.run.step.completed': + case 'thread.run.step.failed': + case 'thread.run.step.cancelled': + case 'thread.run.step.expired': + __classPrivateFieldSet(this, _AssistantStream_currentRunStepSnapshot, undefined, "f"); + const details = event.data.step_details; + if (details.type == 'tool_calls') { + if (__classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")) { + this._emit('toolCallDone', __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")); + __classPrivateFieldSet(this, _AssistantStream_currentToolCall, undefined, "f"); + } + } + this._emit('runStepDone', event.data, accumulatedRunStep); + break; + case 'thread.run.step.in_progress': + break; + } +}, _AssistantStream_handleEvent = function _AssistantStream_handleEvent(event) { + __classPrivateFieldGet(this, _AssistantStream_events, "f").push(event); + this._emit('event', event); +}, _AssistantStream_accumulateRunStep = function _AssistantStream_accumulateRunStep(event) { + switch (event.event) { + case 'thread.run.step.created': + __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id] = event.data; + return event.data; + case 'thread.run.step.delta': + let snapshot = __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id]; + if (!snapshot) { + throw Error('Received a RunStepDelta before creation of a snapshot'); + } + let data = event.data; + if (data.delta) { + const accumulated = AssistantStream.accumulateDelta(snapshot, data.delta); + __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id] = accumulated; + } + return __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id]; + case 'thread.run.step.completed': + case 'thread.run.step.failed': + case 'thread.run.step.cancelled': + case 'thread.run.step.expired': + case 'thread.run.step.in_progress': + __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id] = event.data; + break; + } + if (__classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id]) + return __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id]; + throw new Error('No snapshot available'); +}, _AssistantStream_accumulateMessage = function _AssistantStream_accumulateMessage(event, snapshot) { + let newContent = []; + switch (event.event) { + case 'thread.message.created': + //On creation the snapshot is just the initial message + return [event.data, newContent]; + case 'thread.message.delta': + if (!snapshot) { + throw Error('Received a delta with no existing snapshot (there should be one from message creation)'); + } + let data = event.data; + //If this delta does not have content, nothing to process + if (data.delta.content) { + for (const contentElement of data.delta.content) { + if (contentElement.index in snapshot.content) { + let currentContent = snapshot.content[contentElement.index]; + snapshot.content[contentElement.index] = __classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_accumulateContent).call(this, contentElement, currentContent); + } + else { + snapshot.content[contentElement.index] = contentElement; + // This is a new element + newContent.push(contentElement); + } + } + } + return [snapshot, newContent]; + case 'thread.message.in_progress': + case 'thread.message.completed': + case 'thread.message.incomplete': + //No changes on other thread events + if (snapshot) { + return [snapshot, newContent]; + } + else { + throw Error('Received thread message event with no existing snapshot'); + } + } + throw Error('Tried to accumulate a non-message event'); +}, _AssistantStream_accumulateContent = function _AssistantStream_accumulateContent(contentElement, currentContent) { + return AssistantStream.accumulateDelta(currentContent, contentElement); +}, _AssistantStream_handleRun = function _AssistantStream_handleRun(event) { + __classPrivateFieldSet(this, _AssistantStream_currentRunSnapshot, event.data, "f"); + switch (event.event) { + case 'thread.run.created': + break; + case 'thread.run.queued': + break; + case 'thread.run.in_progress': + break; + case 'thread.run.requires_action': + case 'thread.run.cancelled': + case 'thread.run.failed': + case 'thread.run.completed': + case 'thread.run.expired': + __classPrivateFieldSet(this, _AssistantStream_finalRun, event.data, "f"); + if (__classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")) { + this._emit('toolCallDone', __classPrivateFieldGet(this, _AssistantStream_currentToolCall, "f")); + __classPrivateFieldSet(this, _AssistantStream_currentToolCall, undefined, "f"); + } + break; + case 'thread.run.cancelling': + break; + } +}; +//# sourceMappingURL=AssistantStream.js.map + +/***/ }), + +/***/ 5575: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ChatCompletionRunner = void 0; +const AbstractChatCompletionRunner_1 = __nccwpck_require__(8398); +const chatCompletionUtils_1 = __nccwpck_require__(7858); +class ChatCompletionRunner extends AbstractChatCompletionRunner_1.AbstractChatCompletionRunner { + /** @deprecated - please use `runTools` instead. */ + static runFunctions(completions, params, options) { + const runner = new ChatCompletionRunner(); + const opts = { + ...options, + headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'runFunctions' }, + }; + runner._run(() => runner._runFunctions(completions, params, opts)); + return runner; + } + static runTools(completions, params, options) { + const runner = new ChatCompletionRunner(); + const opts = { + ...options, + headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'runTools' }, + }; + runner._run(() => runner._runTools(completions, params, opts)); + return runner; + } + _addMessage(message) { + super._addMessage(message); + if ((0, chatCompletionUtils_1.isAssistantMessage)(message) && message.content) { + this._emit('content', message.content); + } + } +} +exports.ChatCompletionRunner = ChatCompletionRunner; +//# sourceMappingURL=ChatCompletionRunner.js.map + +/***/ }), + +/***/ 7823: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); + return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); +}; +var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { + if (kind === "m") throw new TypeError("Private method is not writable"); + if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); + if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); + return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; +}; +var _ChatCompletionStream_instances, _ChatCompletionStream_currentChatCompletionSnapshot, _ChatCompletionStream_beginRequest, _ChatCompletionStream_addChunk, _ChatCompletionStream_endRequest, _ChatCompletionStream_accumulateChatCompletion; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ChatCompletionStream = void 0; +const error_1 = __nccwpck_require__(8905); +const AbstractChatCompletionRunner_1 = __nccwpck_require__(8398); +const streaming_1 = __nccwpck_require__(884); +class ChatCompletionStream extends AbstractChatCompletionRunner_1.AbstractChatCompletionRunner { + constructor() { + super(...arguments); + _ChatCompletionStream_instances.add(this); + _ChatCompletionStream_currentChatCompletionSnapshot.set(this, void 0); + } + get currentChatCompletionSnapshot() { + return __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f"); + } + /** + * Intended for use on the frontend, consuming a stream produced with + * `.toReadableStream()` on the backend. + * + * Note that messages sent to the model do not appear in `.on('message')` + * in this context. + */ + static fromReadableStream(stream) { + const runner = new ChatCompletionStream(); + runner._run(() => runner._fromReadableStream(stream)); + return runner; + } + static createChatCompletion(completions, params, options) { + const runner = new ChatCompletionStream(); + runner._run(() => runner._runChatCompletion(completions, { ...params, stream: true }, { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } })); + return runner; + } + async _createChatCompletion(completions, params, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_beginRequest).call(this); + const stream = await completions.create({ ...params, stream: true }, { ...options, signal: this.controller.signal }); + this._connected(); + for await (const chunk of stream) { + __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_addChunk).call(this, chunk); + } + if (stream.controller.signal?.aborted) { + throw new error_1.APIUserAbortError(); + } + return this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this)); + } + async _fromReadableStream(readableStream, options) { + const signal = options?.signal; + if (signal) { + if (signal.aborted) + this.controller.abort(); + signal.addEventListener('abort', () => this.controller.abort()); + } + __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_beginRequest).call(this); + this._connected(); + const stream = streaming_1.Stream.fromReadableStream(readableStream, this.controller); + let chatId; + for await (const chunk of stream) { + if (chatId && chatId !== chunk.id) { + // A new request has been made. + this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this)); + } + __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_addChunk).call(this, chunk); + chatId = chunk.id; + } + if (stream.controller.signal?.aborted) { + throw new error_1.APIUserAbortError(); + } + return this._addChatCompletion(__classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_endRequest).call(this)); + } + [(_ChatCompletionStream_currentChatCompletionSnapshot = new WeakMap(), _ChatCompletionStream_instances = new WeakSet(), _ChatCompletionStream_beginRequest = function _ChatCompletionStream_beginRequest() { + if (this.ended) + return; + __classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, undefined, "f"); + }, _ChatCompletionStream_addChunk = function _ChatCompletionStream_addChunk(chunk) { + if (this.ended) + return; + const completion = __classPrivateFieldGet(this, _ChatCompletionStream_instances, "m", _ChatCompletionStream_accumulateChatCompletion).call(this, chunk); + this._emit('chunk', chunk, completion); + const delta = chunk.choices[0]?.delta?.content; + const snapshot = completion.choices[0]?.message; + if (delta != null && snapshot?.role === 'assistant' && snapshot?.content) { + this._emit('content', delta, snapshot.content); + } + }, _ChatCompletionStream_endRequest = function _ChatCompletionStream_endRequest() { + if (this.ended) { + throw new error_1.OpenAIError(`stream has ended, this shouldn't happen`); + } + const snapshot = __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f"); + if (!snapshot) { + throw new error_1.OpenAIError(`request ended without sending any chunks`); + } + __classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, undefined, "f"); + return finalizeChatCompletion(snapshot); + }, _ChatCompletionStream_accumulateChatCompletion = function _ChatCompletionStream_accumulateChatCompletion(chunk) { + var _a, _b, _c; + let snapshot = __classPrivateFieldGet(this, _ChatCompletionStream_currentChatCompletionSnapshot, "f"); + const { choices, ...rest } = chunk; + if (!snapshot) { + snapshot = __classPrivateFieldSet(this, _ChatCompletionStream_currentChatCompletionSnapshot, { + ...rest, + choices: [], + }, "f"); + } + else { + Object.assign(snapshot, rest); + } + for (const { delta, finish_reason, index, logprobs = null, ...other } of chunk.choices) { + let choice = snapshot.choices[index]; + if (!choice) { + choice = snapshot.choices[index] = { finish_reason, index, message: {}, logprobs, ...other }; + } + if (logprobs) { + if (!choice.logprobs) { + choice.logprobs = Object.assign({}, logprobs); + } + else { + const { content, ...rest } = logprobs; + Object.assign(choice.logprobs, rest); + if (content) { + (_a = choice.logprobs).content ?? (_a.content = []); + choice.logprobs.content.push(...content); + } + } + } + if (finish_reason) + choice.finish_reason = finish_reason; + Object.assign(choice, other); + if (!delta) + continue; // Shouldn't happen; just in case. + const { content, function_call, role, tool_calls, ...rest } = delta; + Object.assign(choice.message, rest); + if (content) + choice.message.content = (choice.message.content || '') + content; + if (role) + choice.message.role = role; + if (function_call) { + if (!choice.message.function_call) { + choice.message.function_call = function_call; + } + else { + if (function_call.name) + choice.message.function_call.name = function_call.name; + if (function_call.arguments) { + (_b = choice.message.function_call).arguments ?? (_b.arguments = ''); + choice.message.function_call.arguments += function_call.arguments; + } + } + } + if (tool_calls) { + if (!choice.message.tool_calls) + choice.message.tool_calls = []; + for (const { index, id, type, function: fn, ...rest } of tool_calls) { + const tool_call = ((_c = choice.message.tool_calls)[index] ?? (_c[index] = {})); + Object.assign(tool_call, rest); + if (id) + tool_call.id = id; + if (type) + tool_call.type = type; + if (fn) + tool_call.function ?? (tool_call.function = { arguments: '' }); + if (fn?.name) + tool_call.function.name = fn.name; + if (fn?.arguments) + tool_call.function.arguments += fn.arguments; + } + } + } + return snapshot; + }, Symbol.asyncIterator)]() { + const pushQueue = []; + const readQueue = []; + let done = false; + this.on('chunk', (chunk) => { + const reader = readQueue.shift(); + if (reader) { + reader.resolve(chunk); + } + else { + pushQueue.push(chunk); + } + }); + this.on('end', () => { + done = true; + for (const reader of readQueue) { + reader.resolve(undefined); + } + readQueue.length = 0; + }); + this.on('abort', (err) => { + done = true; + for (const reader of readQueue) { + reader.reject(err); + } + readQueue.length = 0; + }); + this.on('error', (err) => { + done = true; + for (const reader of readQueue) { + reader.reject(err); + } + readQueue.length = 0; + }); + return { + next: async () => { + if (!pushQueue.length) { + if (done) { + return { value: undefined, done: true }; + } + return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((chunk) => (chunk ? { value: chunk, done: false } : { value: undefined, done: true })); + } + const chunk = pushQueue.shift(); + return { value: chunk, done: false }; + }, + return: async () => { + this.abort(); + return { value: undefined, done: true }; + }, + }; + } + toReadableStream() { + const stream = new streaming_1.Stream(this[Symbol.asyncIterator].bind(this), this.controller); + return stream.toReadableStream(); + } +} +exports.ChatCompletionStream = ChatCompletionStream; +function finalizeChatCompletion(snapshot) { + const { id, choices, created, model, system_fingerprint, ...rest } = snapshot; + return { + ...rest, + id, + choices: choices.map(({ message, finish_reason, index, logprobs, ...choiceRest }) => { + if (!finish_reason) + throw new error_1.OpenAIError(`missing finish_reason for choice ${index}`); + const { content = null, function_call, tool_calls, ...messageRest } = message; + const role = message.role; // this is what we expect; in theory it could be different which would make our types a slight lie but would be fine. + if (!role) + throw new error_1.OpenAIError(`missing role for choice ${index}`); + if (function_call) { + const { arguments: args, name } = function_call; + if (args == null) + throw new error_1.OpenAIError(`missing function_call.arguments for choice ${index}`); + if (!name) + throw new error_1.OpenAIError(`missing function_call.name for choice ${index}`); + return { + ...choiceRest, + message: { content, function_call: { arguments: args, name }, role }, + finish_reason, + index, + logprobs, + }; + } + if (tool_calls) { + return { + ...choiceRest, + index, + finish_reason, + logprobs, + message: { + ...messageRest, + role, + content, + tool_calls: tool_calls.map((tool_call, i) => { + const { function: fn, type, id, ...toolRest } = tool_call; + const { arguments: args, name, ...fnRest } = fn || {}; + if (id == null) + throw new error_1.OpenAIError(`missing choices[${index}].tool_calls[${i}].id\n${str(snapshot)}`); + if (type == null) + throw new error_1.OpenAIError(`missing choices[${index}].tool_calls[${i}].type\n${str(snapshot)}`); + if (name == null) + throw new error_1.OpenAIError(`missing choices[${index}].tool_calls[${i}].function.name\n${str(snapshot)}`); + if (args == null) + throw new error_1.OpenAIError(`missing choices[${index}].tool_calls[${i}].function.arguments\n${str(snapshot)}`); + return { ...toolRest, id, type, function: { ...fnRest, name, arguments: args } }; + }), + }, + }; + } + return { + ...choiceRest, + message: { ...messageRest, content, role }, + finish_reason, + index, + logprobs, + }; + }), + created, + model, + object: 'chat.completion', + ...(system_fingerprint ? { system_fingerprint } : {}), + }; +} +function str(x) { + return JSON.stringify(x); +} +//# sourceMappingURL=ChatCompletionStream.js.map + +/***/ }), + +/***/ 794: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ChatCompletionStreamingRunner = void 0; +const ChatCompletionStream_1 = __nccwpck_require__(7823); +class ChatCompletionStreamingRunner extends ChatCompletionStream_1.ChatCompletionStream { + static fromReadableStream(stream) { + const runner = new ChatCompletionStreamingRunner(); + runner._run(() => runner._fromReadableStream(stream)); + return runner; + } + /** @deprecated - please use `runTools` instead. */ + static runFunctions(completions, params, options) { + const runner = new ChatCompletionStreamingRunner(); + const opts = { + ...options, + headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'runFunctions' }, + }; + runner._run(() => runner._runFunctions(completions, params, opts)); + return runner; + } + static runTools(completions, params, options) { + const runner = new ChatCompletionStreamingRunner(); + const opts = { + ...options, + headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'runTools' }, + }; + runner._run(() => runner._runTools(completions, params, opts)); + return runner; + } +} +exports.ChatCompletionStreamingRunner = ChatCompletionStreamingRunner; +//# sourceMappingURL=ChatCompletionStreamingRunner.js.map + +/***/ }), + +/***/ 5464: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ParsingToolFunction = exports.ParsingFunction = exports.isRunnableFunctionWithParse = void 0; +function isRunnableFunctionWithParse(fn) { + return typeof fn.parse === 'function'; +} +exports.isRunnableFunctionWithParse = isRunnableFunctionWithParse; +/** + * This is helper class for passing a `function` and `parse` where the `function` + * argument type matches the `parse` return type. + * + * @deprecated - please use ParsingToolFunction instead. + */ +class ParsingFunction { + constructor(input) { + this.function = input.function; + this.parse = input.parse; + this.parameters = input.parameters; + this.description = input.description; + this.name = input.name; + } +} +exports.ParsingFunction = ParsingFunction; +/** + * This is helper class for passing a `function` and `parse` where the `function` + * argument type matches the `parse` return type. + */ +class ParsingToolFunction { + constructor(input) { + this.type = 'function'; + this.function = input; + } +} +exports.ParsingToolFunction = ParsingToolFunction; +//# sourceMappingURL=RunnableFunction.js.map + +/***/ }), + +/***/ 2626: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.allSettledWithThrow = void 0; +/** + * Like `Promise.allSettled()` but throws an error if any promises are rejected. + */ +const allSettledWithThrow = async (promises) => { + const results = await Promise.allSettled(promises); + const rejected = results.filter((result) => result.status === 'rejected'); + if (rejected.length) { + for (const result of rejected) { + console.error(result.reason); + } + throw new Error(`${rejected.length} promise(s) failed - see the above errors`); + } + // Note: TS was complaining about using `.filter().map()` here for some reason + const values = []; + for (const result of results) { + if (result.status === 'fulfilled') { + values.push(result.value); + } + } + return values; +}; +exports.allSettledWithThrow = allSettledWithThrow; +//# sourceMappingURL=Util.js.map + +/***/ }), + +/***/ 7858: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.isPresent = exports.isToolMessage = exports.isFunctionMessage = exports.isAssistantMessage = void 0; +const isAssistantMessage = (message) => { + return message?.role === 'assistant'; +}; +exports.isAssistantMessage = isAssistantMessage; +const isFunctionMessage = (message) => { + return message?.role === 'function'; +}; +exports.isFunctionMessage = isFunctionMessage; +const isToolMessage = (message) => { + return message?.role === 'tool'; +}; +exports.isToolMessage = isToolMessage; +function isPresent(obj) { + return obj != null; +} +exports.isPresent = isPresent; +//# sourceMappingURL=chatCompletionUtils.js.map + +/***/ }), + +/***/ 7401: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.CursorPage = exports.Page = void 0; +const core_1 = __nccwpck_require__(1798); +/** + * Note: no pagination actually occurs yet, this is for forwards-compatibility. + */ +class Page extends core_1.AbstractPage { + constructor(client, response, body, options) { + super(client, response, body, options); + this.data = body.data || []; + this.object = body.object; + } + getPaginatedItems() { + return this.data ?? []; + } + // @deprecated Please use `nextPageInfo()` instead + /** + * This page represents a response that isn't actually paginated at the API level + * so there will never be any next page params. + */ + nextPageParams() { + return null; + } + nextPageInfo() { + return null; + } +} +exports.Page = Page; +class CursorPage extends core_1.AbstractPage { + constructor(client, response, body, options) { + super(client, response, body, options); + this.data = body.data || []; + } + getPaginatedItems() { + return this.data ?? []; + } + // @deprecated Please use `nextPageInfo()` instead + nextPageParams() { + const info = this.nextPageInfo(); + if (!info) + return null; + if ('params' in info) + return info.params; + const params = Object.fromEntries(info.url.searchParams); + if (!Object.keys(params).length) + return null; + return params; + } + nextPageInfo() { + const data = this.getPaginatedItems(); + if (!data.length) { + return null; + } + const id = data[data.length - 1]?.id; + if (!id) { + return null; + } + return { params: { after: id } }; + } +} +exports.CursorPage = CursorPage; +//# sourceMappingURL=pagination.js.map + +/***/ }), + +/***/ 9593: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.APIResource = void 0; +class APIResource { + constructor(client) { + this._client = client; + } +} +exports.APIResource = APIResource; +//# sourceMappingURL=resource.js.map + +/***/ }), + +/***/ 6376: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Audio = void 0; +const resource_1 = __nccwpck_require__(9593); +const SpeechAPI = __importStar(__nccwpck_require__(4117)); +const TranscriptionsAPI = __importStar(__nccwpck_require__(5622)); +const TranslationsAPI = __importStar(__nccwpck_require__(7735)); +class Audio extends resource_1.APIResource { + constructor() { + super(...arguments); + this.transcriptions = new TranscriptionsAPI.Transcriptions(this._client); + this.translations = new TranslationsAPI.Translations(this._client); + this.speech = new SpeechAPI.Speech(this._client); + } +} +exports.Audio = Audio; +(function (Audio) { + Audio.Transcriptions = TranscriptionsAPI.Transcriptions; + Audio.Translations = TranslationsAPI.Translations; + Audio.Speech = SpeechAPI.Speech; +})(Audio = exports.Audio || (exports.Audio = {})); +//# sourceMappingURL=audio.js.map + +/***/ }), + +/***/ 4117: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Speech = void 0; +const resource_1 = __nccwpck_require__(9593); +class Speech extends resource_1.APIResource { + /** + * Generates audio from the input text. + */ + create(body, options) { + return this._client.post('/audio/speech', { body, ...options, __binaryResponse: true }); + } +} +exports.Speech = Speech; +(function (Speech) { +})(Speech = exports.Speech || (exports.Speech = {})); +//# sourceMappingURL=speech.js.map + +/***/ }), + +/***/ 5622: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Transcriptions = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +class Transcriptions extends resource_1.APIResource { + /** + * Transcribes audio into the input language. + */ + create(body, options) { + return this._client.post('/audio/transcriptions', (0, core_1.multipartFormRequestOptions)({ body, ...options })); + } +} +exports.Transcriptions = Transcriptions; +(function (Transcriptions) { +})(Transcriptions = exports.Transcriptions || (exports.Transcriptions = {})); +//# sourceMappingURL=transcriptions.js.map + +/***/ }), + +/***/ 7735: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Translations = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +class Translations extends resource_1.APIResource { + /** + * Translates audio into English. + */ + create(body, options) { + return this._client.post('/audio/translations', (0, core_1.multipartFormRequestOptions)({ body, ...options })); + } +} +exports.Translations = Translations; +(function (Translations) { +})(Translations = exports.Translations || (exports.Translations = {})); +//# sourceMappingURL=translations.js.map + +/***/ }), + +/***/ 341: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.BatchesPage = exports.Batches = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const BatchesAPI = __importStar(__nccwpck_require__(341)); +const pagination_1 = __nccwpck_require__(7401); +class Batches extends resource_1.APIResource { + /** + * Creates and executes a batch from an uploaded file of requests + */ + create(body, options) { + return this._client.post('/batches', { body, ...options }); + } + /** + * Retrieves a batch. + */ + retrieve(batchId, options) { + return this._client.get(`/batches/${batchId}`, options); + } + list(query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list({}, query); + } + return this._client.getAPIList('/batches', BatchesPage, { query, ...options }); + } + /** + * Cancels an in-progress batch. + */ + cancel(batchId, options) { + return this._client.post(`/batches/${batchId}/cancel`, options); + } +} +exports.Batches = Batches; +class BatchesPage extends pagination_1.CursorPage { +} +exports.BatchesPage = BatchesPage; +(function (Batches) { + Batches.BatchesPage = BatchesAPI.BatchesPage; +})(Batches = exports.Batches || (exports.Batches = {})); +//# sourceMappingURL=batches.js.map + +/***/ }), + +/***/ 616: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.AssistantsPage = exports.Assistants = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const AssistantsAPI = __importStar(__nccwpck_require__(616)); +const pagination_1 = __nccwpck_require__(7401); +class Assistants extends resource_1.APIResource { + /** + * Create an assistant with a model and instructions. + */ + create(body, options) { + return this._client.post('/assistants', { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Retrieves an assistant. + */ + retrieve(assistantId, options) { + return this._client.get(`/assistants/${assistantId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Modifies an assistant. + */ + update(assistantId, body, options) { + return this._client.post(`/assistants/${assistantId}`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + list(query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list({}, query); + } + return this._client.getAPIList('/assistants', AssistantsPage, { + query, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Delete an assistant. + */ + del(assistantId, options) { + return this._client.delete(`/assistants/${assistantId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } +} +exports.Assistants = Assistants; +class AssistantsPage extends pagination_1.CursorPage { +} +exports.AssistantsPage = AssistantsPage; +(function (Assistants) { + Assistants.AssistantsPage = AssistantsAPI.AssistantsPage; +})(Assistants = exports.Assistants || (exports.Assistants = {})); +//# sourceMappingURL=assistants.js.map + +/***/ }), + +/***/ 853: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Beta = void 0; +const resource_1 = __nccwpck_require__(9593); +const AssistantsAPI = __importStar(__nccwpck_require__(616)); +const ChatAPI = __importStar(__nccwpck_require__(8691)); +const ThreadsAPI = __importStar(__nccwpck_require__(1931)); +const VectorStoresAPI = __importStar(__nccwpck_require__(5822)); +class Beta extends resource_1.APIResource { + constructor() { + super(...arguments); + this.vectorStores = new VectorStoresAPI.VectorStores(this._client); + this.chat = new ChatAPI.Chat(this._client); + this.assistants = new AssistantsAPI.Assistants(this._client); + this.threads = new ThreadsAPI.Threads(this._client); + } +} +exports.Beta = Beta; +(function (Beta) { + Beta.VectorStores = VectorStoresAPI.VectorStores; + Beta.VectorStoresPage = VectorStoresAPI.VectorStoresPage; + Beta.Chat = ChatAPI.Chat; + Beta.Assistants = AssistantsAPI.Assistants; + Beta.AssistantsPage = AssistantsAPI.AssistantsPage; + Beta.Threads = ThreadsAPI.Threads; +})(Beta = exports.Beta || (exports.Beta = {})); +//# sourceMappingURL=beta.js.map + +/***/ }), + +/***/ 8691: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Chat = void 0; +const resource_1 = __nccwpck_require__(9593); +const CompletionsAPI = __importStar(__nccwpck_require__(559)); +class Chat extends resource_1.APIResource { + constructor() { + super(...arguments); + this.completions = new CompletionsAPI.Completions(this._client); + } +} +exports.Chat = Chat; +(function (Chat) { + Chat.Completions = CompletionsAPI.Completions; +})(Chat = exports.Chat || (exports.Chat = {})); +//# sourceMappingURL=chat.js.map + +/***/ }), + +/***/ 559: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Completions = exports.ChatCompletionStream = exports.ParsingToolFunction = exports.ParsingFunction = exports.ChatCompletionStreamingRunner = exports.ChatCompletionRunner = void 0; +const resource_1 = __nccwpck_require__(9593); +const ChatCompletionRunner_1 = __nccwpck_require__(5575); +var ChatCompletionRunner_2 = __nccwpck_require__(5575); +Object.defineProperty(exports, "ChatCompletionRunner", ({ enumerable: true, get: function () { return ChatCompletionRunner_2.ChatCompletionRunner; } })); +const ChatCompletionStreamingRunner_1 = __nccwpck_require__(794); +var ChatCompletionStreamingRunner_2 = __nccwpck_require__(794); +Object.defineProperty(exports, "ChatCompletionStreamingRunner", ({ enumerable: true, get: function () { return ChatCompletionStreamingRunner_2.ChatCompletionStreamingRunner; } })); +var RunnableFunction_1 = __nccwpck_require__(5464); +Object.defineProperty(exports, "ParsingFunction", ({ enumerable: true, get: function () { return RunnableFunction_1.ParsingFunction; } })); +Object.defineProperty(exports, "ParsingToolFunction", ({ enumerable: true, get: function () { return RunnableFunction_1.ParsingToolFunction; } })); +const ChatCompletionStream_1 = __nccwpck_require__(7823); +var ChatCompletionStream_2 = __nccwpck_require__(7823); +Object.defineProperty(exports, "ChatCompletionStream", ({ enumerable: true, get: function () { return ChatCompletionStream_2.ChatCompletionStream; } })); +class Completions extends resource_1.APIResource { + runFunctions(body, options) { + if (body.stream) { + return ChatCompletionStreamingRunner_1.ChatCompletionStreamingRunner.runFunctions(this._client.chat.completions, body, options); + } + return ChatCompletionRunner_1.ChatCompletionRunner.runFunctions(this._client.chat.completions, body, options); + } + runTools(body, options) { + if (body.stream) { + return ChatCompletionStreamingRunner_1.ChatCompletionStreamingRunner.runTools(this._client.chat.completions, body, options); + } + return ChatCompletionRunner_1.ChatCompletionRunner.runTools(this._client.chat.completions, body, options); + } + /** + * Creates a chat completion stream + */ + stream(body, options) { + return ChatCompletionStream_1.ChatCompletionStream.createChatCompletion(this._client.chat.completions, body, options); + } +} +exports.Completions = Completions; +//# sourceMappingURL=completions.js.map + +/***/ }), + +/***/ 1787: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.MessagesPage = exports.Messages = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const MessagesAPI = __importStar(__nccwpck_require__(1787)); +const pagination_1 = __nccwpck_require__(7401); +class Messages extends resource_1.APIResource { + /** + * Create a message. + */ + create(threadId, body, options) { + return this._client.post(`/threads/${threadId}/messages`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Retrieve a message. + */ + retrieve(threadId, messageId, options) { + return this._client.get(`/threads/${threadId}/messages/${messageId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Modifies a message. + */ + update(threadId, messageId, body, options) { + return this._client.post(`/threads/${threadId}/messages/${messageId}`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + list(threadId, query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list(threadId, {}, query); + } + return this._client.getAPIList(`/threads/${threadId}/messages`, MessagesPage, { + query, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Deletes a message. + */ + del(threadId, messageId, options) { + return this._client.delete(`/threads/${threadId}/messages/${messageId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } +} +exports.Messages = Messages; +class MessagesPage extends pagination_1.CursorPage { +} +exports.MessagesPage = MessagesPage; +(function (Messages) { + Messages.MessagesPage = MessagesAPI.MessagesPage; +})(Messages = exports.Messages || (exports.Messages = {})); +//# sourceMappingURL=messages.js.map + +/***/ }), + +/***/ 3187: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.RunsPage = exports.Runs = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const AssistantStream_1 = __nccwpck_require__(7514); +const core_2 = __nccwpck_require__(1798); +const RunsAPI = __importStar(__nccwpck_require__(3187)); +const StepsAPI = __importStar(__nccwpck_require__(2630)); +const pagination_1 = __nccwpck_require__(7401); +class Runs extends resource_1.APIResource { + constructor() { + super(...arguments); + this.steps = new StepsAPI.Steps(this._client); + } + create(threadId, body, options) { + return this._client.post(`/threads/${threadId}/runs`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + stream: body.stream ?? false, + }); + } + /** + * Retrieves a run. + */ + retrieve(threadId, runId, options) { + return this._client.get(`/threads/${threadId}/runs/${runId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Modifies a run. + */ + update(threadId, runId, body, options) { + return this._client.post(`/threads/${threadId}/runs/${runId}`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + list(threadId, query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list(threadId, {}, query); + } + return this._client.getAPIList(`/threads/${threadId}/runs`, RunsPage, { + query, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Cancels a run that is `in_progress`. + */ + cancel(threadId, runId, options) { + return this._client.post(`/threads/${threadId}/runs/${runId}/cancel`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * A helper to create a run an poll for a terminal state. More information on Run + * lifecycles can be found here: + * https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps + */ + async createAndPoll(threadId, body, options) { + const run = await this.create(threadId, body, options); + return await this.poll(threadId, run.id, options); + } + /** + * Create a Run stream + * + * @deprecated use `stream` instead + */ + createAndStream(threadId, body, options) { + return AssistantStream_1.AssistantStream.createAssistantStream(threadId, this._client.beta.threads.runs, body, options); + } + /** + * A helper to poll a run status until it reaches a terminal state. More + * information on Run lifecycles can be found here: + * https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps + */ + async poll(threadId, runId, options) { + const headers = { ...options?.headers, 'X-Stainless-Poll-Helper': 'true' }; + if (options?.pollIntervalMs) { + headers['X-Stainless-Custom-Poll-Interval'] = options.pollIntervalMs.toString(); + } + while (true) { + const { data: run, response } = await this.retrieve(threadId, runId, { + ...options, + headers: { ...options?.headers, ...headers }, + }).withResponse(); + switch (run.status) { + //If we are in any sort of intermediate state we poll + case 'queued': + case 'in_progress': + case 'cancelling': + let sleepInterval = 5000; + if (options?.pollIntervalMs) { + sleepInterval = options.pollIntervalMs; + } + else { + const headerInterval = response.headers.get('openai-poll-after-ms'); + if (headerInterval) { + const headerIntervalMs = parseInt(headerInterval); + if (!isNaN(headerIntervalMs)) { + sleepInterval = headerIntervalMs; + } + } + } + await (0, core_2.sleep)(sleepInterval); + break; + //We return the run in any terminal state. + case 'requires_action': + case 'incomplete': + case 'cancelled': + case 'completed': + case 'failed': + case 'expired': + return run; + } + } + } + /** + * Create a Run stream + */ + stream(threadId, body, options) { + return AssistantStream_1.AssistantStream.createAssistantStream(threadId, this._client.beta.threads.runs, body, options); + } + submitToolOutputs(threadId, runId, body, options) { + return this._client.post(`/threads/${threadId}/runs/${runId}/submit_tool_outputs`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + stream: body.stream ?? false, + }); + } + /** + * A helper to submit a tool output to a run and poll for a terminal run state. + * More information on Run lifecycles can be found here: + * https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps + */ + async submitToolOutputsAndPoll(threadId, runId, body, options) { + const run = await this.submitToolOutputs(threadId, runId, body, options); + return await this.poll(threadId, run.id, options); + } + /** + * Submit the tool outputs from a previous run and stream the run to a terminal + * state. More information on Run lifecycles can be found here: + * https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps + */ + submitToolOutputsStream(threadId, runId, body, options) { + return AssistantStream_1.AssistantStream.createToolAssistantStream(threadId, runId, this._client.beta.threads.runs, body, options); + } +} +exports.Runs = Runs; +class RunsPage extends pagination_1.CursorPage { +} +exports.RunsPage = RunsPage; +(function (Runs) { + Runs.RunsPage = RunsAPI.RunsPage; + Runs.Steps = StepsAPI.Steps; + Runs.RunStepsPage = StepsAPI.RunStepsPage; +})(Runs = exports.Runs || (exports.Runs = {})); +//# sourceMappingURL=runs.js.map + +/***/ }), + +/***/ 2630: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.RunStepsPage = exports.Steps = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const StepsAPI = __importStar(__nccwpck_require__(2630)); +const pagination_1 = __nccwpck_require__(7401); +class Steps extends resource_1.APIResource { + /** + * Retrieves a run step. + */ + retrieve(threadId, runId, stepId, options) { + return this._client.get(`/threads/${threadId}/runs/${runId}/steps/${stepId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + list(threadId, runId, query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list(threadId, runId, {}, query); + } + return this._client.getAPIList(`/threads/${threadId}/runs/${runId}/steps`, RunStepsPage, { + query, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } +} +exports.Steps = Steps; +class RunStepsPage extends pagination_1.CursorPage { +} +exports.RunStepsPage = RunStepsPage; +(function (Steps) { + Steps.RunStepsPage = StepsAPI.RunStepsPage; +})(Steps = exports.Steps || (exports.Steps = {})); +//# sourceMappingURL=steps.js.map + +/***/ }), + +/***/ 1931: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Threads = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const AssistantStream_1 = __nccwpck_require__(7514); +const MessagesAPI = __importStar(__nccwpck_require__(1787)); +const RunsAPI = __importStar(__nccwpck_require__(3187)); +class Threads extends resource_1.APIResource { + constructor() { + super(...arguments); + this.runs = new RunsAPI.Runs(this._client); + this.messages = new MessagesAPI.Messages(this._client); + } + create(body = {}, options) { + if ((0, core_1.isRequestOptions)(body)) { + return this.create({}, body); + } + return this._client.post('/threads', { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Retrieves a thread. + */ + retrieve(threadId, options) { + return this._client.get(`/threads/${threadId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Modifies a thread. + */ + update(threadId, body, options) { + return this._client.post(`/threads/${threadId}`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Delete a thread. + */ + del(threadId, options) { + return this._client.delete(`/threads/${threadId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + createAndRun(body, options) { + return this._client.post('/threads/runs', { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + stream: body.stream ?? false, + }); + } + /** + * A helper to create a thread, start a run and then poll for a terminal state. + * More information on Run lifecycles can be found here: + * https://platform.openai.com/docs/assistants/how-it-works/runs-and-run-steps + */ + async createAndRunPoll(body, options) { + const run = await this.createAndRun(body, options); + return await this.runs.poll(run.thread_id, run.id, options); + } + /** + * Create a thread and stream the run back + */ + createAndRunStream(body, options) { + return AssistantStream_1.AssistantStream.createThreadAssistantStream(body, this._client.beta.threads, options); + } +} +exports.Threads = Threads; +(function (Threads) { + Threads.Runs = RunsAPI.Runs; + Threads.RunsPage = RunsAPI.RunsPage; + Threads.Messages = MessagesAPI.Messages; + Threads.MessagesPage = MessagesAPI.MessagesPage; +})(Threads = exports.Threads || (exports.Threads = {})); +//# sourceMappingURL=threads.js.map + +/***/ }), + +/***/ 3922: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.VectorStoreFilesPage = exports.FileBatches = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const core_2 = __nccwpck_require__(1798); +const Util_1 = __nccwpck_require__(2626); +const files_1 = __nccwpck_require__(9180); +Object.defineProperty(exports, "VectorStoreFilesPage", ({ enumerable: true, get: function () { return files_1.VectorStoreFilesPage; } })); +class FileBatches extends resource_1.APIResource { + /** + * Create a vector store file batch. + */ + create(vectorStoreId, body, options) { + return this._client.post(`/vector_stores/${vectorStoreId}/file_batches`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Retrieves a vector store file batch. + */ + retrieve(vectorStoreId, batchId, options) { + return this._client.get(`/vector_stores/${vectorStoreId}/file_batches/${batchId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Cancel a vector store file batch. This attempts to cancel the processing of + * files in this batch as soon as possible. + */ + cancel(vectorStoreId, batchId, options) { + return this._client.post(`/vector_stores/${vectorStoreId}/file_batches/${batchId}/cancel`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Create a vector store batch and poll until all files have been processed. + */ + async createAndPoll(vectorStoreId, body, options) { + const batch = await this.create(vectorStoreId, body); + return await this.poll(vectorStoreId, batch.id, options); + } + listFiles(vectorStoreId, batchId, query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.listFiles(vectorStoreId, batchId, {}, query); + } + return this._client.getAPIList(`/vector_stores/${vectorStoreId}/file_batches/${batchId}/files`, files_1.VectorStoreFilesPage, { query, ...options, headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers } }); + } + /** + * Wait for the given file batch to be processed. + * + * Note: this will return even if one of the files failed to process, you need to + * check batch.file_counts.failed_count to handle this case. + */ + async poll(vectorStoreId, batchId, options) { + const headers = { ...options?.headers, 'X-Stainless-Poll-Helper': 'true' }; + if (options?.pollIntervalMs) { + headers['X-Stainless-Custom-Poll-Interval'] = options.pollIntervalMs.toString(); + } + while (true) { + const { data: batch, response } = await this.retrieve(vectorStoreId, batchId, { + ...options, + headers, + }).withResponse(); + switch (batch.status) { + case 'in_progress': + let sleepInterval = 5000; + if (options?.pollIntervalMs) { + sleepInterval = options.pollIntervalMs; + } + else { + const headerInterval = response.headers.get('openai-poll-after-ms'); + if (headerInterval) { + const headerIntervalMs = parseInt(headerInterval); + if (!isNaN(headerIntervalMs)) { + sleepInterval = headerIntervalMs; + } + } + } + await (0, core_2.sleep)(sleepInterval); + break; + case 'failed': + case 'cancelled': + case 'completed': + return batch; + } + } + } + /** + * Uploads the given files concurrently and then creates a vector store file batch. + * + * The concurrency limit is configurable using the `maxConcurrency` parameter. + */ + async uploadAndPoll(vectorStoreId, { files, fileIds = [] }, options) { + if (files === null || files.length == 0) { + throw new Error('No files provided to process.'); + } + const configuredConcurrency = options?.maxConcurrency ?? 5; + //We cap the number of workers at the number of files (so we don't start any unnecessary workers) + const concurrencyLimit = Math.min(configuredConcurrency, files.length); + const client = this._client; + const fileIterator = files.values(); + const allFileIds = [...fileIds]; + //This code is based on this design. The libraries don't accommodate our environment limits. + // https://stackoverflow.com/questions/40639432/what-is-the-best-way-to-limit-concurrency-when-using-es6s-promise-all + async function processFiles(iterator) { + for (let item of iterator) { + const fileObj = await client.files.create({ file: item, purpose: 'assistants' }, options); + allFileIds.push(fileObj.id); + } + } + //Start workers to process results + const workers = Array(concurrencyLimit).fill(fileIterator).map(processFiles); + //Wait for all processing to complete. + await (0, Util_1.allSettledWithThrow)(workers); + return await this.createAndPoll(vectorStoreId, { + file_ids: allFileIds, + }); + } +} +exports.FileBatches = FileBatches; +(function (FileBatches) { +})(FileBatches = exports.FileBatches || (exports.FileBatches = {})); +//# sourceMappingURL=file-batches.js.map + +/***/ }), + +/***/ 9180: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.VectorStoreFilesPage = exports.Files = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const core_2 = __nccwpck_require__(1798); +const FilesAPI = __importStar(__nccwpck_require__(9180)); +const pagination_1 = __nccwpck_require__(7401); +class Files extends resource_1.APIResource { + /** + * Create a vector store file by attaching a + * [File](https://platform.openai.com/docs/api-reference/files) to a + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object). + */ + create(vectorStoreId, body, options) { + return this._client.post(`/vector_stores/${vectorStoreId}/files`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Retrieves a vector store file. + */ + retrieve(vectorStoreId, fileId, options) { + return this._client.get(`/vector_stores/${vectorStoreId}/files/${fileId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + list(vectorStoreId, query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list(vectorStoreId, {}, query); + } + return this._client.getAPIList(`/vector_stores/${vectorStoreId}/files`, VectorStoreFilesPage, { + query, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Delete a vector store file. This will remove the file from the vector store but + * the file itself will not be deleted. To delete the file, use the + * [delete file](https://platform.openai.com/docs/api-reference/files/delete) + * endpoint. + */ + del(vectorStoreId, fileId, options) { + return this._client.delete(`/vector_stores/${vectorStoreId}/files/${fileId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Attach a file to the given vector store and wait for it to be processed. + */ + async createAndPoll(vectorStoreId, body, options) { + const file = await this.create(vectorStoreId, body, options); + return await this.poll(vectorStoreId, file.id, options); + } + /** + * Wait for the vector store file to finish processing. + * + * Note: this will return even if the file failed to process, you need to check + * file.last_error and file.status to handle these cases + */ + async poll(vectorStoreId, fileId, options) { + const headers = { ...options?.headers, 'X-Stainless-Poll-Helper': 'true' }; + if (options?.pollIntervalMs) { + headers['X-Stainless-Custom-Poll-Interval'] = options.pollIntervalMs.toString(); + } + while (true) { + const fileResponse = await this.retrieve(vectorStoreId, fileId, { + ...options, + headers, + }).withResponse(); + const file = fileResponse.data; + switch (file.status) { + case 'in_progress': + let sleepInterval = 5000; + if (options?.pollIntervalMs) { + sleepInterval = options.pollIntervalMs; + } + else { + const headerInterval = fileResponse.response.headers.get('openai-poll-after-ms'); + if (headerInterval) { + const headerIntervalMs = parseInt(headerInterval); + if (!isNaN(headerIntervalMs)) { + sleepInterval = headerIntervalMs; + } + } + } + await (0, core_2.sleep)(sleepInterval); + break; + case 'failed': + case 'completed': + return file; + } + } + } + /** + * Upload a file to the `files` API and then attach it to the given vector store. + * + * Note the file will be asynchronously processed (you can use the alternative + * polling helper method to wait for processing to complete). + */ + async upload(vectorStoreId, file, options) { + const fileInfo = await this._client.files.create({ file: file, purpose: 'assistants' }, options); + return this.create(vectorStoreId, { file_id: fileInfo.id }, options); + } + /** + * Add a file to a vector store and poll until processing is complete. + */ + async uploadAndPoll(vectorStoreId, file, options) { + const fileInfo = await this.upload(vectorStoreId, file, options); + return await this.poll(vectorStoreId, fileInfo.id, options); + } +} +exports.Files = Files; +class VectorStoreFilesPage extends pagination_1.CursorPage { +} +exports.VectorStoreFilesPage = VectorStoreFilesPage; +(function (Files) { + Files.VectorStoreFilesPage = FilesAPI.VectorStoreFilesPage; +})(Files = exports.Files || (exports.Files = {})); +//# sourceMappingURL=files.js.map + +/***/ }), + +/***/ 5822: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.VectorStoresPage = exports.VectorStores = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const VectorStoresAPI = __importStar(__nccwpck_require__(5822)); +const FileBatchesAPI = __importStar(__nccwpck_require__(3922)); +const FilesAPI = __importStar(__nccwpck_require__(9180)); +const pagination_1 = __nccwpck_require__(7401); +class VectorStores extends resource_1.APIResource { + constructor() { + super(...arguments); + this.files = new FilesAPI.Files(this._client); + this.fileBatches = new FileBatchesAPI.FileBatches(this._client); + } + /** + * Create a vector store. + */ + create(body, options) { + return this._client.post('/vector_stores', { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Retrieves a vector store. + */ + retrieve(vectorStoreId, options) { + return this._client.get(`/vector_stores/${vectorStoreId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Modifies a vector store. + */ + update(vectorStoreId, body, options) { + return this._client.post(`/vector_stores/${vectorStoreId}`, { + body, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + list(query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list({}, query); + } + return this._client.getAPIList('/vector_stores', VectorStoresPage, { + query, + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } + /** + * Delete a vector store. + */ + del(vectorStoreId, options) { + return this._client.delete(`/vector_stores/${vectorStoreId}`, { + ...options, + headers: { 'OpenAI-Beta': 'assistants=v2', ...options?.headers }, + }); + } +} +exports.VectorStores = VectorStores; +class VectorStoresPage extends pagination_1.CursorPage { +} +exports.VectorStoresPage = VectorStoresPage; +(function (VectorStores) { + VectorStores.VectorStoresPage = VectorStoresAPI.VectorStoresPage; + VectorStores.Files = FilesAPI.Files; + VectorStores.VectorStoreFilesPage = FilesAPI.VectorStoreFilesPage; + VectorStores.FileBatches = FileBatchesAPI.FileBatches; +})(VectorStores = exports.VectorStores || (exports.VectorStores = {})); +//# sourceMappingURL=vector-stores.js.map + +/***/ }), + +/***/ 7670: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Chat = void 0; +const resource_1 = __nccwpck_require__(9593); +const CompletionsAPI = __importStar(__nccwpck_require__(2875)); +class Chat extends resource_1.APIResource { + constructor() { + super(...arguments); + this.completions = new CompletionsAPI.Completions(this._client); + } +} +exports.Chat = Chat; +(function (Chat) { + Chat.Completions = CompletionsAPI.Completions; +})(Chat = exports.Chat || (exports.Chat = {})); +//# sourceMappingURL=chat.js.map + +/***/ }), + +/***/ 2875: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Completions = void 0; +const resource_1 = __nccwpck_require__(9593); +class Completions extends resource_1.APIResource { + create(body, options) { + return this._client.post('/chat/completions', { body, ...options, stream: body.stream ?? false }); + } +} +exports.Completions = Completions; +(function (Completions) { +})(Completions = exports.Completions || (exports.Completions = {})); +//# sourceMappingURL=completions.js.map + +/***/ }), + +/***/ 8240: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Chat = exports.Completions = void 0; +var completions_1 = __nccwpck_require__(2875); +Object.defineProperty(exports, "Completions", ({ enumerable: true, get: function () { return completions_1.Completions; } })); +var chat_1 = __nccwpck_require__(7670); +Object.defineProperty(exports, "Chat", ({ enumerable: true, get: function () { return chat_1.Chat; } })); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 9327: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Completions = void 0; +const resource_1 = __nccwpck_require__(9593); +class Completions extends resource_1.APIResource { + create(body, options) { + return this._client.post('/completions', { body, ...options, stream: body.stream ?? false }); + } +} +exports.Completions = Completions; +(function (Completions) { +})(Completions = exports.Completions || (exports.Completions = {})); +//# sourceMappingURL=completions.js.map + +/***/ }), + +/***/ 8064: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Embeddings = void 0; +const resource_1 = __nccwpck_require__(9593); +class Embeddings extends resource_1.APIResource { + /** + * Creates an embedding vector representing the input text. + */ + create(body, options) { + return this._client.post('/embeddings', { body, ...options }); + } +} +exports.Embeddings = Embeddings; +(function (Embeddings) { +})(Embeddings = exports.Embeddings || (exports.Embeddings = {})); +//# sourceMappingURL=embeddings.js.map + +/***/ }), + +/***/ 3873: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.FileObjectsPage = exports.Files = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const core_2 = __nccwpck_require__(1798); +const error_1 = __nccwpck_require__(8905); +const FilesAPI = __importStar(__nccwpck_require__(3873)); +const core_3 = __nccwpck_require__(1798); +const pagination_1 = __nccwpck_require__(7401); +class Files extends resource_1.APIResource { + /** + * Upload a file that can be used across various endpoints. Individual files can be + * up to 512 MB, and the size of all files uploaded by one organization can be up + * to 100 GB. + * + * The Assistants API supports files up to 2 million tokens and of specific file + * types. See the + * [Assistants Tools guide](https://platform.openai.com/docs/assistants/tools) for + * details. + * + * The Fine-tuning API only supports `.jsonl` files. + * + * The Batch API only supports `.jsonl` files up to 100 MB in size. + * + * Please [contact us](https://help.openai.com/) if you need to increase these + * storage limits. + */ + create(body, options) { + return this._client.post('/files', (0, core_3.multipartFormRequestOptions)({ body, ...options })); + } + /** + * Returns information about a specific file. + */ + retrieve(fileId, options) { + return this._client.get(`/files/${fileId}`, options); + } + list(query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list({}, query); + } + return this._client.getAPIList('/files', FileObjectsPage, { query, ...options }); + } + /** + * Delete a file. + */ + del(fileId, options) { + return this._client.delete(`/files/${fileId}`, options); + } + /** + * Returns the contents of the specified file. + */ + content(fileId, options) { + return this._client.get(`/files/${fileId}/content`, { ...options, __binaryResponse: true }); + } + /** + * Returns the contents of the specified file. + * + * @deprecated The `.content()` method should be used instead + */ + retrieveContent(fileId, options) { + return this._client.get(`/files/${fileId}/content`, { + ...options, + headers: { Accept: 'application/json', ...options?.headers }, + }); + } + /** + * Waits for the given file to be processed, default timeout is 30 mins. + */ + async waitForProcessing(id, { pollInterval = 5000, maxWait = 30 * 60 * 1000 } = {}) { + const TERMINAL_STATES = new Set(['processed', 'error', 'deleted']); + const start = Date.now(); + let file = await this.retrieve(id); + while (!file.status || !TERMINAL_STATES.has(file.status)) { + await (0, core_2.sleep)(pollInterval); + file = await this.retrieve(id); + if (Date.now() - start > maxWait) { + throw new error_1.APIConnectionTimeoutError({ + message: `Giving up on waiting for file ${id} to finish processing after ${maxWait} milliseconds.`, + }); + } + } + return file; + } +} +exports.Files = Files; +/** + * Note: no pagination actually occurs yet, this is for forwards-compatibility. + */ +class FileObjectsPage extends pagination_1.Page { +} +exports.FileObjectsPage = FileObjectsPage; +(function (Files) { + Files.FileObjectsPage = FilesAPI.FileObjectsPage; +})(Files = exports.Files || (exports.Files = {})); +//# sourceMappingURL=files.js.map + +/***/ }), + +/***/ 1364: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.FineTuning = void 0; +const resource_1 = __nccwpck_require__(9593); +const JobsAPI = __importStar(__nccwpck_require__(816)); +class FineTuning extends resource_1.APIResource { + constructor() { + super(...arguments); + this.jobs = new JobsAPI.Jobs(this._client); + } +} +exports.FineTuning = FineTuning; +(function (FineTuning) { + FineTuning.Jobs = JobsAPI.Jobs; + FineTuning.FineTuningJobsPage = JobsAPI.FineTuningJobsPage; + FineTuning.FineTuningJobEventsPage = JobsAPI.FineTuningJobEventsPage; +})(FineTuning = exports.FineTuning || (exports.FineTuning = {})); +//# sourceMappingURL=fine-tuning.js.map + +/***/ }), + +/***/ 3104: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.FineTuningJobCheckpointsPage = exports.Checkpoints = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const CheckpointsAPI = __importStar(__nccwpck_require__(3104)); +const pagination_1 = __nccwpck_require__(7401); +class Checkpoints extends resource_1.APIResource { + list(fineTuningJobId, query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list(fineTuningJobId, {}, query); + } + return this._client.getAPIList(`/fine_tuning/jobs/${fineTuningJobId}/checkpoints`, FineTuningJobCheckpointsPage, { query, ...options }); + } +} +exports.Checkpoints = Checkpoints; +class FineTuningJobCheckpointsPage extends pagination_1.CursorPage { +} +exports.FineTuningJobCheckpointsPage = FineTuningJobCheckpointsPage; +(function (Checkpoints) { + Checkpoints.FineTuningJobCheckpointsPage = CheckpointsAPI.FineTuningJobCheckpointsPage; +})(Checkpoints = exports.Checkpoints || (exports.Checkpoints = {})); +//# sourceMappingURL=checkpoints.js.map + +/***/ }), + +/***/ 816: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.FineTuningJobEventsPage = exports.FineTuningJobsPage = exports.Jobs = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +const JobsAPI = __importStar(__nccwpck_require__(816)); +const CheckpointsAPI = __importStar(__nccwpck_require__(3104)); +const pagination_1 = __nccwpck_require__(7401); +class Jobs extends resource_1.APIResource { + constructor() { + super(...arguments); + this.checkpoints = new CheckpointsAPI.Checkpoints(this._client); + } + /** + * Creates a fine-tuning job which begins the process of creating a new model from + * a given dataset. + * + * Response includes details of the enqueued job including job status and the name + * of the fine-tuned models once complete. + * + * [Learn more about fine-tuning](https://platform.openai.com/docs/guides/fine-tuning) + */ + create(body, options) { + return this._client.post('/fine_tuning/jobs', { body, ...options }); + } + /** + * Get info about a fine-tuning job. + * + * [Learn more about fine-tuning](https://platform.openai.com/docs/guides/fine-tuning) + */ + retrieve(fineTuningJobId, options) { + return this._client.get(`/fine_tuning/jobs/${fineTuningJobId}`, options); + } + list(query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.list({}, query); + } + return this._client.getAPIList('/fine_tuning/jobs', FineTuningJobsPage, { query, ...options }); + } + /** + * Immediately cancel a fine-tune job. + */ + cancel(fineTuningJobId, options) { + return this._client.post(`/fine_tuning/jobs/${fineTuningJobId}/cancel`, options); + } + listEvents(fineTuningJobId, query = {}, options) { + if ((0, core_1.isRequestOptions)(query)) { + return this.listEvents(fineTuningJobId, {}, query); + } + return this._client.getAPIList(`/fine_tuning/jobs/${fineTuningJobId}/events`, FineTuningJobEventsPage, { + query, + ...options, + }); + } +} +exports.Jobs = Jobs; +class FineTuningJobsPage extends pagination_1.CursorPage { +} +exports.FineTuningJobsPage = FineTuningJobsPage; +class FineTuningJobEventsPage extends pagination_1.CursorPage { +} +exports.FineTuningJobEventsPage = FineTuningJobEventsPage; +(function (Jobs) { + Jobs.FineTuningJobsPage = JobsAPI.FineTuningJobsPage; + Jobs.FineTuningJobEventsPage = JobsAPI.FineTuningJobEventsPage; + Jobs.Checkpoints = CheckpointsAPI.Checkpoints; + Jobs.FineTuningJobCheckpointsPage = CheckpointsAPI.FineTuningJobCheckpointsPage; +})(Jobs = exports.Jobs || (exports.Jobs = {})); +//# sourceMappingURL=jobs.js.map + +/***/ }), + +/***/ 2621: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Images = void 0; +const resource_1 = __nccwpck_require__(9593); +const core_1 = __nccwpck_require__(1798); +class Images extends resource_1.APIResource { + /** + * Creates a variation of a given image. + */ + createVariation(body, options) { + return this._client.post('/images/variations', (0, core_1.multipartFormRequestOptions)({ body, ...options })); + } + /** + * Creates an edited or extended image given an original image and a prompt. + */ + edit(body, options) { + return this._client.post('/images/edits', (0, core_1.multipartFormRequestOptions)({ body, ...options })); + } + /** + * Creates an image given a prompt. + */ + generate(body, options) { + return this._client.post('/images/generations', { body, ...options }); + } +} +exports.Images = Images; +(function (Images) { +})(Images = exports.Images || (exports.Images = {})); +//# sourceMappingURL=images.js.map + +/***/ }), + +/***/ 5690: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __exportStar = (this && this.__exportStar) || function(m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Moderations = exports.Models = exports.ModelsPage = exports.Images = exports.FineTuning = exports.Files = exports.FileObjectsPage = exports.Embeddings = exports.Completions = exports.Beta = exports.Batches = exports.BatchesPage = exports.Audio = void 0; +__exportStar(__nccwpck_require__(8240), exports); +__exportStar(__nccwpck_require__(4866), exports); +var audio_1 = __nccwpck_require__(6376); +Object.defineProperty(exports, "Audio", ({ enumerable: true, get: function () { return audio_1.Audio; } })); +var batches_1 = __nccwpck_require__(341); +Object.defineProperty(exports, "BatchesPage", ({ enumerable: true, get: function () { return batches_1.BatchesPage; } })); +Object.defineProperty(exports, "Batches", ({ enumerable: true, get: function () { return batches_1.Batches; } })); +var beta_1 = __nccwpck_require__(853); +Object.defineProperty(exports, "Beta", ({ enumerable: true, get: function () { return beta_1.Beta; } })); +var completions_1 = __nccwpck_require__(9327); +Object.defineProperty(exports, "Completions", ({ enumerable: true, get: function () { return completions_1.Completions; } })); +var embeddings_1 = __nccwpck_require__(8064); +Object.defineProperty(exports, "Embeddings", ({ enumerable: true, get: function () { return embeddings_1.Embeddings; } })); +var files_1 = __nccwpck_require__(3873); +Object.defineProperty(exports, "FileObjectsPage", ({ enumerable: true, get: function () { return files_1.FileObjectsPage; } })); +Object.defineProperty(exports, "Files", ({ enumerable: true, get: function () { return files_1.Files; } })); +var fine_tuning_1 = __nccwpck_require__(1364); +Object.defineProperty(exports, "FineTuning", ({ enumerable: true, get: function () { return fine_tuning_1.FineTuning; } })); +var images_1 = __nccwpck_require__(2621); +Object.defineProperty(exports, "Images", ({ enumerable: true, get: function () { return images_1.Images; } })); +var models_1 = __nccwpck_require__(6467); +Object.defineProperty(exports, "ModelsPage", ({ enumerable: true, get: function () { return models_1.ModelsPage; } })); +Object.defineProperty(exports, "Models", ({ enumerable: true, get: function () { return models_1.Models; } })); +var moderations_1 = __nccwpck_require__(2085); +Object.defineProperty(exports, "Moderations", ({ enumerable: true, get: function () { return moderations_1.Moderations; } })); +//# sourceMappingURL=index.js.map + +/***/ }), + +/***/ 6467: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.ModelsPage = exports.Models = void 0; +const resource_1 = __nccwpck_require__(9593); +const ModelsAPI = __importStar(__nccwpck_require__(6467)); +const pagination_1 = __nccwpck_require__(7401); +class Models extends resource_1.APIResource { + /** + * Retrieves a model instance, providing basic information about the model such as + * the owner and permissioning. + */ + retrieve(model, options) { + return this._client.get(`/models/${model}`, options); + } + /** + * Lists the currently available models, and provides basic information about each + * one such as the owner and availability. + */ + list(options) { + return this._client.getAPIList('/models', ModelsPage, options); + } + /** + * Delete a fine-tuned model. You must have the Owner role in your organization to + * delete a model. + */ + del(model, options) { + return this._client.delete(`/models/${model}`, options); + } +} +exports.Models = Models; +/** + * Note: no pagination actually occurs yet, this is for forwards-compatibility. + */ +class ModelsPage extends pagination_1.Page { +} +exports.ModelsPage = ModelsPage; +(function (Models) { + Models.ModelsPage = ModelsAPI.ModelsPage; +})(Models = exports.Models || (exports.Models = {})); +//# sourceMappingURL=models.js.map + +/***/ }), + +/***/ 2085: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.Moderations = void 0; +const resource_1 = __nccwpck_require__(9593); +class Moderations extends resource_1.APIResource { + /** + * Classifies if text is potentially harmful. + */ + create(body, options) { + return this._client.post('/moderations', { body, ...options }); + } +} +exports.Moderations = Moderations; +(function (Moderations) { +})(Moderations = exports.Moderations || (exports.Moderations = {})); +//# sourceMappingURL=moderations.js.map + +/***/ }), + +/***/ 4866: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +Object.defineProperty(exports, "__esModule", ({ value: true })); +//# sourceMappingURL=shared.js.map + +/***/ }), + +/***/ 884: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.readableStreamAsyncIterable = exports._decodeChunks = exports._iterSSEMessages = exports.Stream = void 0; +const index_1 = __nccwpck_require__(6678); +const error_1 = __nccwpck_require__(8905); +const error_2 = __nccwpck_require__(8905); +class Stream { + constructor(iterator, controller) { + this.iterator = iterator; + this.controller = controller; + } + static fromSSEResponse(response, controller) { + let consumed = false; + async function* iterator() { + if (consumed) { + throw new Error('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + for await (const sse of _iterSSEMessages(response, controller)) { + if (done) + continue; + if (sse.data.startsWith('[DONE]')) { + done = true; + continue; + } + if (sse.event === null) { + let data; + try { + data = JSON.parse(sse.data); + } + catch (e) { + console.error(`Could not parse message into JSON:`, sse.data); + console.error(`From chunk:`, sse.raw); + throw e; + } + if (data && data.error) { + throw new error_2.APIError(undefined, data.error, undefined, undefined); + } + yield data; + } + else { + let data; + try { + data = JSON.parse(sse.data); + } + catch (e) { + console.error(`Could not parse message into JSON:`, sse.data); + console.error(`From chunk:`, sse.raw); + throw e; + } + // TODO: Is this where the error should be thrown? + if (sse.event == 'error') { + throw new error_2.APIError(undefined, data.error, data.message, undefined); + } + yield { event: sse.event, data: data }; + } + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (e instanceof Error && e.name === 'AbortError') + return; + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + } + return new Stream(iterator, controller); + } + /** + * Generates a Stream from a newline-separated ReadableStream + * where each item is a JSON value. + */ + static fromReadableStream(readableStream, controller) { + let consumed = false; + async function* iterLines() { + const lineDecoder = new LineDecoder(); + const iter = readableStreamAsyncIterable(readableStream); + for await (const chunk of iter) { + for (const line of lineDecoder.decode(chunk)) { + yield line; + } + } + for (const line of lineDecoder.flush()) { + yield line; + } + } + async function* iterator() { + if (consumed) { + throw new Error('Cannot iterate over a consumed stream, use `.tee()` to split the stream.'); + } + consumed = true; + let done = false; + try { + for await (const line of iterLines()) { + if (done) + continue; + if (line) + yield JSON.parse(line); + } + done = true; + } + catch (e) { + // If the user calls `stream.controller.abort()`, we should exit without throwing. + if (e instanceof Error && e.name === 'AbortError') + return; + throw e; + } + finally { + // If the user `break`s, abort the ongoing request. + if (!done) + controller.abort(); + } + } + return new Stream(iterator, controller); + } + [Symbol.asyncIterator]() { + return this.iterator(); + } + /** + * Splits the stream into two streams which can be + * independently read from at different speeds. + */ + tee() { + const left = []; + const right = []; + const iterator = this.iterator(); + const teeIterator = (queue) => { + return { + next: () => { + if (queue.length === 0) { + const result = iterator.next(); + left.push(result); + right.push(result); + } + return queue.shift(); + }, + }; + }; + return [ + new Stream(() => teeIterator(left), this.controller), + new Stream(() => teeIterator(right), this.controller), + ]; + } + /** + * Converts this stream to a newline-separated ReadableStream of + * JSON stringified values in the stream + * which can be turned back into a Stream with `Stream.fromReadableStream()`. + */ + toReadableStream() { + const self = this; + let iter; + const encoder = new TextEncoder(); + return new index_1.ReadableStream({ + async start() { + iter = self[Symbol.asyncIterator](); + }, + async pull(ctrl) { + try { + const { value, done } = await iter.next(); + if (done) + return ctrl.close(); + const bytes = encoder.encode(JSON.stringify(value) + '\n'); + ctrl.enqueue(bytes); + } + catch (err) { + ctrl.error(err); + } + }, + async cancel() { + await iter.return?.(); + }, + }); + } +} +exports.Stream = Stream; +async function* _iterSSEMessages(response, controller) { + if (!response.body) { + controller.abort(); + throw new error_1.OpenAIError(`Attempted to iterate over a response with no body`); + } + const sseDecoder = new SSEDecoder(); + const lineDecoder = new LineDecoder(); + const iter = readableStreamAsyncIterable(response.body); + for await (const sseChunk of iterSSEChunks(iter)) { + for (const line of lineDecoder.decode(sseChunk)) { + const sse = sseDecoder.decode(line); + if (sse) + yield sse; + } + } + for (const line of lineDecoder.flush()) { + const sse = sseDecoder.decode(line); + if (sse) + yield sse; + } +} +exports._iterSSEMessages = _iterSSEMessages; +/** + * Given an async iterable iterator, iterates over it and yields full + * SSE chunks, i.e. yields when a double new-line is encountered. + */ +async function* iterSSEChunks(iterator) { + let data = new Uint8Array(); + for await (const chunk of iterator) { + if (chunk == null) { + continue; + } + const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk) + : typeof chunk === 'string' ? new TextEncoder().encode(chunk) + : chunk; + let newData = new Uint8Array(data.length + binaryChunk.length); + newData.set(data); + newData.set(binaryChunk, data.length); + data = newData; + let patternIndex; + while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) { + yield data.slice(0, patternIndex); + data = data.slice(patternIndex); + } + } + if (data.length > 0) { + yield data; + } +} +function findDoubleNewlineIndex(buffer) { + // This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n) + // and returns the index right after the first occurrence of any pattern, + // or -1 if none of the patterns are found. + const newline = 0x0a; // \n + const carriage = 0x0d; // \r + for (let i = 0; i < buffer.length - 2; i++) { + if (buffer[i] === newline && buffer[i + 1] === newline) { + // \n\n + return i + 2; + } + if (buffer[i] === carriage && buffer[i + 1] === carriage) { + // \r\r + return i + 2; + } + if (buffer[i] === carriage && + buffer[i + 1] === newline && + i + 3 < buffer.length && + buffer[i + 2] === carriage && + buffer[i + 3] === newline) { + // \r\n\r\n + return i + 4; + } + } + return -1; +} +class SSEDecoder { + constructor() { + this.event = null; + this.data = []; + this.chunks = []; + } + decode(line) { + if (line.endsWith('\r')) { + line = line.substring(0, line.length - 1); + } + if (!line) { + // empty line and we didn't previously encounter any messages + if (!this.event && !this.data.length) + return null; + const sse = { + event: this.event, + data: this.data.join('\n'), + raw: this.chunks, + }; + this.event = null; + this.data = []; + this.chunks = []; + return sse; + } + this.chunks.push(line); + if (line.startsWith(':')) { + return null; + } + let [fieldname, _, value] = partition(line, ':'); + if (value.startsWith(' ')) { + value = value.substring(1); + } + if (fieldname === 'event') { + this.event = value; + } + else if (fieldname === 'data') { + this.data.push(value); + } + return null; + } +} +/** + * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally + * reading lines from text. + * + * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258 + */ +class LineDecoder { + constructor() { + this.buffer = []; + this.trailingCR = false; + } + decode(chunk) { + let text = this.decodeText(chunk); + if (this.trailingCR) { + text = '\r' + text; + this.trailingCR = false; + } + if (text.endsWith('\r')) { + this.trailingCR = true; + text = text.slice(0, -1); + } + if (!text) { + return []; + } + const trailingNewline = LineDecoder.NEWLINE_CHARS.has(text[text.length - 1] || ''); + let lines = text.split(LineDecoder.NEWLINE_REGEXP); + // if there is a trailing new line then the last entry will be an empty + // string which we don't care about + if (trailingNewline) { + lines.pop(); + } + if (lines.length === 1 && !trailingNewline) { + this.buffer.push(lines[0]); + return []; + } + if (this.buffer.length > 0) { + lines = [this.buffer.join('') + lines[0], ...lines.slice(1)]; + this.buffer = []; + } + if (!trailingNewline) { + this.buffer = [lines.pop() || '']; + } + return lines; + } + decodeText(bytes) { + if (bytes == null) + return ''; + if (typeof bytes === 'string') + return bytes; + // Node: + if (typeof Buffer !== 'undefined') { + if (bytes instanceof Buffer) { + return bytes.toString(); + } + if (bytes instanceof Uint8Array) { + return Buffer.from(bytes).toString(); + } + throw new error_1.OpenAIError(`Unexpected: received non-Uint8Array (${bytes.constructor.name}) stream chunk in an environment with a global "Buffer" defined, which this library assumes to be Node. Please report this error.`); + } + // Browser + if (typeof TextDecoder !== 'undefined') { + if (bytes instanceof Uint8Array || bytes instanceof ArrayBuffer) { + this.textDecoder ?? (this.textDecoder = new TextDecoder('utf8')); + return this.textDecoder.decode(bytes); + } + throw new error_1.OpenAIError(`Unexpected: received non-Uint8Array/ArrayBuffer (${bytes.constructor.name}) in a web platform. Please report this error.`); + } + throw new error_1.OpenAIError(`Unexpected: neither Buffer nor TextDecoder are available as globals. Please report this error.`); + } + flush() { + if (!this.buffer.length && !this.trailingCR) { + return []; + } + const lines = [this.buffer.join('')]; + this.buffer = []; + this.trailingCR = false; + return lines; + } +} +// prettier-ignore +LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']); +LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g; +/** This is an internal helper function that's just used for testing */ +function _decodeChunks(chunks) { + const decoder = new LineDecoder(); + const lines = []; + for (const chunk of chunks) { + lines.push(...decoder.decode(chunk)); + } + return lines; +} +exports._decodeChunks = _decodeChunks; +function partition(str, delimiter) { + const index = str.indexOf(delimiter); + if (index !== -1) { + return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)]; + } + return [str, '', '']; +} +/** + * Most browsers don't yet have async iterable support for ReadableStream, + * and Node has a very different way of reading bytes from its "ReadableStream". + * + * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490 + */ +function readableStreamAsyncIterable(stream) { + if (stream[Symbol.asyncIterator]) + return stream; + const reader = stream.getReader(); + return { + async next() { + try { + const result = await reader.read(); + if (result?.done) + reader.releaseLock(); // release lock when stream becomes closed + return result; + } + catch (e) { + reader.releaseLock(); // release lock when stream becomes errored + throw e; + } + }, + async return() { + const cancelPromise = reader.cancel(); + reader.releaseLock(); + await cancelPromise; + return { done: true, value: undefined }; + }, + [Symbol.asyncIterator]() { + return this; + }, + }; +} +exports.readableStreamAsyncIterable = readableStreamAsyncIterable; +//# sourceMappingURL=streaming.js.map + +/***/ }), + +/***/ 3394: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createForm = exports.multipartFormRequestOptions = exports.maybeMultipartFormRequestOptions = exports.isMultipartBody = exports.toFile = exports.isUploadable = exports.isBlobLike = exports.isFileLike = exports.isResponseLike = exports.fileFromPath = void 0; +const index_1 = __nccwpck_require__(6678); +var index_2 = __nccwpck_require__(6678); +Object.defineProperty(exports, "fileFromPath", ({ enumerable: true, get: function () { return index_2.fileFromPath; } })); +const isResponseLike = (value) => value != null && + typeof value === 'object' && + typeof value.url === 'string' && + typeof value.blob === 'function'; +exports.isResponseLike = isResponseLike; +const isFileLike = (value) => value != null && + typeof value === 'object' && + typeof value.name === 'string' && + typeof value.lastModified === 'number' && + (0, exports.isBlobLike)(value); +exports.isFileLike = isFileLike; +/** + * The BlobLike type omits arrayBuffer() because @types/node-fetch@^2.6.4 lacks it; but this check + * adds the arrayBuffer() method type because it is available and used at runtime + */ +const isBlobLike = (value) => value != null && + typeof value === 'object' && + typeof value.size === 'number' && + typeof value.type === 'string' && + typeof value.text === 'function' && + typeof value.slice === 'function' && + typeof value.arrayBuffer === 'function'; +exports.isBlobLike = isBlobLike; +const isUploadable = (value) => { + return (0, exports.isFileLike)(value) || (0, exports.isResponseLike)(value) || (0, index_1.isFsReadStream)(value); +}; +exports.isUploadable = isUploadable; +/** + * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats + * @param value the raw content of the file. Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s + * @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible + * @param {Object=} options additional properties + * @param {string=} options.type the MIME type of the content + * @param {number=} options.lastModified the last modified timestamp + * @returns a {@link File} with the given properties + */ +async function toFile(value, name, options) { + // If it's a promise, resolve it. + value = await value; + // Use the file's options if there isn't one provided + options ?? (options = (0, exports.isFileLike)(value) ? { lastModified: value.lastModified, type: value.type } : {}); + if ((0, exports.isResponseLike)(value)) { + const blob = await value.blob(); + name || (name = new URL(value.url).pathname.split(/[\\/]/).pop() ?? 'unknown_file'); + return new index_1.File([blob], name, options); + } + const bits = await getBytes(value); + name || (name = getName(value) ?? 'unknown_file'); + if (!options.type) { + const type = bits[0]?.type; + if (typeof type === 'string') { + options = { ...options, type }; + } + } + return new index_1.File(bits, name, options); +} +exports.toFile = toFile; +async function getBytes(value) { + let parts = []; + if (typeof value === 'string' || + ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc. + value instanceof ArrayBuffer) { + parts.push(value); + } + else if ((0, exports.isBlobLike)(value)) { + parts.push(await value.arrayBuffer()); + } + else if (isAsyncIterableIterator(value) // includes Readable, ReadableStream, etc. + ) { + for await (const chunk of value) { + parts.push(chunk); // TODO, consider validating? + } + } + else { + throw new Error(`Unexpected data type: ${typeof value}; constructor: ${value?.constructor + ?.name}; props: ${propsForError(value)}`); + } + return parts; +} +function propsForError(value) { + const props = Object.getOwnPropertyNames(value); + return `[${props.map((p) => `"${p}"`).join(', ')}]`; +} +function getName(value) { + return (getStringFromMaybeBuffer(value.name) || + getStringFromMaybeBuffer(value.filename) || + // For fs.ReadStream + getStringFromMaybeBuffer(value.path)?.split(/[\\/]/).pop()); +} +const getStringFromMaybeBuffer = (x) => { + if (typeof x === 'string') + return x; + if (typeof Buffer !== 'undefined' && x instanceof Buffer) + return String(x); + return undefined; +}; +const isAsyncIterableIterator = (value) => value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function'; +const isMultipartBody = (body) => body && typeof body === 'object' && body.body && body[Symbol.toStringTag] === 'MultipartBody'; +exports.isMultipartBody = isMultipartBody; +/** + * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value. + * Otherwise returns the request as is. + */ +const maybeMultipartFormRequestOptions = async (opts) => { + if (!hasUploadableValue(opts.body)) + return opts; + const form = await (0, exports.createForm)(opts.body); + return (0, index_1.getMultipartRequestOptions)(form, opts); +}; +exports.maybeMultipartFormRequestOptions = maybeMultipartFormRequestOptions; +const multipartFormRequestOptions = async (opts) => { + const form = await (0, exports.createForm)(opts.body); + return (0, index_1.getMultipartRequestOptions)(form, opts); +}; +exports.multipartFormRequestOptions = multipartFormRequestOptions; +const createForm = async (body) => { + const form = new index_1.FormData(); + await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value))); + return form; +}; +exports.createForm = createForm; +const hasUploadableValue = (value) => { + if ((0, exports.isUploadable)(value)) + return true; + if (Array.isArray(value)) + return value.some(hasUploadableValue); + if (value && typeof value === 'object') { + for (const k in value) { + if (hasUploadableValue(value[k])) + return true; + } + } + return false; +}; +const addFormValue = async (form, key, value) => { + if (value === undefined) + return; + if (value == null) { + throw new TypeError(`Received null for "${key}"; to pass null in FormData, you must use the string 'null'`); + } + // TODO: make nested formats configurable + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + form.append(key, String(value)); + } + else if ((0, exports.isUploadable)(value)) { + const file = await toFile(value); + form.append(key, file); + } + else if (Array.isArray(value)) { + await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry))); + } + else if (typeof value === 'object') { + await Promise.all(Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop))); + } + else { + throw new TypeError(`Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`); + } +}; +//# sourceMappingURL=uploads.js.map + +/***/ }), + +/***/ 6417: +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.VERSION = void 0; +exports.VERSION = '4.47.2'; // x-release-please-version +//# sourceMappingURL=version.js.map + +/***/ }), + +/***/ 1907: +/***/ ((module) => { + +"use strict"; +module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"],[[47,47],"disallowed_STD3_valid"],[[48,57],"valid"],[[58,64],"disallowed_STD3_valid"],[[65,65],"mapped",[97]],[[66,66],"mapped",[98]],[[67,67],"mapped",[99]],[[68,68],"mapped",[100]],[[69,69],"mapped",[101]],[[70,70],"mapped",[102]],[[71,71],"mapped",[103]],[[72,72],"mapped",[104]],[[73,73],"mapped",[105]],[[74,74],"mapped",[106]],[[75,75],"mapped",[107]],[[76,76],"mapped",[108]],[[77,77],"mapped",[109]],[[78,78],"mapped",[110]],[[79,79],"mapped",[111]],[[80,80],"mapped",[112]],[[81,81],"mapped",[113]],[[82,82],"mapped",[114]],[[83,83],"mapped",[115]],[[84,84],"mapped",[116]],[[85,85],"mapped",[117]],[[86,86],"mapped",[118]],[[87,87],"mapped",[119]],[[88,88],"mapped",[120]],[[89,89],"mapped",[121]],[[90,90],"mapped",[122]],[[91,96],"disallowed_STD3_valid"],[[97,122],"valid"],[[123,127],"disallowed_STD3_valid"],[[128,159],"disallowed"],[[160,160],"disallowed_STD3_mapped",[32]],[[161,167],"valid",[],"NV8"],[[168,168],"disallowed_STD3_mapped",[32,776]],[[169,169],"valid",[],"NV8"],[[170,170],"mapped",[97]],[[171,172],"valid",[],"NV8"],[[173,173],"ignored"],[[174,174],"valid",[],"NV8"],[[175,175],"disallowed_STD3_mapped",[32,772]],[[176,177],"valid",[],"NV8"],[[178,178],"mapped",[50]],[[179,179],"mapped",[51]],[[180,180],"disallowed_STD3_mapped",[32,769]],[[181,181],"mapped",[956]],[[182,182],"valid",[],"NV8"],[[183,183],"valid"],[[184,184],"disallowed_STD3_mapped",[32,807]],[[185,185],"mapped",[49]],[[186,186],"mapped",[111]],[[187,187],"valid",[],"NV8"],[[188,188],"mapped",[49,8260,52]],[[189,189],"mapped",[49,8260,50]],[[190,190],"mapped",[51,8260,52]],[[191,191],"valid",[],"NV8"],[[192,192],"mapped",[224]],[[193,193],"mapped",[225]],[[194,194],"mapped",[226]],[[195,195],"mapped",[227]],[[196,196],"mapped",[228]],[[197,197],"mapped",[229]],[[198,198],"mapped",[230]],[[199,199],"mapped",[231]],[[200,200],"mapped",[232]],[[201,201],"mapped",[233]],[[202,202],"mapped",[234]],[[203,203],"mapped",[235]],[[204,204],"mapped",[236]],[[205,205],"mapped",[237]],[[206,206],"mapped",[238]],[[207,207],"mapped",[239]],[[208,208],"mapped",[240]],[[209,209],"mapped",[241]],[[210,210],"mapped",[242]],[[211,211],"mapped",[243]],[[212,212],"mapped",[244]],[[213,213],"mapped",[245]],[[214,214],"mapped",[246]],[[215,215],"valid",[],"NV8"],[[216,216],"mapped",[248]],[[217,217],"mapped",[249]],[[218,218],"mapped",[250]],[[219,219],"mapped",[251]],[[220,220],"mapped",[252]],[[221,221],"mapped",[253]],[[222,222],"mapped",[254]],[[223,223],"deviation",[115,115]],[[224,246],"valid"],[[247,247],"valid",[],"NV8"],[[248,255],"valid"],[[256,256],"mapped",[257]],[[257,257],"valid"],[[258,258],"mapped",[259]],[[259,259],"valid"],[[260,260],"mapped",[261]],[[261,261],"valid"],[[262,262],"mapped",[263]],[[263,263],"valid"],[[264,264],"mapped",[265]],[[265,265],"valid"],[[266,266],"mapped",[267]],[[267,267],"valid"],[[268,268],"mapped",[269]],[[269,269],"valid"],[[270,270],"mapped",[271]],[[271,271],"valid"],[[272,272],"mapped",[273]],[[273,273],"valid"],[[274,274],"mapped",[275]],[[275,275],"valid"],[[276,276],"mapped",[277]],[[277,277],"valid"],[[278,278],"mapped",[279]],[[279,279],"valid"],[[280,280],"mapped",[281]],[[281,281],"valid"],[[282,282],"mapped",[283]],[[283,283],"valid"],[[284,284],"mapped",[285]],[[285,285],"valid"],[[286,286],"mapped",[287]],[[287,287],"valid"],[[288,288],"mapped",[289]],[[289,289],"valid"],[[290,290],"mapped",[291]],[[291,291],"valid"],[[292,292],"mapped",[293]],[[293,293],"valid"],[[294,294],"mapped",[295]],[[295,295],"valid"],[[296,296],"mapped",[297]],[[297,297],"valid"],[[298,298],"mapped",[299]],[[299,299],"valid"],[[300,300],"mapped",[301]],[[301,301],"valid"],[[302,302],"mapped",[303]],[[303,303],"valid"],[[304,304],"mapped",[105,775]],[[305,305],"valid"],[[306,307],"mapped",[105,106]],[[308,308],"mapped",[309]],[[309,309],"valid"],[[310,310],"mapped",[311]],[[311,312],"valid"],[[313,313],"mapped",[314]],[[314,314],"valid"],[[315,315],"mapped",[316]],[[316,316],"valid"],[[317,317],"mapped",[318]],[[318,318],"valid"],[[319,320],"mapped",[108,183]],[[321,321],"mapped",[322]],[[322,322],"valid"],[[323,323],"mapped",[324]],[[324,324],"valid"],[[325,325],"mapped",[326]],[[326,326],"valid"],[[327,327],"mapped",[328]],[[328,328],"valid"],[[329,329],"mapped",[700,110]],[[330,330],"mapped",[331]],[[331,331],"valid"],[[332,332],"mapped",[333]],[[333,333],"valid"],[[334,334],"mapped",[335]],[[335,335],"valid"],[[336,336],"mapped",[337]],[[337,337],"valid"],[[338,338],"mapped",[339]],[[339,339],"valid"],[[340,340],"mapped",[341]],[[341,341],"valid"],[[342,342],"mapped",[343]],[[343,343],"valid"],[[344,344],"mapped",[345]],[[345,345],"valid"],[[346,346],"mapped",[347]],[[347,347],"valid"],[[348,348],"mapped",[349]],[[349,349],"valid"],[[350,350],"mapped",[351]],[[351,351],"valid"],[[352,352],"mapped",[353]],[[353,353],"valid"],[[354,354],"mapped",[355]],[[355,355],"valid"],[[356,356],"mapped",[357]],[[357,357],"valid"],[[358,358],"mapped",[359]],[[359,359],"valid"],[[360,360],"mapped",[361]],[[361,361],"valid"],[[362,362],"mapped",[363]],[[363,363],"valid"],[[364,364],"mapped",[365]],[[365,365],"valid"],[[366,366],"mapped",[367]],[[367,367],"valid"],[[368,368],"mapped",[369]],[[369,369],"valid"],[[370,370],"mapped",[371]],[[371,371],"valid"],[[372,372],"mapped",[373]],[[373,373],"valid"],[[374,374],"mapped",[375]],[[375,375],"valid"],[[376,376],"mapped",[255]],[[377,377],"mapped",[378]],[[378,378],"valid"],[[379,379],"mapped",[380]],[[380,380],"valid"],[[381,381],"mapped",[382]],[[382,382],"valid"],[[383,383],"mapped",[115]],[[384,384],"valid"],[[385,385],"mapped",[595]],[[386,386],"mapped",[387]],[[387,387],"valid"],[[388,388],"mapped",[389]],[[389,389],"valid"],[[390,390],"mapped",[596]],[[391,391],"mapped",[392]],[[392,392],"valid"],[[393,393],"mapped",[598]],[[394,394],"mapped",[599]],[[395,395],"mapped",[396]],[[396,397],"valid"],[[398,398],"mapped",[477]],[[399,399],"mapped",[601]],[[400,400],"mapped",[603]],[[401,401],"mapped",[402]],[[402,402],"valid"],[[403,403],"mapped",[608]],[[404,404],"mapped",[611]],[[405,405],"valid"],[[406,406],"mapped",[617]],[[407,407],"mapped",[616]],[[408,408],"mapped",[409]],[[409,411],"valid"],[[412,412],"mapped",[623]],[[413,413],"mapped",[626]],[[414,414],"valid"],[[415,415],"mapped",[629]],[[416,416],"mapped",[417]],[[417,417],"valid"],[[418,418],"mapped",[419]],[[419,419],"valid"],[[420,420],"mapped",[421]],[[421,421],"valid"],[[422,422],"mapped",[640]],[[423,423],"mapped",[424]],[[424,424],"valid"],[[425,425],"mapped",[643]],[[426,427],"valid"],[[428,428],"mapped",[429]],[[429,429],"valid"],[[430,430],"mapped",[648]],[[431,431],"mapped",[432]],[[432,432],"valid"],[[433,433],"mapped",[650]],[[434,434],"mapped",[651]],[[435,435],"mapped",[436]],[[436,436],"valid"],[[437,437],"mapped",[438]],[[438,438],"valid"],[[439,439],"mapped",[658]],[[440,440],"mapped",[441]],[[441,443],"valid"],[[444,444],"mapped",[445]],[[445,451],"valid"],[[452,454],"mapped",[100,382]],[[455,457],"mapped",[108,106]],[[458,460],"mapped",[110,106]],[[461,461],"mapped",[462]],[[462,462],"valid"],[[463,463],"mapped",[464]],[[464,464],"valid"],[[465,465],"mapped",[466]],[[466,466],"valid"],[[467,467],"mapped",[468]],[[468,468],"valid"],[[469,469],"mapped",[470]],[[470,470],"valid"],[[471,471],"mapped",[472]],[[472,472],"valid"],[[473,473],"mapped",[474]],[[474,474],"valid"],[[475,475],"mapped",[476]],[[476,477],"valid"],[[478,478],"mapped",[479]],[[479,479],"valid"],[[480,480],"mapped",[481]],[[481,481],"valid"],[[482,482],"mapped",[483]],[[483,483],"valid"],[[484,484],"mapped",[485]],[[485,485],"valid"],[[486,486],"mapped",[487]],[[487,487],"valid"],[[488,488],"mapped",[489]],[[489,489],"valid"],[[490,490],"mapped",[491]],[[491,491],"valid"],[[492,492],"mapped",[493]],[[493,493],"valid"],[[494,494],"mapped",[495]],[[495,496],"valid"],[[497,499],"mapped",[100,122]],[[500,500],"mapped",[501]],[[501,501],"valid"],[[502,502],"mapped",[405]],[[503,503],"mapped",[447]],[[504,504],"mapped",[505]],[[505,505],"valid"],[[506,506],"mapped",[507]],[[507,507],"valid"],[[508,508],"mapped",[509]],[[509,509],"valid"],[[510,510],"mapped",[511]],[[511,511],"valid"],[[512,512],"mapped",[513]],[[513,513],"valid"],[[514,514],"mapped",[515]],[[515,515],"valid"],[[516,516],"mapped",[517]],[[517,517],"valid"],[[518,518],"mapped",[519]],[[519,519],"valid"],[[520,520],"mapped",[521]],[[521,521],"valid"],[[522,522],"mapped",[523]],[[523,523],"valid"],[[524,524],"mapped",[525]],[[525,525],"valid"],[[526,526],"mapped",[527]],[[527,527],"valid"],[[528,528],"mapped",[529]],[[529,529],"valid"],[[530,530],"mapped",[531]],[[531,531],"valid"],[[532,532],"mapped",[533]],[[533,533],"valid"],[[534,534],"mapped",[535]],[[535,535],"valid"],[[536,536],"mapped",[537]],[[537,537],"valid"],[[538,538],"mapped",[539]],[[539,539],"valid"],[[540,540],"mapped",[541]],[[541,541],"valid"],[[542,542],"mapped",[543]],[[543,543],"valid"],[[544,544],"mapped",[414]],[[545,545],"valid"],[[546,546],"mapped",[547]],[[547,547],"valid"],[[548,548],"mapped",[549]],[[549,549],"valid"],[[550,550],"mapped",[551]],[[551,551],"valid"],[[552,552],"mapped",[553]],[[553,553],"valid"],[[554,554],"mapped",[555]],[[555,555],"valid"],[[556,556],"mapped",[557]],[[557,557],"valid"],[[558,558],"mapped",[559]],[[559,559],"valid"],[[560,560],"mapped",[561]],[[561,561],"valid"],[[562,562],"mapped",[563]],[[563,563],"valid"],[[564,566],"valid"],[[567,569],"valid"],[[570,570],"mapped",[11365]],[[571,571],"mapped",[572]],[[572,572],"valid"],[[573,573],"mapped",[410]],[[574,574],"mapped",[11366]],[[575,576],"valid"],[[577,577],"mapped",[578]],[[578,578],"valid"],[[579,579],"mapped",[384]],[[580,580],"mapped",[649]],[[581,581],"mapped",[652]],[[582,582],"mapped",[583]],[[583,583],"valid"],[[584,584],"mapped",[585]],[[585,585],"valid"],[[586,586],"mapped",[587]],[[587,587],"valid"],[[588,588],"mapped",[589]],[[589,589],"valid"],[[590,590],"mapped",[591]],[[591,591],"valid"],[[592,680],"valid"],[[681,685],"valid"],[[686,687],"valid"],[[688,688],"mapped",[104]],[[689,689],"mapped",[614]],[[690,690],"mapped",[106]],[[691,691],"mapped",[114]],[[692,692],"mapped",[633]],[[693,693],"mapped",[635]],[[694,694],"mapped",[641]],[[695,695],"mapped",[119]],[[696,696],"mapped",[121]],[[697,705],"valid"],[[706,709],"valid",[],"NV8"],[[710,721],"valid"],[[722,727],"valid",[],"NV8"],[[728,728],"disallowed_STD3_mapped",[32,774]],[[729,729],"disallowed_STD3_mapped",[32,775]],[[730,730],"disallowed_STD3_mapped",[32,778]],[[731,731],"disallowed_STD3_mapped",[32,808]],[[732,732],"disallowed_STD3_mapped",[32,771]],[[733,733],"disallowed_STD3_mapped",[32,779]],[[734,734],"valid",[],"NV8"],[[735,735],"valid",[],"NV8"],[[736,736],"mapped",[611]],[[737,737],"mapped",[108]],[[738,738],"mapped",[115]],[[739,739],"mapped",[120]],[[740,740],"mapped",[661]],[[741,745],"valid",[],"NV8"],[[746,747],"valid",[],"NV8"],[[748,748],"valid"],[[749,749],"valid",[],"NV8"],[[750,750],"valid"],[[751,767],"valid",[],"NV8"],[[768,831],"valid"],[[832,832],"mapped",[768]],[[833,833],"mapped",[769]],[[834,834],"valid"],[[835,835],"mapped",[787]],[[836,836],"mapped",[776,769]],[[837,837],"mapped",[953]],[[838,846],"valid"],[[847,847],"ignored"],[[848,855],"valid"],[[856,860],"valid"],[[861,863],"valid"],[[864,865],"valid"],[[866,866],"valid"],[[867,879],"valid"],[[880,880],"mapped",[881]],[[881,881],"valid"],[[882,882],"mapped",[883]],[[883,883],"valid"],[[884,884],"mapped",[697]],[[885,885],"valid"],[[886,886],"mapped",[887]],[[887,887],"valid"],[[888,889],"disallowed"],[[890,890],"disallowed_STD3_mapped",[32,953]],[[891,893],"valid"],[[894,894],"disallowed_STD3_mapped",[59]],[[895,895],"mapped",[1011]],[[896,899],"disallowed"],[[900,900],"disallowed_STD3_mapped",[32,769]],[[901,901],"disallowed_STD3_mapped",[32,776,769]],[[902,902],"mapped",[940]],[[903,903],"mapped",[183]],[[904,904],"mapped",[941]],[[905,905],"mapped",[942]],[[906,906],"mapped",[943]],[[907,907],"disallowed"],[[908,908],"mapped",[972]],[[909,909],"disallowed"],[[910,910],"mapped",[973]],[[911,911],"mapped",[974]],[[912,912],"valid"],[[913,913],"mapped",[945]],[[914,914],"mapped",[946]],[[915,915],"mapped",[947]],[[916,916],"mapped",[948]],[[917,917],"mapped",[949]],[[918,918],"mapped",[950]],[[919,919],"mapped",[951]],[[920,920],"mapped",[952]],[[921,921],"mapped",[953]],[[922,922],"mapped",[954]],[[923,923],"mapped",[955]],[[924,924],"mapped",[956]],[[925,925],"mapped",[957]],[[926,926],"mapped",[958]],[[927,927],"mapped",[959]],[[928,928],"mapped",[960]],[[929,929],"mapped",[961]],[[930,930],"disallowed"],[[931,931],"mapped",[963]],[[932,932],"mapped",[964]],[[933,933],"mapped",[965]],[[934,934],"mapped",[966]],[[935,935],"mapped",[967]],[[936,936],"mapped",[968]],[[937,937],"mapped",[969]],[[938,938],"mapped",[970]],[[939,939],"mapped",[971]],[[940,961],"valid"],[[962,962],"deviation",[963]],[[963,974],"valid"],[[975,975],"mapped",[983]],[[976,976],"mapped",[946]],[[977,977],"mapped",[952]],[[978,978],"mapped",[965]],[[979,979],"mapped",[973]],[[980,980],"mapped",[971]],[[981,981],"mapped",[966]],[[982,982],"mapped",[960]],[[983,983],"valid"],[[984,984],"mapped",[985]],[[985,985],"valid"],[[986,986],"mapped",[987]],[[987,987],"valid"],[[988,988],"mapped",[989]],[[989,989],"valid"],[[990,990],"mapped",[991]],[[991,991],"valid"],[[992,992],"mapped",[993]],[[993,993],"valid"],[[994,994],"mapped",[995]],[[995,995],"valid"],[[996,996],"mapped",[997]],[[997,997],"valid"],[[998,998],"mapped",[999]],[[999,999],"valid"],[[1000,1000],"mapped",[1001]],[[1001,1001],"valid"],[[1002,1002],"mapped",[1003]],[[1003,1003],"valid"],[[1004,1004],"mapped",[1005]],[[1005,1005],"valid"],[[1006,1006],"mapped",[1007]],[[1007,1007],"valid"],[[1008,1008],"mapped",[954]],[[1009,1009],"mapped",[961]],[[1010,1010],"mapped",[963]],[[1011,1011],"valid"],[[1012,1012],"mapped",[952]],[[1013,1013],"mapped",[949]],[[1014,1014],"valid",[],"NV8"],[[1015,1015],"mapped",[1016]],[[1016,1016],"valid"],[[1017,1017],"mapped",[963]],[[1018,1018],"mapped",[1019]],[[1019,1019],"valid"],[[1020,1020],"valid"],[[1021,1021],"mapped",[891]],[[1022,1022],"mapped",[892]],[[1023,1023],"mapped",[893]],[[1024,1024],"mapped",[1104]],[[1025,1025],"mapped",[1105]],[[1026,1026],"mapped",[1106]],[[1027,1027],"mapped",[1107]],[[1028,1028],"mapped",[1108]],[[1029,1029],"mapped",[1109]],[[1030,1030],"mapped",[1110]],[[1031,1031],"mapped",[1111]],[[1032,1032],"mapped",[1112]],[[1033,1033],"mapped",[1113]],[[1034,1034],"mapped",[1114]],[[1035,1035],"mapped",[1115]],[[1036,1036],"mapped",[1116]],[[1037,1037],"mapped",[1117]],[[1038,1038],"mapped",[1118]],[[1039,1039],"mapped",[1119]],[[1040,1040],"mapped",[1072]],[[1041,1041],"mapped",[1073]],[[1042,1042],"mapped",[1074]],[[1043,1043],"mapped",[1075]],[[1044,1044],"mapped",[1076]],[[1045,1045],"mapped",[1077]],[[1046,1046],"mapped",[1078]],[[1047,1047],"mapped",[1079]],[[1048,1048],"mapped",[1080]],[[1049,1049],"mapped",[1081]],[[1050,1050],"mapped",[1082]],[[1051,1051],"mapped",[1083]],[[1052,1052],"mapped",[1084]],[[1053,1053],"mapped",[1085]],[[1054,1054],"mapped",[1086]],[[1055,1055],"mapped",[1087]],[[1056,1056],"mapped",[1088]],[[1057,1057],"mapped",[1089]],[[1058,1058],"mapped",[1090]],[[1059,1059],"mapped",[1091]],[[1060,1060],"mapped",[1092]],[[1061,1061],"mapped",[1093]],[[1062,1062],"mapped",[1094]],[[1063,1063],"mapped",[1095]],[[1064,1064],"mapped",[1096]],[[1065,1065],"mapped",[1097]],[[1066,1066],"mapped",[1098]],[[1067,1067],"mapped",[1099]],[[1068,1068],"mapped",[1100]],[[1069,1069],"mapped",[1101]],[[1070,1070],"mapped",[1102]],[[1071,1071],"mapped",[1103]],[[1072,1103],"valid"],[[1104,1104],"valid"],[[1105,1116],"valid"],[[1117,1117],"valid"],[[1118,1119],"valid"],[[1120,1120],"mapped",[1121]],[[1121,1121],"valid"],[[1122,1122],"mapped",[1123]],[[1123,1123],"valid"],[[1124,1124],"mapped",[1125]],[[1125,1125],"valid"],[[1126,1126],"mapped",[1127]],[[1127,1127],"valid"],[[1128,1128],"mapped",[1129]],[[1129,1129],"valid"],[[1130,1130],"mapped",[1131]],[[1131,1131],"valid"],[[1132,1132],"mapped",[1133]],[[1133,1133],"valid"],[[1134,1134],"mapped",[1135]],[[1135,1135],"valid"],[[1136,1136],"mapped",[1137]],[[1137,1137],"valid"],[[1138,1138],"mapped",[1139]],[[1139,1139],"valid"],[[1140,1140],"mapped",[1141]],[[1141,1141],"valid"],[[1142,1142],"mapped",[1143]],[[1143,1143],"valid"],[[1144,1144],"mapped",[1145]],[[1145,1145],"valid"],[[1146,1146],"mapped",[1147]],[[1147,1147],"valid"],[[1148,1148],"mapped",[1149]],[[1149,1149],"valid"],[[1150,1150],"mapped",[1151]],[[1151,1151],"valid"],[[1152,1152],"mapped",[1153]],[[1153,1153],"valid"],[[1154,1154],"valid",[],"NV8"],[[1155,1158],"valid"],[[1159,1159],"valid"],[[1160,1161],"valid",[],"NV8"],[[1162,1162],"mapped",[1163]],[[1163,1163],"valid"],[[1164,1164],"mapped",[1165]],[[1165,1165],"valid"],[[1166,1166],"mapped",[1167]],[[1167,1167],"valid"],[[1168,1168],"mapped",[1169]],[[1169,1169],"valid"],[[1170,1170],"mapped",[1171]],[[1171,1171],"valid"],[[1172,1172],"mapped",[1173]],[[1173,1173],"valid"],[[1174,1174],"mapped",[1175]],[[1175,1175],"valid"],[[1176,1176],"mapped",[1177]],[[1177,1177],"valid"],[[1178,1178],"mapped",[1179]],[[1179,1179],"valid"],[[1180,1180],"mapped",[1181]],[[1181,1181],"valid"],[[1182,1182],"mapped",[1183]],[[1183,1183],"valid"],[[1184,1184],"mapped",[1185]],[[1185,1185],"valid"],[[1186,1186],"mapped",[1187]],[[1187,1187],"valid"],[[1188,1188],"mapped",[1189]],[[1189,1189],"valid"],[[1190,1190],"mapped",[1191]],[[1191,1191],"valid"],[[1192,1192],"mapped",[1193]],[[1193,1193],"valid"],[[1194,1194],"mapped",[1195]],[[1195,1195],"valid"],[[1196,1196],"mapped",[1197]],[[1197,1197],"valid"],[[1198,1198],"mapped",[1199]],[[1199,1199],"valid"],[[1200,1200],"mapped",[1201]],[[1201,1201],"valid"],[[1202,1202],"mapped",[1203]],[[1203,1203],"valid"],[[1204,1204],"mapped",[1205]],[[1205,1205],"valid"],[[1206,1206],"mapped",[1207]],[[1207,1207],"valid"],[[1208,1208],"mapped",[1209]],[[1209,1209],"valid"],[[1210,1210],"mapped",[1211]],[[1211,1211],"valid"],[[1212,1212],"mapped",[1213]],[[1213,1213],"valid"],[[1214,1214],"mapped",[1215]],[[1215,1215],"valid"],[[1216,1216],"disallowed"],[[1217,1217],"mapped",[1218]],[[1218,1218],"valid"],[[1219,1219],"mapped",[1220]],[[1220,1220],"valid"],[[1221,1221],"mapped",[1222]],[[1222,1222],"valid"],[[1223,1223],"mapped",[1224]],[[1224,1224],"valid"],[[1225,1225],"mapped",[1226]],[[1226,1226],"valid"],[[1227,1227],"mapped",[1228]],[[1228,1228],"valid"],[[1229,1229],"mapped",[1230]],[[1230,1230],"valid"],[[1231,1231],"valid"],[[1232,1232],"mapped",[1233]],[[1233,1233],"valid"],[[1234,1234],"mapped",[1235]],[[1235,1235],"valid"],[[1236,1236],"mapped",[1237]],[[1237,1237],"valid"],[[1238,1238],"mapped",[1239]],[[1239,1239],"valid"],[[1240,1240],"mapped",[1241]],[[1241,1241],"valid"],[[1242,1242],"mapped",[1243]],[[1243,1243],"valid"],[[1244,1244],"mapped",[1245]],[[1245,1245],"valid"],[[1246,1246],"mapped",[1247]],[[1247,1247],"valid"],[[1248,1248],"mapped",[1249]],[[1249,1249],"valid"],[[1250,1250],"mapped",[1251]],[[1251,1251],"valid"],[[1252,1252],"mapped",[1253]],[[1253,1253],"valid"],[[1254,1254],"mapped",[1255]],[[1255,1255],"valid"],[[1256,1256],"mapped",[1257]],[[1257,1257],"valid"],[[1258,1258],"mapped",[1259]],[[1259,1259],"valid"],[[1260,1260],"mapped",[1261]],[[1261,1261],"valid"],[[1262,1262],"mapped",[1263]],[[1263,1263],"valid"],[[1264,1264],"mapped",[1265]],[[1265,1265],"valid"],[[1266,1266],"mapped",[1267]],[[1267,1267],"valid"],[[1268,1268],"mapped",[1269]],[[1269,1269],"valid"],[[1270,1270],"mapped",[1271]],[[1271,1271],"valid"],[[1272,1272],"mapped",[1273]],[[1273,1273],"valid"],[[1274,1274],"mapped",[1275]],[[1275,1275],"valid"],[[1276,1276],"mapped",[1277]],[[1277,1277],"valid"],[[1278,1278],"mapped",[1279]],[[1279,1279],"valid"],[[1280,1280],"mapped",[1281]],[[1281,1281],"valid"],[[1282,1282],"mapped",[1283]],[[1283,1283],"valid"],[[1284,1284],"mapped",[1285]],[[1285,1285],"valid"],[[1286,1286],"mapped",[1287]],[[1287,1287],"valid"],[[1288,1288],"mapped",[1289]],[[1289,1289],"valid"],[[1290,1290],"mapped",[1291]],[[1291,1291],"valid"],[[1292,1292],"mapped",[1293]],[[1293,1293],"valid"],[[1294,1294],"mapped",[1295]],[[1295,1295],"valid"],[[1296,1296],"mapped",[1297]],[[1297,1297],"valid"],[[1298,1298],"mapped",[1299]],[[1299,1299],"valid"],[[1300,1300],"mapped",[1301]],[[1301,1301],"valid"],[[1302,1302],"mapped",[1303]],[[1303,1303],"valid"],[[1304,1304],"mapped",[1305]],[[1305,1305],"valid"],[[1306,1306],"mapped",[1307]],[[1307,1307],"valid"],[[1308,1308],"mapped",[1309]],[[1309,1309],"valid"],[[1310,1310],"mapped",[1311]],[[1311,1311],"valid"],[[1312,1312],"mapped",[1313]],[[1313,1313],"valid"],[[1314,1314],"mapped",[1315]],[[1315,1315],"valid"],[[1316,1316],"mapped",[1317]],[[1317,1317],"valid"],[[1318,1318],"mapped",[1319]],[[1319,1319],"valid"],[[1320,1320],"mapped",[1321]],[[1321,1321],"valid"],[[1322,1322],"mapped",[1323]],[[1323,1323],"valid"],[[1324,1324],"mapped",[1325]],[[1325,1325],"valid"],[[1326,1326],"mapped",[1327]],[[1327,1327],"valid"],[[1328,1328],"disallowed"],[[1329,1329],"mapped",[1377]],[[1330,1330],"mapped",[1378]],[[1331,1331],"mapped",[1379]],[[1332,1332],"mapped",[1380]],[[1333,1333],"mapped",[1381]],[[1334,1334],"mapped",[1382]],[[1335,1335],"mapped",[1383]],[[1336,1336],"mapped",[1384]],[[1337,1337],"mapped",[1385]],[[1338,1338],"mapped",[1386]],[[1339,1339],"mapped",[1387]],[[1340,1340],"mapped",[1388]],[[1341,1341],"mapped",[1389]],[[1342,1342],"mapped",[1390]],[[1343,1343],"mapped",[1391]],[[1344,1344],"mapped",[1392]],[[1345,1345],"mapped",[1393]],[[1346,1346],"mapped",[1394]],[[1347,1347],"mapped",[1395]],[[1348,1348],"mapped",[1396]],[[1349,1349],"mapped",[1397]],[[1350,1350],"mapped",[1398]],[[1351,1351],"mapped",[1399]],[[1352,1352],"mapped",[1400]],[[1353,1353],"mapped",[1401]],[[1354,1354],"mapped",[1402]],[[1355,1355],"mapped",[1403]],[[1356,1356],"mapped",[1404]],[[1357,1357],"mapped",[1405]],[[1358,1358],"mapped",[1406]],[[1359,1359],"mapped",[1407]],[[1360,1360],"mapped",[1408]],[[1361,1361],"mapped",[1409]],[[1362,1362],"mapped",[1410]],[[1363,1363],"mapped",[1411]],[[1364,1364],"mapped",[1412]],[[1365,1365],"mapped",[1413]],[[1366,1366],"mapped",[1414]],[[1367,1368],"disallowed"],[[1369,1369],"valid"],[[1370,1375],"valid",[],"NV8"],[[1376,1376],"disallowed"],[[1377,1414],"valid"],[[1415,1415],"mapped",[1381,1410]],[[1416,1416],"disallowed"],[[1417,1417],"valid",[],"NV8"],[[1418,1418],"valid",[],"NV8"],[[1419,1420],"disallowed"],[[1421,1422],"valid",[],"NV8"],[[1423,1423],"valid",[],"NV8"],[[1424,1424],"disallowed"],[[1425,1441],"valid"],[[1442,1442],"valid"],[[1443,1455],"valid"],[[1456,1465],"valid"],[[1466,1466],"valid"],[[1467,1469],"valid"],[[1470,1470],"valid",[],"NV8"],[[1471,1471],"valid"],[[1472,1472],"valid",[],"NV8"],[[1473,1474],"valid"],[[1475,1475],"valid",[],"NV8"],[[1476,1476],"valid"],[[1477,1477],"valid"],[[1478,1478],"valid",[],"NV8"],[[1479,1479],"valid"],[[1480,1487],"disallowed"],[[1488,1514],"valid"],[[1515,1519],"disallowed"],[[1520,1524],"valid"],[[1525,1535],"disallowed"],[[1536,1539],"disallowed"],[[1540,1540],"disallowed"],[[1541,1541],"disallowed"],[[1542,1546],"valid",[],"NV8"],[[1547,1547],"valid",[],"NV8"],[[1548,1548],"valid",[],"NV8"],[[1549,1551],"valid",[],"NV8"],[[1552,1557],"valid"],[[1558,1562],"valid"],[[1563,1563],"valid",[],"NV8"],[[1564,1564],"disallowed"],[[1565,1565],"disallowed"],[[1566,1566],"valid",[],"NV8"],[[1567,1567],"valid",[],"NV8"],[[1568,1568],"valid"],[[1569,1594],"valid"],[[1595,1599],"valid"],[[1600,1600],"valid",[],"NV8"],[[1601,1618],"valid"],[[1619,1621],"valid"],[[1622,1624],"valid"],[[1625,1630],"valid"],[[1631,1631],"valid"],[[1632,1641],"valid"],[[1642,1645],"valid",[],"NV8"],[[1646,1647],"valid"],[[1648,1652],"valid"],[[1653,1653],"mapped",[1575,1652]],[[1654,1654],"mapped",[1608,1652]],[[1655,1655],"mapped",[1735,1652]],[[1656,1656],"mapped",[1610,1652]],[[1657,1719],"valid"],[[1720,1721],"valid"],[[1722,1726],"valid"],[[1727,1727],"valid"],[[1728,1742],"valid"],[[1743,1743],"valid"],[[1744,1747],"valid"],[[1748,1748],"valid",[],"NV8"],[[1749,1756],"valid"],[[1757,1757],"disallowed"],[[1758,1758],"valid",[],"NV8"],[[1759,1768],"valid"],[[1769,1769],"valid",[],"NV8"],[[1770,1773],"valid"],[[1774,1775],"valid"],[[1776,1785],"valid"],[[1786,1790],"valid"],[[1791,1791],"valid"],[[1792,1805],"valid",[],"NV8"],[[1806,1806],"disallowed"],[[1807,1807],"disallowed"],[[1808,1836],"valid"],[[1837,1839],"valid"],[[1840,1866],"valid"],[[1867,1868],"disallowed"],[[1869,1871],"valid"],[[1872,1901],"valid"],[[1902,1919],"valid"],[[1920,1968],"valid"],[[1969,1969],"valid"],[[1970,1983],"disallowed"],[[1984,2037],"valid"],[[2038,2042],"valid",[],"NV8"],[[2043,2047],"disallowed"],[[2048,2093],"valid"],[[2094,2095],"disallowed"],[[2096,2110],"valid",[],"NV8"],[[2111,2111],"disallowed"],[[2112,2139],"valid"],[[2140,2141],"disallowed"],[[2142,2142],"valid",[],"NV8"],[[2143,2207],"disallowed"],[[2208,2208],"valid"],[[2209,2209],"valid"],[[2210,2220],"valid"],[[2221,2226],"valid"],[[2227,2228],"valid"],[[2229,2274],"disallowed"],[[2275,2275],"valid"],[[2276,2302],"valid"],[[2303,2303],"valid"],[[2304,2304],"valid"],[[2305,2307],"valid"],[[2308,2308],"valid"],[[2309,2361],"valid"],[[2362,2363],"valid"],[[2364,2381],"valid"],[[2382,2382],"valid"],[[2383,2383],"valid"],[[2384,2388],"valid"],[[2389,2389],"valid"],[[2390,2391],"valid"],[[2392,2392],"mapped",[2325,2364]],[[2393,2393],"mapped",[2326,2364]],[[2394,2394],"mapped",[2327,2364]],[[2395,2395],"mapped",[2332,2364]],[[2396,2396],"mapped",[2337,2364]],[[2397,2397],"mapped",[2338,2364]],[[2398,2398],"mapped",[2347,2364]],[[2399,2399],"mapped",[2351,2364]],[[2400,2403],"valid"],[[2404,2405],"valid",[],"NV8"],[[2406,2415],"valid"],[[2416,2416],"valid",[],"NV8"],[[2417,2418],"valid"],[[2419,2423],"valid"],[[2424,2424],"valid"],[[2425,2426],"valid"],[[2427,2428],"valid"],[[2429,2429],"valid"],[[2430,2431],"valid"],[[2432,2432],"valid"],[[2433,2435],"valid"],[[2436,2436],"disallowed"],[[2437,2444],"valid"],[[2445,2446],"disallowed"],[[2447,2448],"valid"],[[2449,2450],"disallowed"],[[2451,2472],"valid"],[[2473,2473],"disallowed"],[[2474,2480],"valid"],[[2481,2481],"disallowed"],[[2482,2482],"valid"],[[2483,2485],"disallowed"],[[2486,2489],"valid"],[[2490,2491],"disallowed"],[[2492,2492],"valid"],[[2493,2493],"valid"],[[2494,2500],"valid"],[[2501,2502],"disallowed"],[[2503,2504],"valid"],[[2505,2506],"disallowed"],[[2507,2509],"valid"],[[2510,2510],"valid"],[[2511,2518],"disallowed"],[[2519,2519],"valid"],[[2520,2523],"disallowed"],[[2524,2524],"mapped",[2465,2492]],[[2525,2525],"mapped",[2466,2492]],[[2526,2526],"disallowed"],[[2527,2527],"mapped",[2479,2492]],[[2528,2531],"valid"],[[2532,2533],"disallowed"],[[2534,2545],"valid"],[[2546,2554],"valid",[],"NV8"],[[2555,2555],"valid",[],"NV8"],[[2556,2560],"disallowed"],[[2561,2561],"valid"],[[2562,2562],"valid"],[[2563,2563],"valid"],[[2564,2564],"disallowed"],[[2565,2570],"valid"],[[2571,2574],"disallowed"],[[2575,2576],"valid"],[[2577,2578],"disallowed"],[[2579,2600],"valid"],[[2601,2601],"disallowed"],[[2602,2608],"valid"],[[2609,2609],"disallowed"],[[2610,2610],"valid"],[[2611,2611],"mapped",[2610,2620]],[[2612,2612],"disallowed"],[[2613,2613],"valid"],[[2614,2614],"mapped",[2616,2620]],[[2615,2615],"disallowed"],[[2616,2617],"valid"],[[2618,2619],"disallowed"],[[2620,2620],"valid"],[[2621,2621],"disallowed"],[[2622,2626],"valid"],[[2627,2630],"disallowed"],[[2631,2632],"valid"],[[2633,2634],"disallowed"],[[2635,2637],"valid"],[[2638,2640],"disallowed"],[[2641,2641],"valid"],[[2642,2648],"disallowed"],[[2649,2649],"mapped",[2582,2620]],[[2650,2650],"mapped",[2583,2620]],[[2651,2651],"mapped",[2588,2620]],[[2652,2652],"valid"],[[2653,2653],"disallowed"],[[2654,2654],"mapped",[2603,2620]],[[2655,2661],"disallowed"],[[2662,2676],"valid"],[[2677,2677],"valid"],[[2678,2688],"disallowed"],[[2689,2691],"valid"],[[2692,2692],"disallowed"],[[2693,2699],"valid"],[[2700,2700],"valid"],[[2701,2701],"valid"],[[2702,2702],"disallowed"],[[2703,2705],"valid"],[[2706,2706],"disallowed"],[[2707,2728],"valid"],[[2729,2729],"disallowed"],[[2730,2736],"valid"],[[2737,2737],"disallowed"],[[2738,2739],"valid"],[[2740,2740],"disallowed"],[[2741,2745],"valid"],[[2746,2747],"disallowed"],[[2748,2757],"valid"],[[2758,2758],"disallowed"],[[2759,2761],"valid"],[[2762,2762],"disallowed"],[[2763,2765],"valid"],[[2766,2767],"disallowed"],[[2768,2768],"valid"],[[2769,2783],"disallowed"],[[2784,2784],"valid"],[[2785,2787],"valid"],[[2788,2789],"disallowed"],[[2790,2799],"valid"],[[2800,2800],"valid",[],"NV8"],[[2801,2801],"valid",[],"NV8"],[[2802,2808],"disallowed"],[[2809,2809],"valid"],[[2810,2816],"disallowed"],[[2817,2819],"valid"],[[2820,2820],"disallowed"],[[2821,2828],"valid"],[[2829,2830],"disallowed"],[[2831,2832],"valid"],[[2833,2834],"disallowed"],[[2835,2856],"valid"],[[2857,2857],"disallowed"],[[2858,2864],"valid"],[[2865,2865],"disallowed"],[[2866,2867],"valid"],[[2868,2868],"disallowed"],[[2869,2869],"valid"],[[2870,2873],"valid"],[[2874,2875],"disallowed"],[[2876,2883],"valid"],[[2884,2884],"valid"],[[2885,2886],"disallowed"],[[2887,2888],"valid"],[[2889,2890],"disallowed"],[[2891,2893],"valid"],[[2894,2901],"disallowed"],[[2902,2903],"valid"],[[2904,2907],"disallowed"],[[2908,2908],"mapped",[2849,2876]],[[2909,2909],"mapped",[2850,2876]],[[2910,2910],"disallowed"],[[2911,2913],"valid"],[[2914,2915],"valid"],[[2916,2917],"disallowed"],[[2918,2927],"valid"],[[2928,2928],"valid",[],"NV8"],[[2929,2929],"valid"],[[2930,2935],"valid",[],"NV8"],[[2936,2945],"disallowed"],[[2946,2947],"valid"],[[2948,2948],"disallowed"],[[2949,2954],"valid"],[[2955,2957],"disallowed"],[[2958,2960],"valid"],[[2961,2961],"disallowed"],[[2962,2965],"valid"],[[2966,2968],"disallowed"],[[2969,2970],"valid"],[[2971,2971],"disallowed"],[[2972,2972],"valid"],[[2973,2973],"disallowed"],[[2974,2975],"valid"],[[2976,2978],"disallowed"],[[2979,2980],"valid"],[[2981,2983],"disallowed"],[[2984,2986],"valid"],[[2987,2989],"disallowed"],[[2990,2997],"valid"],[[2998,2998],"valid"],[[2999,3001],"valid"],[[3002,3005],"disallowed"],[[3006,3010],"valid"],[[3011,3013],"disallowed"],[[3014,3016],"valid"],[[3017,3017],"disallowed"],[[3018,3021],"valid"],[[3022,3023],"disallowed"],[[3024,3024],"valid"],[[3025,3030],"disallowed"],[[3031,3031],"valid"],[[3032,3045],"disallowed"],[[3046,3046],"valid"],[[3047,3055],"valid"],[[3056,3058],"valid",[],"NV8"],[[3059,3066],"valid",[],"NV8"],[[3067,3071],"disallowed"],[[3072,3072],"valid"],[[3073,3075],"valid"],[[3076,3076],"disallowed"],[[3077,3084],"valid"],[[3085,3085],"disallowed"],[[3086,3088],"valid"],[[3089,3089],"disallowed"],[[3090,3112],"valid"],[[3113,3113],"disallowed"],[[3114,3123],"valid"],[[3124,3124],"valid"],[[3125,3129],"valid"],[[3130,3132],"disallowed"],[[3133,3133],"valid"],[[3134,3140],"valid"],[[3141,3141],"disallowed"],[[3142,3144],"valid"],[[3145,3145],"disallowed"],[[3146,3149],"valid"],[[3150,3156],"disallowed"],[[3157,3158],"valid"],[[3159,3159],"disallowed"],[[3160,3161],"valid"],[[3162,3162],"valid"],[[3163,3167],"disallowed"],[[3168,3169],"valid"],[[3170,3171],"valid"],[[3172,3173],"disallowed"],[[3174,3183],"valid"],[[3184,3191],"disallowed"],[[3192,3199],"valid",[],"NV8"],[[3200,3200],"disallowed"],[[3201,3201],"valid"],[[3202,3203],"valid"],[[3204,3204],"disallowed"],[[3205,3212],"valid"],[[3213,3213],"disallowed"],[[3214,3216],"valid"],[[3217,3217],"disallowed"],[[3218,3240],"valid"],[[3241,3241],"disallowed"],[[3242,3251],"valid"],[[3252,3252],"disallowed"],[[3253,3257],"valid"],[[3258,3259],"disallowed"],[[3260,3261],"valid"],[[3262,3268],"valid"],[[3269,3269],"disallowed"],[[3270,3272],"valid"],[[3273,3273],"disallowed"],[[3274,3277],"valid"],[[3278,3284],"disallowed"],[[3285,3286],"valid"],[[3287,3293],"disallowed"],[[3294,3294],"valid"],[[3295,3295],"disallowed"],[[3296,3297],"valid"],[[3298,3299],"valid"],[[3300,3301],"disallowed"],[[3302,3311],"valid"],[[3312,3312],"disallowed"],[[3313,3314],"valid"],[[3315,3328],"disallowed"],[[3329,3329],"valid"],[[3330,3331],"valid"],[[3332,3332],"disallowed"],[[3333,3340],"valid"],[[3341,3341],"disallowed"],[[3342,3344],"valid"],[[3345,3345],"disallowed"],[[3346,3368],"valid"],[[3369,3369],"valid"],[[3370,3385],"valid"],[[3386,3386],"valid"],[[3387,3388],"disallowed"],[[3389,3389],"valid"],[[3390,3395],"valid"],[[3396,3396],"valid"],[[3397,3397],"disallowed"],[[3398,3400],"valid"],[[3401,3401],"disallowed"],[[3402,3405],"valid"],[[3406,3406],"valid"],[[3407,3414],"disallowed"],[[3415,3415],"valid"],[[3416,3422],"disallowed"],[[3423,3423],"valid"],[[3424,3425],"valid"],[[3426,3427],"valid"],[[3428,3429],"disallowed"],[[3430,3439],"valid"],[[3440,3445],"valid",[],"NV8"],[[3446,3448],"disallowed"],[[3449,3449],"valid",[],"NV8"],[[3450,3455],"valid"],[[3456,3457],"disallowed"],[[3458,3459],"valid"],[[3460,3460],"disallowed"],[[3461,3478],"valid"],[[3479,3481],"disallowed"],[[3482,3505],"valid"],[[3506,3506],"disallowed"],[[3507,3515],"valid"],[[3516,3516],"disallowed"],[[3517,3517],"valid"],[[3518,3519],"disallowed"],[[3520,3526],"valid"],[[3527,3529],"disallowed"],[[3530,3530],"valid"],[[3531,3534],"disallowed"],[[3535,3540],"valid"],[[3541,3541],"disallowed"],[[3542,3542],"valid"],[[3543,3543],"disallowed"],[[3544,3551],"valid"],[[3552,3557],"disallowed"],[[3558,3567],"valid"],[[3568,3569],"disallowed"],[[3570,3571],"valid"],[[3572,3572],"valid",[],"NV8"],[[3573,3584],"disallowed"],[[3585,3634],"valid"],[[3635,3635],"mapped",[3661,3634]],[[3636,3642],"valid"],[[3643,3646],"disallowed"],[[3647,3647],"valid",[],"NV8"],[[3648,3662],"valid"],[[3663,3663],"valid",[],"NV8"],[[3664,3673],"valid"],[[3674,3675],"valid",[],"NV8"],[[3676,3712],"disallowed"],[[3713,3714],"valid"],[[3715,3715],"disallowed"],[[3716,3716],"valid"],[[3717,3718],"disallowed"],[[3719,3720],"valid"],[[3721,3721],"disallowed"],[[3722,3722],"valid"],[[3723,3724],"disallowed"],[[3725,3725],"valid"],[[3726,3731],"disallowed"],[[3732,3735],"valid"],[[3736,3736],"disallowed"],[[3737,3743],"valid"],[[3744,3744],"disallowed"],[[3745,3747],"valid"],[[3748,3748],"disallowed"],[[3749,3749],"valid"],[[3750,3750],"disallowed"],[[3751,3751],"valid"],[[3752,3753],"disallowed"],[[3754,3755],"valid"],[[3756,3756],"disallowed"],[[3757,3762],"valid"],[[3763,3763],"mapped",[3789,3762]],[[3764,3769],"valid"],[[3770,3770],"disallowed"],[[3771,3773],"valid"],[[3774,3775],"disallowed"],[[3776,3780],"valid"],[[3781,3781],"disallowed"],[[3782,3782],"valid"],[[3783,3783],"disallowed"],[[3784,3789],"valid"],[[3790,3791],"disallowed"],[[3792,3801],"valid"],[[3802,3803],"disallowed"],[[3804,3804],"mapped",[3755,3737]],[[3805,3805],"mapped",[3755,3745]],[[3806,3807],"valid"],[[3808,3839],"disallowed"],[[3840,3840],"valid"],[[3841,3850],"valid",[],"NV8"],[[3851,3851],"valid"],[[3852,3852],"mapped",[3851]],[[3853,3863],"valid",[],"NV8"],[[3864,3865],"valid"],[[3866,3871],"valid",[],"NV8"],[[3872,3881],"valid"],[[3882,3892],"valid",[],"NV8"],[[3893,3893],"valid"],[[3894,3894],"valid",[],"NV8"],[[3895,3895],"valid"],[[3896,3896],"valid",[],"NV8"],[[3897,3897],"valid"],[[3898,3901],"valid",[],"NV8"],[[3902,3906],"valid"],[[3907,3907],"mapped",[3906,4023]],[[3908,3911],"valid"],[[3912,3912],"disallowed"],[[3913,3916],"valid"],[[3917,3917],"mapped",[3916,4023]],[[3918,3921],"valid"],[[3922,3922],"mapped",[3921,4023]],[[3923,3926],"valid"],[[3927,3927],"mapped",[3926,4023]],[[3928,3931],"valid"],[[3932,3932],"mapped",[3931,4023]],[[3933,3944],"valid"],[[3945,3945],"mapped",[3904,4021]],[[3946,3946],"valid"],[[3947,3948],"valid"],[[3949,3952],"disallowed"],[[3953,3954],"valid"],[[3955,3955],"mapped",[3953,3954]],[[3956,3956],"valid"],[[3957,3957],"mapped",[3953,3956]],[[3958,3958],"mapped",[4018,3968]],[[3959,3959],"mapped",[4018,3953,3968]],[[3960,3960],"mapped",[4019,3968]],[[3961,3961],"mapped",[4019,3953,3968]],[[3962,3968],"valid"],[[3969,3969],"mapped",[3953,3968]],[[3970,3972],"valid"],[[3973,3973],"valid",[],"NV8"],[[3974,3979],"valid"],[[3980,3983],"valid"],[[3984,3986],"valid"],[[3987,3987],"mapped",[3986,4023]],[[3988,3989],"valid"],[[3990,3990],"valid"],[[3991,3991],"valid"],[[3992,3992],"disallowed"],[[3993,3996],"valid"],[[3997,3997],"mapped",[3996,4023]],[[3998,4001],"valid"],[[4002,4002],"mapped",[4001,4023]],[[4003,4006],"valid"],[[4007,4007],"mapped",[4006,4023]],[[4008,4011],"valid"],[[4012,4012],"mapped",[4011,4023]],[[4013,4013],"valid"],[[4014,4016],"valid"],[[4017,4023],"valid"],[[4024,4024],"valid"],[[4025,4025],"mapped",[3984,4021]],[[4026,4028],"valid"],[[4029,4029],"disallowed"],[[4030,4037],"valid",[],"NV8"],[[4038,4038],"valid"],[[4039,4044],"valid",[],"NV8"],[[4045,4045],"disallowed"],[[4046,4046],"valid",[],"NV8"],[[4047,4047],"valid",[],"NV8"],[[4048,4049],"valid",[],"NV8"],[[4050,4052],"valid",[],"NV8"],[[4053,4056],"valid",[],"NV8"],[[4057,4058],"valid",[],"NV8"],[[4059,4095],"disallowed"],[[4096,4129],"valid"],[[4130,4130],"valid"],[[4131,4135],"valid"],[[4136,4136],"valid"],[[4137,4138],"valid"],[[4139,4139],"valid"],[[4140,4146],"valid"],[[4147,4149],"valid"],[[4150,4153],"valid"],[[4154,4159],"valid"],[[4160,4169],"valid"],[[4170,4175],"valid",[],"NV8"],[[4176,4185],"valid"],[[4186,4249],"valid"],[[4250,4253],"valid"],[[4254,4255],"valid",[],"NV8"],[[4256,4293],"disallowed"],[[4294,4294],"disallowed"],[[4295,4295],"mapped",[11559]],[[4296,4300],"disallowed"],[[4301,4301],"mapped",[11565]],[[4302,4303],"disallowed"],[[4304,4342],"valid"],[[4343,4344],"valid"],[[4345,4346],"valid"],[[4347,4347],"valid",[],"NV8"],[[4348,4348],"mapped",[4316]],[[4349,4351],"valid"],[[4352,4441],"valid",[],"NV8"],[[4442,4446],"valid",[],"NV8"],[[4447,4448],"disallowed"],[[4449,4514],"valid",[],"NV8"],[[4515,4519],"valid",[],"NV8"],[[4520,4601],"valid",[],"NV8"],[[4602,4607],"valid",[],"NV8"],[[4608,4614],"valid"],[[4615,4615],"valid"],[[4616,4678],"valid"],[[4679,4679],"valid"],[[4680,4680],"valid"],[[4681,4681],"disallowed"],[[4682,4685],"valid"],[[4686,4687],"disallowed"],[[4688,4694],"valid"],[[4695,4695],"disallowed"],[[4696,4696],"valid"],[[4697,4697],"disallowed"],[[4698,4701],"valid"],[[4702,4703],"disallowed"],[[4704,4742],"valid"],[[4743,4743],"valid"],[[4744,4744],"valid"],[[4745,4745],"disallowed"],[[4746,4749],"valid"],[[4750,4751],"disallowed"],[[4752,4782],"valid"],[[4783,4783],"valid"],[[4784,4784],"valid"],[[4785,4785],"disallowed"],[[4786,4789],"valid"],[[4790,4791],"disallowed"],[[4792,4798],"valid"],[[4799,4799],"disallowed"],[[4800,4800],"valid"],[[4801,4801],"disallowed"],[[4802,4805],"valid"],[[4806,4807],"disallowed"],[[4808,4814],"valid"],[[4815,4815],"valid"],[[4816,4822],"valid"],[[4823,4823],"disallowed"],[[4824,4846],"valid"],[[4847,4847],"valid"],[[4848,4878],"valid"],[[4879,4879],"valid"],[[4880,4880],"valid"],[[4881,4881],"disallowed"],[[4882,4885],"valid"],[[4886,4887],"disallowed"],[[4888,4894],"valid"],[[4895,4895],"valid"],[[4896,4934],"valid"],[[4935,4935],"valid"],[[4936,4954],"valid"],[[4955,4956],"disallowed"],[[4957,4958],"valid"],[[4959,4959],"valid"],[[4960,4960],"valid",[],"NV8"],[[4961,4988],"valid",[],"NV8"],[[4989,4991],"disallowed"],[[4992,5007],"valid"],[[5008,5017],"valid",[],"NV8"],[[5018,5023],"disallowed"],[[5024,5108],"valid"],[[5109,5109],"valid"],[[5110,5111],"disallowed"],[[5112,5112],"mapped",[5104]],[[5113,5113],"mapped",[5105]],[[5114,5114],"mapped",[5106]],[[5115,5115],"mapped",[5107]],[[5116,5116],"mapped",[5108]],[[5117,5117],"mapped",[5109]],[[5118,5119],"disallowed"],[[5120,5120],"valid",[],"NV8"],[[5121,5740],"valid"],[[5741,5742],"valid",[],"NV8"],[[5743,5750],"valid"],[[5751,5759],"valid"],[[5760,5760],"disallowed"],[[5761,5786],"valid"],[[5787,5788],"valid",[],"NV8"],[[5789,5791],"disallowed"],[[5792,5866],"valid"],[[5867,5872],"valid",[],"NV8"],[[5873,5880],"valid"],[[5881,5887],"disallowed"],[[5888,5900],"valid"],[[5901,5901],"disallowed"],[[5902,5908],"valid"],[[5909,5919],"disallowed"],[[5920,5940],"valid"],[[5941,5942],"valid",[],"NV8"],[[5943,5951],"disallowed"],[[5952,5971],"valid"],[[5972,5983],"disallowed"],[[5984,5996],"valid"],[[5997,5997],"disallowed"],[[5998,6000],"valid"],[[6001,6001],"disallowed"],[[6002,6003],"valid"],[[6004,6015],"disallowed"],[[6016,6067],"valid"],[[6068,6069],"disallowed"],[[6070,6099],"valid"],[[6100,6102],"valid",[],"NV8"],[[6103,6103],"valid"],[[6104,6107],"valid",[],"NV8"],[[6108,6108],"valid"],[[6109,6109],"valid"],[[6110,6111],"disallowed"],[[6112,6121],"valid"],[[6122,6127],"disallowed"],[[6128,6137],"valid",[],"NV8"],[[6138,6143],"disallowed"],[[6144,6149],"valid",[],"NV8"],[[6150,6150],"disallowed"],[[6151,6154],"valid",[],"NV8"],[[6155,6157],"ignored"],[[6158,6158],"disallowed"],[[6159,6159],"disallowed"],[[6160,6169],"valid"],[[6170,6175],"disallowed"],[[6176,6263],"valid"],[[6264,6271],"disallowed"],[[6272,6313],"valid"],[[6314,6314],"valid"],[[6315,6319],"disallowed"],[[6320,6389],"valid"],[[6390,6399],"disallowed"],[[6400,6428],"valid"],[[6429,6430],"valid"],[[6431,6431],"disallowed"],[[6432,6443],"valid"],[[6444,6447],"disallowed"],[[6448,6459],"valid"],[[6460,6463],"disallowed"],[[6464,6464],"valid",[],"NV8"],[[6465,6467],"disallowed"],[[6468,6469],"valid",[],"NV8"],[[6470,6509],"valid"],[[6510,6511],"disallowed"],[[6512,6516],"valid"],[[6517,6527],"disallowed"],[[6528,6569],"valid"],[[6570,6571],"valid"],[[6572,6575],"disallowed"],[[6576,6601],"valid"],[[6602,6607],"disallowed"],[[6608,6617],"valid"],[[6618,6618],"valid",[],"XV8"],[[6619,6621],"disallowed"],[[6622,6623],"valid",[],"NV8"],[[6624,6655],"valid",[],"NV8"],[[6656,6683],"valid"],[[6684,6685],"disallowed"],[[6686,6687],"valid",[],"NV8"],[[6688,6750],"valid"],[[6751,6751],"disallowed"],[[6752,6780],"valid"],[[6781,6782],"disallowed"],[[6783,6793],"valid"],[[6794,6799],"disallowed"],[[6800,6809],"valid"],[[6810,6815],"disallowed"],[[6816,6822],"valid",[],"NV8"],[[6823,6823],"valid"],[[6824,6829],"valid",[],"NV8"],[[6830,6831],"disallowed"],[[6832,6845],"valid"],[[6846,6846],"valid",[],"NV8"],[[6847,6911],"disallowed"],[[6912,6987],"valid"],[[6988,6991],"disallowed"],[[6992,7001],"valid"],[[7002,7018],"valid",[],"NV8"],[[7019,7027],"valid"],[[7028,7036],"valid",[],"NV8"],[[7037,7039],"disallowed"],[[7040,7082],"valid"],[[7083,7085],"valid"],[[7086,7097],"valid"],[[7098,7103],"valid"],[[7104,7155],"valid"],[[7156,7163],"disallowed"],[[7164,7167],"valid",[],"NV8"],[[7168,7223],"valid"],[[7224,7226],"disallowed"],[[7227,7231],"valid",[],"NV8"],[[7232,7241],"valid"],[[7242,7244],"disallowed"],[[7245,7293],"valid"],[[7294,7295],"valid",[],"NV8"],[[7296,7359],"disallowed"],[[7360,7367],"valid",[],"NV8"],[[7368,7375],"disallowed"],[[7376,7378],"valid"],[[7379,7379],"valid",[],"NV8"],[[7380,7410],"valid"],[[7411,7414],"valid"],[[7415,7415],"disallowed"],[[7416,7417],"valid"],[[7418,7423],"disallowed"],[[7424,7467],"valid"],[[7468,7468],"mapped",[97]],[[7469,7469],"mapped",[230]],[[7470,7470],"mapped",[98]],[[7471,7471],"valid"],[[7472,7472],"mapped",[100]],[[7473,7473],"mapped",[101]],[[7474,7474],"mapped",[477]],[[7475,7475],"mapped",[103]],[[7476,7476],"mapped",[104]],[[7477,7477],"mapped",[105]],[[7478,7478],"mapped",[106]],[[7479,7479],"mapped",[107]],[[7480,7480],"mapped",[108]],[[7481,7481],"mapped",[109]],[[7482,7482],"mapped",[110]],[[7483,7483],"valid"],[[7484,7484],"mapped",[111]],[[7485,7485],"mapped",[547]],[[7486,7486],"mapped",[112]],[[7487,7487],"mapped",[114]],[[7488,7488],"mapped",[116]],[[7489,7489],"mapped",[117]],[[7490,7490],"mapped",[119]],[[7491,7491],"mapped",[97]],[[7492,7492],"mapped",[592]],[[7493,7493],"mapped",[593]],[[7494,7494],"mapped",[7426]],[[7495,7495],"mapped",[98]],[[7496,7496],"mapped",[100]],[[7497,7497],"mapped",[101]],[[7498,7498],"mapped",[601]],[[7499,7499],"mapped",[603]],[[7500,7500],"mapped",[604]],[[7501,7501],"mapped",[103]],[[7502,7502],"valid"],[[7503,7503],"mapped",[107]],[[7504,7504],"mapped",[109]],[[7505,7505],"mapped",[331]],[[7506,7506],"mapped",[111]],[[7507,7507],"mapped",[596]],[[7508,7508],"mapped",[7446]],[[7509,7509],"mapped",[7447]],[[7510,7510],"mapped",[112]],[[7511,7511],"mapped",[116]],[[7512,7512],"mapped",[117]],[[7513,7513],"mapped",[7453]],[[7514,7514],"mapped",[623]],[[7515,7515],"mapped",[118]],[[7516,7516],"mapped",[7461]],[[7517,7517],"mapped",[946]],[[7518,7518],"mapped",[947]],[[7519,7519],"mapped",[948]],[[7520,7520],"mapped",[966]],[[7521,7521],"mapped",[967]],[[7522,7522],"mapped",[105]],[[7523,7523],"mapped",[114]],[[7524,7524],"mapped",[117]],[[7525,7525],"mapped",[118]],[[7526,7526],"mapped",[946]],[[7527,7527],"mapped",[947]],[[7528,7528],"mapped",[961]],[[7529,7529],"mapped",[966]],[[7530,7530],"mapped",[967]],[[7531,7531],"valid"],[[7532,7543],"valid"],[[7544,7544],"mapped",[1085]],[[7545,7578],"valid"],[[7579,7579],"mapped",[594]],[[7580,7580],"mapped",[99]],[[7581,7581],"mapped",[597]],[[7582,7582],"mapped",[240]],[[7583,7583],"mapped",[604]],[[7584,7584],"mapped",[102]],[[7585,7585],"mapped",[607]],[[7586,7586],"mapped",[609]],[[7587,7587],"mapped",[613]],[[7588,7588],"mapped",[616]],[[7589,7589],"mapped",[617]],[[7590,7590],"mapped",[618]],[[7591,7591],"mapped",[7547]],[[7592,7592],"mapped",[669]],[[7593,7593],"mapped",[621]],[[7594,7594],"mapped",[7557]],[[7595,7595],"mapped",[671]],[[7596,7596],"mapped",[625]],[[7597,7597],"mapped",[624]],[[7598,7598],"mapped",[626]],[[7599,7599],"mapped",[627]],[[7600,7600],"mapped",[628]],[[7601,7601],"mapped",[629]],[[7602,7602],"mapped",[632]],[[7603,7603],"mapped",[642]],[[7604,7604],"mapped",[643]],[[7605,7605],"mapped",[427]],[[7606,7606],"mapped",[649]],[[7607,7607],"mapped",[650]],[[7608,7608],"mapped",[7452]],[[7609,7609],"mapped",[651]],[[7610,7610],"mapped",[652]],[[7611,7611],"mapped",[122]],[[7612,7612],"mapped",[656]],[[7613,7613],"mapped",[657]],[[7614,7614],"mapped",[658]],[[7615,7615],"mapped",[952]],[[7616,7619],"valid"],[[7620,7626],"valid"],[[7627,7654],"valid"],[[7655,7669],"valid"],[[7670,7675],"disallowed"],[[7676,7676],"valid"],[[7677,7677],"valid"],[[7678,7679],"valid"],[[7680,7680],"mapped",[7681]],[[7681,7681],"valid"],[[7682,7682],"mapped",[7683]],[[7683,7683],"valid"],[[7684,7684],"mapped",[7685]],[[7685,7685],"valid"],[[7686,7686],"mapped",[7687]],[[7687,7687],"valid"],[[7688,7688],"mapped",[7689]],[[7689,7689],"valid"],[[7690,7690],"mapped",[7691]],[[7691,7691],"valid"],[[7692,7692],"mapped",[7693]],[[7693,7693],"valid"],[[7694,7694],"mapped",[7695]],[[7695,7695],"valid"],[[7696,7696],"mapped",[7697]],[[7697,7697],"valid"],[[7698,7698],"mapped",[7699]],[[7699,7699],"valid"],[[7700,7700],"mapped",[7701]],[[7701,7701],"valid"],[[7702,7702],"mapped",[7703]],[[7703,7703],"valid"],[[7704,7704],"mapped",[7705]],[[7705,7705],"valid"],[[7706,7706],"mapped",[7707]],[[7707,7707],"valid"],[[7708,7708],"mapped",[7709]],[[7709,7709],"valid"],[[7710,7710],"mapped",[7711]],[[7711,7711],"valid"],[[7712,7712],"mapped",[7713]],[[7713,7713],"valid"],[[7714,7714],"mapped",[7715]],[[7715,7715],"valid"],[[7716,7716],"mapped",[7717]],[[7717,7717],"valid"],[[7718,7718],"mapped",[7719]],[[7719,7719],"valid"],[[7720,7720],"mapped",[7721]],[[7721,7721],"valid"],[[7722,7722],"mapped",[7723]],[[7723,7723],"valid"],[[7724,7724],"mapped",[7725]],[[7725,7725],"valid"],[[7726,7726],"mapped",[7727]],[[7727,7727],"valid"],[[7728,7728],"mapped",[7729]],[[7729,7729],"valid"],[[7730,7730],"mapped",[7731]],[[7731,7731],"valid"],[[7732,7732],"mapped",[7733]],[[7733,7733],"valid"],[[7734,7734],"mapped",[7735]],[[7735,7735],"valid"],[[7736,7736],"mapped",[7737]],[[7737,7737],"valid"],[[7738,7738],"mapped",[7739]],[[7739,7739],"valid"],[[7740,7740],"mapped",[7741]],[[7741,7741],"valid"],[[7742,7742],"mapped",[7743]],[[7743,7743],"valid"],[[7744,7744],"mapped",[7745]],[[7745,7745],"valid"],[[7746,7746],"mapped",[7747]],[[7747,7747],"valid"],[[7748,7748],"mapped",[7749]],[[7749,7749],"valid"],[[7750,7750],"mapped",[7751]],[[7751,7751],"valid"],[[7752,7752],"mapped",[7753]],[[7753,7753],"valid"],[[7754,7754],"mapped",[7755]],[[7755,7755],"valid"],[[7756,7756],"mapped",[7757]],[[7757,7757],"valid"],[[7758,7758],"mapped",[7759]],[[7759,7759],"valid"],[[7760,7760],"mapped",[7761]],[[7761,7761],"valid"],[[7762,7762],"mapped",[7763]],[[7763,7763],"valid"],[[7764,7764],"mapped",[7765]],[[7765,7765],"valid"],[[7766,7766],"mapped",[7767]],[[7767,7767],"valid"],[[7768,7768],"mapped",[7769]],[[7769,7769],"valid"],[[7770,7770],"mapped",[7771]],[[7771,7771],"valid"],[[7772,7772],"mapped",[7773]],[[7773,7773],"valid"],[[7774,7774],"mapped",[7775]],[[7775,7775],"valid"],[[7776,7776],"mapped",[7777]],[[7777,7777],"valid"],[[7778,7778],"mapped",[7779]],[[7779,7779],"valid"],[[7780,7780],"mapped",[7781]],[[7781,7781],"valid"],[[7782,7782],"mapped",[7783]],[[7783,7783],"valid"],[[7784,7784],"mapped",[7785]],[[7785,7785],"valid"],[[7786,7786],"mapped",[7787]],[[7787,7787],"valid"],[[7788,7788],"mapped",[7789]],[[7789,7789],"valid"],[[7790,7790],"mapped",[7791]],[[7791,7791],"valid"],[[7792,7792],"mapped",[7793]],[[7793,7793],"valid"],[[7794,7794],"mapped",[7795]],[[7795,7795],"valid"],[[7796,7796],"mapped",[7797]],[[7797,7797],"valid"],[[7798,7798],"mapped",[7799]],[[7799,7799],"valid"],[[7800,7800],"mapped",[7801]],[[7801,7801],"valid"],[[7802,7802],"mapped",[7803]],[[7803,7803],"valid"],[[7804,7804],"mapped",[7805]],[[7805,7805],"valid"],[[7806,7806],"mapped",[7807]],[[7807,7807],"valid"],[[7808,7808],"mapped",[7809]],[[7809,7809],"valid"],[[7810,7810],"mapped",[7811]],[[7811,7811],"valid"],[[7812,7812],"mapped",[7813]],[[7813,7813],"valid"],[[7814,7814],"mapped",[7815]],[[7815,7815],"valid"],[[7816,7816],"mapped",[7817]],[[7817,7817],"valid"],[[7818,7818],"mapped",[7819]],[[7819,7819],"valid"],[[7820,7820],"mapped",[7821]],[[7821,7821],"valid"],[[7822,7822],"mapped",[7823]],[[7823,7823],"valid"],[[7824,7824],"mapped",[7825]],[[7825,7825],"valid"],[[7826,7826],"mapped",[7827]],[[7827,7827],"valid"],[[7828,7828],"mapped",[7829]],[[7829,7833],"valid"],[[7834,7834],"mapped",[97,702]],[[7835,7835],"mapped",[7777]],[[7836,7837],"valid"],[[7838,7838],"mapped",[115,115]],[[7839,7839],"valid"],[[7840,7840],"mapped",[7841]],[[7841,7841],"valid"],[[7842,7842],"mapped",[7843]],[[7843,7843],"valid"],[[7844,7844],"mapped",[7845]],[[7845,7845],"valid"],[[7846,7846],"mapped",[7847]],[[7847,7847],"valid"],[[7848,7848],"mapped",[7849]],[[7849,7849],"valid"],[[7850,7850],"mapped",[7851]],[[7851,7851],"valid"],[[7852,7852],"mapped",[7853]],[[7853,7853],"valid"],[[7854,7854],"mapped",[7855]],[[7855,7855],"valid"],[[7856,7856],"mapped",[7857]],[[7857,7857],"valid"],[[7858,7858],"mapped",[7859]],[[7859,7859],"valid"],[[7860,7860],"mapped",[7861]],[[7861,7861],"valid"],[[7862,7862],"mapped",[7863]],[[7863,7863],"valid"],[[7864,7864],"mapped",[7865]],[[7865,7865],"valid"],[[7866,7866],"mapped",[7867]],[[7867,7867],"valid"],[[7868,7868],"mapped",[7869]],[[7869,7869],"valid"],[[7870,7870],"mapped",[7871]],[[7871,7871],"valid"],[[7872,7872],"mapped",[7873]],[[7873,7873],"valid"],[[7874,7874],"mapped",[7875]],[[7875,7875],"valid"],[[7876,7876],"mapped",[7877]],[[7877,7877],"valid"],[[7878,7878],"mapped",[7879]],[[7879,7879],"valid"],[[7880,7880],"mapped",[7881]],[[7881,7881],"valid"],[[7882,7882],"mapped",[7883]],[[7883,7883],"valid"],[[7884,7884],"mapped",[7885]],[[7885,7885],"valid"],[[7886,7886],"mapped",[7887]],[[7887,7887],"valid"],[[7888,7888],"mapped",[7889]],[[7889,7889],"valid"],[[7890,7890],"mapped",[7891]],[[7891,7891],"valid"],[[7892,7892],"mapped",[7893]],[[7893,7893],"valid"],[[7894,7894],"mapped",[7895]],[[7895,7895],"valid"],[[7896,7896],"mapped",[7897]],[[7897,7897],"valid"],[[7898,7898],"mapped",[7899]],[[7899,7899],"valid"],[[7900,7900],"mapped",[7901]],[[7901,7901],"valid"],[[7902,7902],"mapped",[7903]],[[7903,7903],"valid"],[[7904,7904],"mapped",[7905]],[[7905,7905],"valid"],[[7906,7906],"mapped",[7907]],[[7907,7907],"valid"],[[7908,7908],"mapped",[7909]],[[7909,7909],"valid"],[[7910,7910],"mapped",[7911]],[[7911,7911],"valid"],[[7912,7912],"mapped",[7913]],[[7913,7913],"valid"],[[7914,7914],"mapped",[7915]],[[7915,7915],"valid"],[[7916,7916],"mapped",[7917]],[[7917,7917],"valid"],[[7918,7918],"mapped",[7919]],[[7919,7919],"valid"],[[7920,7920],"mapped",[7921]],[[7921,7921],"valid"],[[7922,7922],"mapped",[7923]],[[7923,7923],"valid"],[[7924,7924],"mapped",[7925]],[[7925,7925],"valid"],[[7926,7926],"mapped",[7927]],[[7927,7927],"valid"],[[7928,7928],"mapped",[7929]],[[7929,7929],"valid"],[[7930,7930],"mapped",[7931]],[[7931,7931],"valid"],[[7932,7932],"mapped",[7933]],[[7933,7933],"valid"],[[7934,7934],"mapped",[7935]],[[7935,7935],"valid"],[[7936,7943],"valid"],[[7944,7944],"mapped",[7936]],[[7945,7945],"mapped",[7937]],[[7946,7946],"mapped",[7938]],[[7947,7947],"mapped",[7939]],[[7948,7948],"mapped",[7940]],[[7949,7949],"mapped",[7941]],[[7950,7950],"mapped",[7942]],[[7951,7951],"mapped",[7943]],[[7952,7957],"valid"],[[7958,7959],"disallowed"],[[7960,7960],"mapped",[7952]],[[7961,7961],"mapped",[7953]],[[7962,7962],"mapped",[7954]],[[7963,7963],"mapped",[7955]],[[7964,7964],"mapped",[7956]],[[7965,7965],"mapped",[7957]],[[7966,7967],"disallowed"],[[7968,7975],"valid"],[[7976,7976],"mapped",[7968]],[[7977,7977],"mapped",[7969]],[[7978,7978],"mapped",[7970]],[[7979,7979],"mapped",[7971]],[[7980,7980],"mapped",[7972]],[[7981,7981],"mapped",[7973]],[[7982,7982],"mapped",[7974]],[[7983,7983],"mapped",[7975]],[[7984,7991],"valid"],[[7992,7992],"mapped",[7984]],[[7993,7993],"mapped",[7985]],[[7994,7994],"mapped",[7986]],[[7995,7995],"mapped",[7987]],[[7996,7996],"mapped",[7988]],[[7997,7997],"mapped",[7989]],[[7998,7998],"mapped",[7990]],[[7999,7999],"mapped",[7991]],[[8000,8005],"valid"],[[8006,8007],"disallowed"],[[8008,8008],"mapped",[8000]],[[8009,8009],"mapped",[8001]],[[8010,8010],"mapped",[8002]],[[8011,8011],"mapped",[8003]],[[8012,8012],"mapped",[8004]],[[8013,8013],"mapped",[8005]],[[8014,8015],"disallowed"],[[8016,8023],"valid"],[[8024,8024],"disallowed"],[[8025,8025],"mapped",[8017]],[[8026,8026],"disallowed"],[[8027,8027],"mapped",[8019]],[[8028,8028],"disallowed"],[[8029,8029],"mapped",[8021]],[[8030,8030],"disallowed"],[[8031,8031],"mapped",[8023]],[[8032,8039],"valid"],[[8040,8040],"mapped",[8032]],[[8041,8041],"mapped",[8033]],[[8042,8042],"mapped",[8034]],[[8043,8043],"mapped",[8035]],[[8044,8044],"mapped",[8036]],[[8045,8045],"mapped",[8037]],[[8046,8046],"mapped",[8038]],[[8047,8047],"mapped",[8039]],[[8048,8048],"valid"],[[8049,8049],"mapped",[940]],[[8050,8050],"valid"],[[8051,8051],"mapped",[941]],[[8052,8052],"valid"],[[8053,8053],"mapped",[942]],[[8054,8054],"valid"],[[8055,8055],"mapped",[943]],[[8056,8056],"valid"],[[8057,8057],"mapped",[972]],[[8058,8058],"valid"],[[8059,8059],"mapped",[973]],[[8060,8060],"valid"],[[8061,8061],"mapped",[974]],[[8062,8063],"disallowed"],[[8064,8064],"mapped",[7936,953]],[[8065,8065],"mapped",[7937,953]],[[8066,8066],"mapped",[7938,953]],[[8067,8067],"mapped",[7939,953]],[[8068,8068],"mapped",[7940,953]],[[8069,8069],"mapped",[7941,953]],[[8070,8070],"mapped",[7942,953]],[[8071,8071],"mapped",[7943,953]],[[8072,8072],"mapped",[7936,953]],[[8073,8073],"mapped",[7937,953]],[[8074,8074],"mapped",[7938,953]],[[8075,8075],"mapped",[7939,953]],[[8076,8076],"mapped",[7940,953]],[[8077,8077],"mapped",[7941,953]],[[8078,8078],"mapped",[7942,953]],[[8079,8079],"mapped",[7943,953]],[[8080,8080],"mapped",[7968,953]],[[8081,8081],"mapped",[7969,953]],[[8082,8082],"mapped",[7970,953]],[[8083,8083],"mapped",[7971,953]],[[8084,8084],"mapped",[7972,953]],[[8085,8085],"mapped",[7973,953]],[[8086,8086],"mapped",[7974,953]],[[8087,8087],"mapped",[7975,953]],[[8088,8088],"mapped",[7968,953]],[[8089,8089],"mapped",[7969,953]],[[8090,8090],"mapped",[7970,953]],[[8091,8091],"mapped",[7971,953]],[[8092,8092],"mapped",[7972,953]],[[8093,8093],"mapped",[7973,953]],[[8094,8094],"mapped",[7974,953]],[[8095,8095],"mapped",[7975,953]],[[8096,8096],"mapped",[8032,953]],[[8097,8097],"mapped",[8033,953]],[[8098,8098],"mapped",[8034,953]],[[8099,8099],"mapped",[8035,953]],[[8100,8100],"mapped",[8036,953]],[[8101,8101],"mapped",[8037,953]],[[8102,8102],"mapped",[8038,953]],[[8103,8103],"mapped",[8039,953]],[[8104,8104],"mapped",[8032,953]],[[8105,8105],"mapped",[8033,953]],[[8106,8106],"mapped",[8034,953]],[[8107,8107],"mapped",[8035,953]],[[8108,8108],"mapped",[8036,953]],[[8109,8109],"mapped",[8037,953]],[[8110,8110],"mapped",[8038,953]],[[8111,8111],"mapped",[8039,953]],[[8112,8113],"valid"],[[8114,8114],"mapped",[8048,953]],[[8115,8115],"mapped",[945,953]],[[8116,8116],"mapped",[940,953]],[[8117,8117],"disallowed"],[[8118,8118],"valid"],[[8119,8119],"mapped",[8118,953]],[[8120,8120],"mapped",[8112]],[[8121,8121],"mapped",[8113]],[[8122,8122],"mapped",[8048]],[[8123,8123],"mapped",[940]],[[8124,8124],"mapped",[945,953]],[[8125,8125],"disallowed_STD3_mapped",[32,787]],[[8126,8126],"mapped",[953]],[[8127,8127],"disallowed_STD3_mapped",[32,787]],[[8128,8128],"disallowed_STD3_mapped",[32,834]],[[8129,8129],"disallowed_STD3_mapped",[32,776,834]],[[8130,8130],"mapped",[8052,953]],[[8131,8131],"mapped",[951,953]],[[8132,8132],"mapped",[942,953]],[[8133,8133],"disallowed"],[[8134,8134],"valid"],[[8135,8135],"mapped",[8134,953]],[[8136,8136],"mapped",[8050]],[[8137,8137],"mapped",[941]],[[8138,8138],"mapped",[8052]],[[8139,8139],"mapped",[942]],[[8140,8140],"mapped",[951,953]],[[8141,8141],"disallowed_STD3_mapped",[32,787,768]],[[8142,8142],"disallowed_STD3_mapped",[32,787,769]],[[8143,8143],"disallowed_STD3_mapped",[32,787,834]],[[8144,8146],"valid"],[[8147,8147],"mapped",[912]],[[8148,8149],"disallowed"],[[8150,8151],"valid"],[[8152,8152],"mapped",[8144]],[[8153,8153],"mapped",[8145]],[[8154,8154],"mapped",[8054]],[[8155,8155],"mapped",[943]],[[8156,8156],"disallowed"],[[8157,8157],"disallowed_STD3_mapped",[32,788,768]],[[8158,8158],"disallowed_STD3_mapped",[32,788,769]],[[8159,8159],"disallowed_STD3_mapped",[32,788,834]],[[8160,8162],"valid"],[[8163,8163],"mapped",[944]],[[8164,8167],"valid"],[[8168,8168],"mapped",[8160]],[[8169,8169],"mapped",[8161]],[[8170,8170],"mapped",[8058]],[[8171,8171],"mapped",[973]],[[8172,8172],"mapped",[8165]],[[8173,8173],"disallowed_STD3_mapped",[32,776,768]],[[8174,8174],"disallowed_STD3_mapped",[32,776,769]],[[8175,8175],"disallowed_STD3_mapped",[96]],[[8176,8177],"disallowed"],[[8178,8178],"mapped",[8060,953]],[[8179,8179],"mapped",[969,953]],[[8180,8180],"mapped",[974,953]],[[8181,8181],"disallowed"],[[8182,8182],"valid"],[[8183,8183],"mapped",[8182,953]],[[8184,8184],"mapped",[8056]],[[8185,8185],"mapped",[972]],[[8186,8186],"mapped",[8060]],[[8187,8187],"mapped",[974]],[[8188,8188],"mapped",[969,953]],[[8189,8189],"disallowed_STD3_mapped",[32,769]],[[8190,8190],"disallowed_STD3_mapped",[32,788]],[[8191,8191],"disallowed"],[[8192,8202],"disallowed_STD3_mapped",[32]],[[8203,8203],"ignored"],[[8204,8205],"deviation",[]],[[8206,8207],"disallowed"],[[8208,8208],"valid",[],"NV8"],[[8209,8209],"mapped",[8208]],[[8210,8214],"valid",[],"NV8"],[[8215,8215],"disallowed_STD3_mapped",[32,819]],[[8216,8227],"valid",[],"NV8"],[[8228,8230],"disallowed"],[[8231,8231],"valid",[],"NV8"],[[8232,8238],"disallowed"],[[8239,8239],"disallowed_STD3_mapped",[32]],[[8240,8242],"valid",[],"NV8"],[[8243,8243],"mapped",[8242,8242]],[[8244,8244],"mapped",[8242,8242,8242]],[[8245,8245],"valid",[],"NV8"],[[8246,8246],"mapped",[8245,8245]],[[8247,8247],"mapped",[8245,8245,8245]],[[8248,8251],"valid",[],"NV8"],[[8252,8252],"disallowed_STD3_mapped",[33,33]],[[8253,8253],"valid",[],"NV8"],[[8254,8254],"disallowed_STD3_mapped",[32,773]],[[8255,8262],"valid",[],"NV8"],[[8263,8263],"disallowed_STD3_mapped",[63,63]],[[8264,8264],"disallowed_STD3_mapped",[63,33]],[[8265,8265],"disallowed_STD3_mapped",[33,63]],[[8266,8269],"valid",[],"NV8"],[[8270,8274],"valid",[],"NV8"],[[8275,8276],"valid",[],"NV8"],[[8277,8278],"valid",[],"NV8"],[[8279,8279],"mapped",[8242,8242,8242,8242]],[[8280,8286],"valid",[],"NV8"],[[8287,8287],"disallowed_STD3_mapped",[32]],[[8288,8288],"ignored"],[[8289,8291],"disallowed"],[[8292,8292],"ignored"],[[8293,8293],"disallowed"],[[8294,8297],"disallowed"],[[8298,8303],"disallowed"],[[8304,8304],"mapped",[48]],[[8305,8305],"mapped",[105]],[[8306,8307],"disallowed"],[[8308,8308],"mapped",[52]],[[8309,8309],"mapped",[53]],[[8310,8310],"mapped",[54]],[[8311,8311],"mapped",[55]],[[8312,8312],"mapped",[56]],[[8313,8313],"mapped",[57]],[[8314,8314],"disallowed_STD3_mapped",[43]],[[8315,8315],"mapped",[8722]],[[8316,8316],"disallowed_STD3_mapped",[61]],[[8317,8317],"disallowed_STD3_mapped",[40]],[[8318,8318],"disallowed_STD3_mapped",[41]],[[8319,8319],"mapped",[110]],[[8320,8320],"mapped",[48]],[[8321,8321],"mapped",[49]],[[8322,8322],"mapped",[50]],[[8323,8323],"mapped",[51]],[[8324,8324],"mapped",[52]],[[8325,8325],"mapped",[53]],[[8326,8326],"mapped",[54]],[[8327,8327],"mapped",[55]],[[8328,8328],"mapped",[56]],[[8329,8329],"mapped",[57]],[[8330,8330],"disallowed_STD3_mapped",[43]],[[8331,8331],"mapped",[8722]],[[8332,8332],"disallowed_STD3_mapped",[61]],[[8333,8333],"disallowed_STD3_mapped",[40]],[[8334,8334],"disallowed_STD3_mapped",[41]],[[8335,8335],"disallowed"],[[8336,8336],"mapped",[97]],[[8337,8337],"mapped",[101]],[[8338,8338],"mapped",[111]],[[8339,8339],"mapped",[120]],[[8340,8340],"mapped",[601]],[[8341,8341],"mapped",[104]],[[8342,8342],"mapped",[107]],[[8343,8343],"mapped",[108]],[[8344,8344],"mapped",[109]],[[8345,8345],"mapped",[110]],[[8346,8346],"mapped",[112]],[[8347,8347],"mapped",[115]],[[8348,8348],"mapped",[116]],[[8349,8351],"disallowed"],[[8352,8359],"valid",[],"NV8"],[[8360,8360],"mapped",[114,115]],[[8361,8362],"valid",[],"NV8"],[[8363,8363],"valid",[],"NV8"],[[8364,8364],"valid",[],"NV8"],[[8365,8367],"valid",[],"NV8"],[[8368,8369],"valid",[],"NV8"],[[8370,8373],"valid",[],"NV8"],[[8374,8376],"valid",[],"NV8"],[[8377,8377],"valid",[],"NV8"],[[8378,8378],"valid",[],"NV8"],[[8379,8381],"valid",[],"NV8"],[[8382,8382],"valid",[],"NV8"],[[8383,8399],"disallowed"],[[8400,8417],"valid",[],"NV8"],[[8418,8419],"valid",[],"NV8"],[[8420,8426],"valid",[],"NV8"],[[8427,8427],"valid",[],"NV8"],[[8428,8431],"valid",[],"NV8"],[[8432,8432],"valid",[],"NV8"],[[8433,8447],"disallowed"],[[8448,8448],"disallowed_STD3_mapped",[97,47,99]],[[8449,8449],"disallowed_STD3_mapped",[97,47,115]],[[8450,8450],"mapped",[99]],[[8451,8451],"mapped",[176,99]],[[8452,8452],"valid",[],"NV8"],[[8453,8453],"disallowed_STD3_mapped",[99,47,111]],[[8454,8454],"disallowed_STD3_mapped",[99,47,117]],[[8455,8455],"mapped",[603]],[[8456,8456],"valid",[],"NV8"],[[8457,8457],"mapped",[176,102]],[[8458,8458],"mapped",[103]],[[8459,8462],"mapped",[104]],[[8463,8463],"mapped",[295]],[[8464,8465],"mapped",[105]],[[8466,8467],"mapped",[108]],[[8468,8468],"valid",[],"NV8"],[[8469,8469],"mapped",[110]],[[8470,8470],"mapped",[110,111]],[[8471,8472],"valid",[],"NV8"],[[8473,8473],"mapped",[112]],[[8474,8474],"mapped",[113]],[[8475,8477],"mapped",[114]],[[8478,8479],"valid",[],"NV8"],[[8480,8480],"mapped",[115,109]],[[8481,8481],"mapped",[116,101,108]],[[8482,8482],"mapped",[116,109]],[[8483,8483],"valid",[],"NV8"],[[8484,8484],"mapped",[122]],[[8485,8485],"valid",[],"NV8"],[[8486,8486],"mapped",[969]],[[8487,8487],"valid",[],"NV8"],[[8488,8488],"mapped",[122]],[[8489,8489],"valid",[],"NV8"],[[8490,8490],"mapped",[107]],[[8491,8491],"mapped",[229]],[[8492,8492],"mapped",[98]],[[8493,8493],"mapped",[99]],[[8494,8494],"valid",[],"NV8"],[[8495,8496],"mapped",[101]],[[8497,8497],"mapped",[102]],[[8498,8498],"disallowed"],[[8499,8499],"mapped",[109]],[[8500,8500],"mapped",[111]],[[8501,8501],"mapped",[1488]],[[8502,8502],"mapped",[1489]],[[8503,8503],"mapped",[1490]],[[8504,8504],"mapped",[1491]],[[8505,8505],"mapped",[105]],[[8506,8506],"valid",[],"NV8"],[[8507,8507],"mapped",[102,97,120]],[[8508,8508],"mapped",[960]],[[8509,8510],"mapped",[947]],[[8511,8511],"mapped",[960]],[[8512,8512],"mapped",[8721]],[[8513,8516],"valid",[],"NV8"],[[8517,8518],"mapped",[100]],[[8519,8519],"mapped",[101]],[[8520,8520],"mapped",[105]],[[8521,8521],"mapped",[106]],[[8522,8523],"valid",[],"NV8"],[[8524,8524],"valid",[],"NV8"],[[8525,8525],"valid",[],"NV8"],[[8526,8526],"valid"],[[8527,8527],"valid",[],"NV8"],[[8528,8528],"mapped",[49,8260,55]],[[8529,8529],"mapped",[49,8260,57]],[[8530,8530],"mapped",[49,8260,49,48]],[[8531,8531],"mapped",[49,8260,51]],[[8532,8532],"mapped",[50,8260,51]],[[8533,8533],"mapped",[49,8260,53]],[[8534,8534],"mapped",[50,8260,53]],[[8535,8535],"mapped",[51,8260,53]],[[8536,8536],"mapped",[52,8260,53]],[[8537,8537],"mapped",[49,8260,54]],[[8538,8538],"mapped",[53,8260,54]],[[8539,8539],"mapped",[49,8260,56]],[[8540,8540],"mapped",[51,8260,56]],[[8541,8541],"mapped",[53,8260,56]],[[8542,8542],"mapped",[55,8260,56]],[[8543,8543],"mapped",[49,8260]],[[8544,8544],"mapped",[105]],[[8545,8545],"mapped",[105,105]],[[8546,8546],"mapped",[105,105,105]],[[8547,8547],"mapped",[105,118]],[[8548,8548],"mapped",[118]],[[8549,8549],"mapped",[118,105]],[[8550,8550],"mapped",[118,105,105]],[[8551,8551],"mapped",[118,105,105,105]],[[8552,8552],"mapped",[105,120]],[[8553,8553],"mapped",[120]],[[8554,8554],"mapped",[120,105]],[[8555,8555],"mapped",[120,105,105]],[[8556,8556],"mapped",[108]],[[8557,8557],"mapped",[99]],[[8558,8558],"mapped",[100]],[[8559,8559],"mapped",[109]],[[8560,8560],"mapped",[105]],[[8561,8561],"mapped",[105,105]],[[8562,8562],"mapped",[105,105,105]],[[8563,8563],"mapped",[105,118]],[[8564,8564],"mapped",[118]],[[8565,8565],"mapped",[118,105]],[[8566,8566],"mapped",[118,105,105]],[[8567,8567],"mapped",[118,105,105,105]],[[8568,8568],"mapped",[105,120]],[[8569,8569],"mapped",[120]],[[8570,8570],"mapped",[120,105]],[[8571,8571],"mapped",[120,105,105]],[[8572,8572],"mapped",[108]],[[8573,8573],"mapped",[99]],[[8574,8574],"mapped",[100]],[[8575,8575],"mapped",[109]],[[8576,8578],"valid",[],"NV8"],[[8579,8579],"disallowed"],[[8580,8580],"valid"],[[8581,8584],"valid",[],"NV8"],[[8585,8585],"mapped",[48,8260,51]],[[8586,8587],"valid",[],"NV8"],[[8588,8591],"disallowed"],[[8592,8682],"valid",[],"NV8"],[[8683,8691],"valid",[],"NV8"],[[8692,8703],"valid",[],"NV8"],[[8704,8747],"valid",[],"NV8"],[[8748,8748],"mapped",[8747,8747]],[[8749,8749],"mapped",[8747,8747,8747]],[[8750,8750],"valid",[],"NV8"],[[8751,8751],"mapped",[8750,8750]],[[8752,8752],"mapped",[8750,8750,8750]],[[8753,8799],"valid",[],"NV8"],[[8800,8800],"disallowed_STD3_valid"],[[8801,8813],"valid",[],"NV8"],[[8814,8815],"disallowed_STD3_valid"],[[8816,8945],"valid",[],"NV8"],[[8946,8959],"valid",[],"NV8"],[[8960,8960],"valid",[],"NV8"],[[8961,8961],"valid",[],"NV8"],[[8962,9000],"valid",[],"NV8"],[[9001,9001],"mapped",[12296]],[[9002,9002],"mapped",[12297]],[[9003,9082],"valid",[],"NV8"],[[9083,9083],"valid",[],"NV8"],[[9084,9084],"valid",[],"NV8"],[[9085,9114],"valid",[],"NV8"],[[9115,9166],"valid",[],"NV8"],[[9167,9168],"valid",[],"NV8"],[[9169,9179],"valid",[],"NV8"],[[9180,9191],"valid",[],"NV8"],[[9192,9192],"valid",[],"NV8"],[[9193,9203],"valid",[],"NV8"],[[9204,9210],"valid",[],"NV8"],[[9211,9215],"disallowed"],[[9216,9252],"valid",[],"NV8"],[[9253,9254],"valid",[],"NV8"],[[9255,9279],"disallowed"],[[9280,9290],"valid",[],"NV8"],[[9291,9311],"disallowed"],[[9312,9312],"mapped",[49]],[[9313,9313],"mapped",[50]],[[9314,9314],"mapped",[51]],[[9315,9315],"mapped",[52]],[[9316,9316],"mapped",[53]],[[9317,9317],"mapped",[54]],[[9318,9318],"mapped",[55]],[[9319,9319],"mapped",[56]],[[9320,9320],"mapped",[57]],[[9321,9321],"mapped",[49,48]],[[9322,9322],"mapped",[49,49]],[[9323,9323],"mapped",[49,50]],[[9324,9324],"mapped",[49,51]],[[9325,9325],"mapped",[49,52]],[[9326,9326],"mapped",[49,53]],[[9327,9327],"mapped",[49,54]],[[9328,9328],"mapped",[49,55]],[[9329,9329],"mapped",[49,56]],[[9330,9330],"mapped",[49,57]],[[9331,9331],"mapped",[50,48]],[[9332,9332],"disallowed_STD3_mapped",[40,49,41]],[[9333,9333],"disallowed_STD3_mapped",[40,50,41]],[[9334,9334],"disallowed_STD3_mapped",[40,51,41]],[[9335,9335],"disallowed_STD3_mapped",[40,52,41]],[[9336,9336],"disallowed_STD3_mapped",[40,53,41]],[[9337,9337],"disallowed_STD3_mapped",[40,54,41]],[[9338,9338],"disallowed_STD3_mapped",[40,55,41]],[[9339,9339],"disallowed_STD3_mapped",[40,56,41]],[[9340,9340],"disallowed_STD3_mapped",[40,57,41]],[[9341,9341],"disallowed_STD3_mapped",[40,49,48,41]],[[9342,9342],"disallowed_STD3_mapped",[40,49,49,41]],[[9343,9343],"disallowed_STD3_mapped",[40,49,50,41]],[[9344,9344],"disallowed_STD3_mapped",[40,49,51,41]],[[9345,9345],"disallowed_STD3_mapped",[40,49,52,41]],[[9346,9346],"disallowed_STD3_mapped",[40,49,53,41]],[[9347,9347],"disallowed_STD3_mapped",[40,49,54,41]],[[9348,9348],"disallowed_STD3_mapped",[40,49,55,41]],[[9349,9349],"disallowed_STD3_mapped",[40,49,56,41]],[[9350,9350],"disallowed_STD3_mapped",[40,49,57,41]],[[9351,9351],"disallowed_STD3_mapped",[40,50,48,41]],[[9352,9371],"disallowed"],[[9372,9372],"disallowed_STD3_mapped",[40,97,41]],[[9373,9373],"disallowed_STD3_mapped",[40,98,41]],[[9374,9374],"disallowed_STD3_mapped",[40,99,41]],[[9375,9375],"disallowed_STD3_mapped",[40,100,41]],[[9376,9376],"disallowed_STD3_mapped",[40,101,41]],[[9377,9377],"disallowed_STD3_mapped",[40,102,41]],[[9378,9378],"disallowed_STD3_mapped",[40,103,41]],[[9379,9379],"disallowed_STD3_mapped",[40,104,41]],[[9380,9380],"disallowed_STD3_mapped",[40,105,41]],[[9381,9381],"disallowed_STD3_mapped",[40,106,41]],[[9382,9382],"disallowed_STD3_mapped",[40,107,41]],[[9383,9383],"disallowed_STD3_mapped",[40,108,41]],[[9384,9384],"disallowed_STD3_mapped",[40,109,41]],[[9385,9385],"disallowed_STD3_mapped",[40,110,41]],[[9386,9386],"disallowed_STD3_mapped",[40,111,41]],[[9387,9387],"disallowed_STD3_mapped",[40,112,41]],[[9388,9388],"disallowed_STD3_mapped",[40,113,41]],[[9389,9389],"disallowed_STD3_mapped",[40,114,41]],[[9390,9390],"disallowed_STD3_mapped",[40,115,41]],[[9391,9391],"disallowed_STD3_mapped",[40,116,41]],[[9392,9392],"disallowed_STD3_mapped",[40,117,41]],[[9393,9393],"disallowed_STD3_mapped",[40,118,41]],[[9394,9394],"disallowed_STD3_mapped",[40,119,41]],[[9395,9395],"disallowed_STD3_mapped",[40,120,41]],[[9396,9396],"disallowed_STD3_mapped",[40,121,41]],[[9397,9397],"disallowed_STD3_mapped",[40,122,41]],[[9398,9398],"mapped",[97]],[[9399,9399],"mapped",[98]],[[9400,9400],"mapped",[99]],[[9401,9401],"mapped",[100]],[[9402,9402],"mapped",[101]],[[9403,9403],"mapped",[102]],[[9404,9404],"mapped",[103]],[[9405,9405],"mapped",[104]],[[9406,9406],"mapped",[105]],[[9407,9407],"mapped",[106]],[[9408,9408],"mapped",[107]],[[9409,9409],"mapped",[108]],[[9410,9410],"mapped",[109]],[[9411,9411],"mapped",[110]],[[9412,9412],"mapped",[111]],[[9413,9413],"mapped",[112]],[[9414,9414],"mapped",[113]],[[9415,9415],"mapped",[114]],[[9416,9416],"mapped",[115]],[[9417,9417],"mapped",[116]],[[9418,9418],"mapped",[117]],[[9419,9419],"mapped",[118]],[[9420,9420],"mapped",[119]],[[9421,9421],"mapped",[120]],[[9422,9422],"mapped",[121]],[[9423,9423],"mapped",[122]],[[9424,9424],"mapped",[97]],[[9425,9425],"mapped",[98]],[[9426,9426],"mapped",[99]],[[9427,9427],"mapped",[100]],[[9428,9428],"mapped",[101]],[[9429,9429],"mapped",[102]],[[9430,9430],"mapped",[103]],[[9431,9431],"mapped",[104]],[[9432,9432],"mapped",[105]],[[9433,9433],"mapped",[106]],[[9434,9434],"mapped",[107]],[[9435,9435],"mapped",[108]],[[9436,9436],"mapped",[109]],[[9437,9437],"mapped",[110]],[[9438,9438],"mapped",[111]],[[9439,9439],"mapped",[112]],[[9440,9440],"mapped",[113]],[[9441,9441],"mapped",[114]],[[9442,9442],"mapped",[115]],[[9443,9443],"mapped",[116]],[[9444,9444],"mapped",[117]],[[9445,9445],"mapped",[118]],[[9446,9446],"mapped",[119]],[[9447,9447],"mapped",[120]],[[9448,9448],"mapped",[121]],[[9449,9449],"mapped",[122]],[[9450,9450],"mapped",[48]],[[9451,9470],"valid",[],"NV8"],[[9471,9471],"valid",[],"NV8"],[[9472,9621],"valid",[],"NV8"],[[9622,9631],"valid",[],"NV8"],[[9632,9711],"valid",[],"NV8"],[[9712,9719],"valid",[],"NV8"],[[9720,9727],"valid",[],"NV8"],[[9728,9747],"valid",[],"NV8"],[[9748,9749],"valid",[],"NV8"],[[9750,9751],"valid",[],"NV8"],[[9752,9752],"valid",[],"NV8"],[[9753,9753],"valid",[],"NV8"],[[9754,9839],"valid",[],"NV8"],[[9840,9841],"valid",[],"NV8"],[[9842,9853],"valid",[],"NV8"],[[9854,9855],"valid",[],"NV8"],[[9856,9865],"valid",[],"NV8"],[[9866,9873],"valid",[],"NV8"],[[9874,9884],"valid",[],"NV8"],[[9885,9885],"valid",[],"NV8"],[[9886,9887],"valid",[],"NV8"],[[9888,9889],"valid",[],"NV8"],[[9890,9905],"valid",[],"NV8"],[[9906,9906],"valid",[],"NV8"],[[9907,9916],"valid",[],"NV8"],[[9917,9919],"valid",[],"NV8"],[[9920,9923],"valid",[],"NV8"],[[9924,9933],"valid",[],"NV8"],[[9934,9934],"valid",[],"NV8"],[[9935,9953],"valid",[],"NV8"],[[9954,9954],"valid",[],"NV8"],[[9955,9955],"valid",[],"NV8"],[[9956,9959],"valid",[],"NV8"],[[9960,9983],"valid",[],"NV8"],[[9984,9984],"valid",[],"NV8"],[[9985,9988],"valid",[],"NV8"],[[9989,9989],"valid",[],"NV8"],[[9990,9993],"valid",[],"NV8"],[[9994,9995],"valid",[],"NV8"],[[9996,10023],"valid",[],"NV8"],[[10024,10024],"valid",[],"NV8"],[[10025,10059],"valid",[],"NV8"],[[10060,10060],"valid",[],"NV8"],[[10061,10061],"valid",[],"NV8"],[[10062,10062],"valid",[],"NV8"],[[10063,10066],"valid",[],"NV8"],[[10067,10069],"valid",[],"NV8"],[[10070,10070],"valid",[],"NV8"],[[10071,10071],"valid",[],"NV8"],[[10072,10078],"valid",[],"NV8"],[[10079,10080],"valid",[],"NV8"],[[10081,10087],"valid",[],"NV8"],[[10088,10101],"valid",[],"NV8"],[[10102,10132],"valid",[],"NV8"],[[10133,10135],"valid",[],"NV8"],[[10136,10159],"valid",[],"NV8"],[[10160,10160],"valid",[],"NV8"],[[10161,10174],"valid",[],"NV8"],[[10175,10175],"valid",[],"NV8"],[[10176,10182],"valid",[],"NV8"],[[10183,10186],"valid",[],"NV8"],[[10187,10187],"valid",[],"NV8"],[[10188,10188],"valid",[],"NV8"],[[10189,10189],"valid",[],"NV8"],[[10190,10191],"valid",[],"NV8"],[[10192,10219],"valid",[],"NV8"],[[10220,10223],"valid",[],"NV8"],[[10224,10239],"valid",[],"NV8"],[[10240,10495],"valid",[],"NV8"],[[10496,10763],"valid",[],"NV8"],[[10764,10764],"mapped",[8747,8747,8747,8747]],[[10765,10867],"valid",[],"NV8"],[[10868,10868],"disallowed_STD3_mapped",[58,58,61]],[[10869,10869],"disallowed_STD3_mapped",[61,61]],[[10870,10870],"disallowed_STD3_mapped",[61,61,61]],[[10871,10971],"valid",[],"NV8"],[[10972,10972],"mapped",[10973,824]],[[10973,11007],"valid",[],"NV8"],[[11008,11021],"valid",[],"NV8"],[[11022,11027],"valid",[],"NV8"],[[11028,11034],"valid",[],"NV8"],[[11035,11039],"valid",[],"NV8"],[[11040,11043],"valid",[],"NV8"],[[11044,11084],"valid",[],"NV8"],[[11085,11087],"valid",[],"NV8"],[[11088,11092],"valid",[],"NV8"],[[11093,11097],"valid",[],"NV8"],[[11098,11123],"valid",[],"NV8"],[[11124,11125],"disallowed"],[[11126,11157],"valid",[],"NV8"],[[11158,11159],"disallowed"],[[11160,11193],"valid",[],"NV8"],[[11194,11196],"disallowed"],[[11197,11208],"valid",[],"NV8"],[[11209,11209],"disallowed"],[[11210,11217],"valid",[],"NV8"],[[11218,11243],"disallowed"],[[11244,11247],"valid",[],"NV8"],[[11248,11263],"disallowed"],[[11264,11264],"mapped",[11312]],[[11265,11265],"mapped",[11313]],[[11266,11266],"mapped",[11314]],[[11267,11267],"mapped",[11315]],[[11268,11268],"mapped",[11316]],[[11269,11269],"mapped",[11317]],[[11270,11270],"mapped",[11318]],[[11271,11271],"mapped",[11319]],[[11272,11272],"mapped",[11320]],[[11273,11273],"mapped",[11321]],[[11274,11274],"mapped",[11322]],[[11275,11275],"mapped",[11323]],[[11276,11276],"mapped",[11324]],[[11277,11277],"mapped",[11325]],[[11278,11278],"mapped",[11326]],[[11279,11279],"mapped",[11327]],[[11280,11280],"mapped",[11328]],[[11281,11281],"mapped",[11329]],[[11282,11282],"mapped",[11330]],[[11283,11283],"mapped",[11331]],[[11284,11284],"mapped",[11332]],[[11285,11285],"mapped",[11333]],[[11286,11286],"mapped",[11334]],[[11287,11287],"mapped",[11335]],[[11288,11288],"mapped",[11336]],[[11289,11289],"mapped",[11337]],[[11290,11290],"mapped",[11338]],[[11291,11291],"mapped",[11339]],[[11292,11292],"mapped",[11340]],[[11293,11293],"mapped",[11341]],[[11294,11294],"mapped",[11342]],[[11295,11295],"mapped",[11343]],[[11296,11296],"mapped",[11344]],[[11297,11297],"mapped",[11345]],[[11298,11298],"mapped",[11346]],[[11299,11299],"mapped",[11347]],[[11300,11300],"mapped",[11348]],[[11301,11301],"mapped",[11349]],[[11302,11302],"mapped",[11350]],[[11303,11303],"mapped",[11351]],[[11304,11304],"mapped",[11352]],[[11305,11305],"mapped",[11353]],[[11306,11306],"mapped",[11354]],[[11307,11307],"mapped",[11355]],[[11308,11308],"mapped",[11356]],[[11309,11309],"mapped",[11357]],[[11310,11310],"mapped",[11358]],[[11311,11311],"disallowed"],[[11312,11358],"valid"],[[11359,11359],"disallowed"],[[11360,11360],"mapped",[11361]],[[11361,11361],"valid"],[[11362,11362],"mapped",[619]],[[11363,11363],"mapped",[7549]],[[11364,11364],"mapped",[637]],[[11365,11366],"valid"],[[11367,11367],"mapped",[11368]],[[11368,11368],"valid"],[[11369,11369],"mapped",[11370]],[[11370,11370],"valid"],[[11371,11371],"mapped",[11372]],[[11372,11372],"valid"],[[11373,11373],"mapped",[593]],[[11374,11374],"mapped",[625]],[[11375,11375],"mapped",[592]],[[11376,11376],"mapped",[594]],[[11377,11377],"valid"],[[11378,11378],"mapped",[11379]],[[11379,11379],"valid"],[[11380,11380],"valid"],[[11381,11381],"mapped",[11382]],[[11382,11383],"valid"],[[11384,11387],"valid"],[[11388,11388],"mapped",[106]],[[11389,11389],"mapped",[118]],[[11390,11390],"mapped",[575]],[[11391,11391],"mapped",[576]],[[11392,11392],"mapped",[11393]],[[11393,11393],"valid"],[[11394,11394],"mapped",[11395]],[[11395,11395],"valid"],[[11396,11396],"mapped",[11397]],[[11397,11397],"valid"],[[11398,11398],"mapped",[11399]],[[11399,11399],"valid"],[[11400,11400],"mapped",[11401]],[[11401,11401],"valid"],[[11402,11402],"mapped",[11403]],[[11403,11403],"valid"],[[11404,11404],"mapped",[11405]],[[11405,11405],"valid"],[[11406,11406],"mapped",[11407]],[[11407,11407],"valid"],[[11408,11408],"mapped",[11409]],[[11409,11409],"valid"],[[11410,11410],"mapped",[11411]],[[11411,11411],"valid"],[[11412,11412],"mapped",[11413]],[[11413,11413],"valid"],[[11414,11414],"mapped",[11415]],[[11415,11415],"valid"],[[11416,11416],"mapped",[11417]],[[11417,11417],"valid"],[[11418,11418],"mapped",[11419]],[[11419,11419],"valid"],[[11420,11420],"mapped",[11421]],[[11421,11421],"valid"],[[11422,11422],"mapped",[11423]],[[11423,11423],"valid"],[[11424,11424],"mapped",[11425]],[[11425,11425],"valid"],[[11426,11426],"mapped",[11427]],[[11427,11427],"valid"],[[11428,11428],"mapped",[11429]],[[11429,11429],"valid"],[[11430,11430],"mapped",[11431]],[[11431,11431],"valid"],[[11432,11432],"mapped",[11433]],[[11433,11433],"valid"],[[11434,11434],"mapped",[11435]],[[11435,11435],"valid"],[[11436,11436],"mapped",[11437]],[[11437,11437],"valid"],[[11438,11438],"mapped",[11439]],[[11439,11439],"valid"],[[11440,11440],"mapped",[11441]],[[11441,11441],"valid"],[[11442,11442],"mapped",[11443]],[[11443,11443],"valid"],[[11444,11444],"mapped",[11445]],[[11445,11445],"valid"],[[11446,11446],"mapped",[11447]],[[11447,11447],"valid"],[[11448,11448],"mapped",[11449]],[[11449,11449],"valid"],[[11450,11450],"mapped",[11451]],[[11451,11451],"valid"],[[11452,11452],"mapped",[11453]],[[11453,11453],"valid"],[[11454,11454],"mapped",[11455]],[[11455,11455],"valid"],[[11456,11456],"mapped",[11457]],[[11457,11457],"valid"],[[11458,11458],"mapped",[11459]],[[11459,11459],"valid"],[[11460,11460],"mapped",[11461]],[[11461,11461],"valid"],[[11462,11462],"mapped",[11463]],[[11463,11463],"valid"],[[11464,11464],"mapped",[11465]],[[11465,11465],"valid"],[[11466,11466],"mapped",[11467]],[[11467,11467],"valid"],[[11468,11468],"mapped",[11469]],[[11469,11469],"valid"],[[11470,11470],"mapped",[11471]],[[11471,11471],"valid"],[[11472,11472],"mapped",[11473]],[[11473,11473],"valid"],[[11474,11474],"mapped",[11475]],[[11475,11475],"valid"],[[11476,11476],"mapped",[11477]],[[11477,11477],"valid"],[[11478,11478],"mapped",[11479]],[[11479,11479],"valid"],[[11480,11480],"mapped",[11481]],[[11481,11481],"valid"],[[11482,11482],"mapped",[11483]],[[11483,11483],"valid"],[[11484,11484],"mapped",[11485]],[[11485,11485],"valid"],[[11486,11486],"mapped",[11487]],[[11487,11487],"valid"],[[11488,11488],"mapped",[11489]],[[11489,11489],"valid"],[[11490,11490],"mapped",[11491]],[[11491,11492],"valid"],[[11493,11498],"valid",[],"NV8"],[[11499,11499],"mapped",[11500]],[[11500,11500],"valid"],[[11501,11501],"mapped",[11502]],[[11502,11505],"valid"],[[11506,11506],"mapped",[11507]],[[11507,11507],"valid"],[[11508,11512],"disallowed"],[[11513,11519],"valid",[],"NV8"],[[11520,11557],"valid"],[[11558,11558],"disallowed"],[[11559,11559],"valid"],[[11560,11564],"disallowed"],[[11565,11565],"valid"],[[11566,11567],"disallowed"],[[11568,11621],"valid"],[[11622,11623],"valid"],[[11624,11630],"disallowed"],[[11631,11631],"mapped",[11617]],[[11632,11632],"valid",[],"NV8"],[[11633,11646],"disallowed"],[[11647,11647],"valid"],[[11648,11670],"valid"],[[11671,11679],"disallowed"],[[11680,11686],"valid"],[[11687,11687],"disallowed"],[[11688,11694],"valid"],[[11695,11695],"disallowed"],[[11696,11702],"valid"],[[11703,11703],"disallowed"],[[11704,11710],"valid"],[[11711,11711],"disallowed"],[[11712,11718],"valid"],[[11719,11719],"disallowed"],[[11720,11726],"valid"],[[11727,11727],"disallowed"],[[11728,11734],"valid"],[[11735,11735],"disallowed"],[[11736,11742],"valid"],[[11743,11743],"disallowed"],[[11744,11775],"valid"],[[11776,11799],"valid",[],"NV8"],[[11800,11803],"valid",[],"NV8"],[[11804,11805],"valid",[],"NV8"],[[11806,11822],"valid",[],"NV8"],[[11823,11823],"valid"],[[11824,11824],"valid",[],"NV8"],[[11825,11825],"valid",[],"NV8"],[[11826,11835],"valid",[],"NV8"],[[11836,11842],"valid",[],"NV8"],[[11843,11903],"disallowed"],[[11904,11929],"valid",[],"NV8"],[[11930,11930],"disallowed"],[[11931,11934],"valid",[],"NV8"],[[11935,11935],"mapped",[27597]],[[11936,12018],"valid",[],"NV8"],[[12019,12019],"mapped",[40863]],[[12020,12031],"disallowed"],[[12032,12032],"mapped",[19968]],[[12033,12033],"mapped",[20008]],[[12034,12034],"mapped",[20022]],[[12035,12035],"mapped",[20031]],[[12036,12036],"mapped",[20057]],[[12037,12037],"mapped",[20101]],[[12038,12038],"mapped",[20108]],[[12039,12039],"mapped",[20128]],[[12040,12040],"mapped",[20154]],[[12041,12041],"mapped",[20799]],[[12042,12042],"mapped",[20837]],[[12043,12043],"mapped",[20843]],[[12044,12044],"mapped",[20866]],[[12045,12045],"mapped",[20886]],[[12046,12046],"mapped",[20907]],[[12047,12047],"mapped",[20960]],[[12048,12048],"mapped",[20981]],[[12049,12049],"mapped",[20992]],[[12050,12050],"mapped",[21147]],[[12051,12051],"mapped",[21241]],[[12052,12052],"mapped",[21269]],[[12053,12053],"mapped",[21274]],[[12054,12054],"mapped",[21304]],[[12055,12055],"mapped",[21313]],[[12056,12056],"mapped",[21340]],[[12057,12057],"mapped",[21353]],[[12058,12058],"mapped",[21378]],[[12059,12059],"mapped",[21430]],[[12060,12060],"mapped",[21448]],[[12061,12061],"mapped",[21475]],[[12062,12062],"mapped",[22231]],[[12063,12063],"mapped",[22303]],[[12064,12064],"mapped",[22763]],[[12065,12065],"mapped",[22786]],[[12066,12066],"mapped",[22794]],[[12067,12067],"mapped",[22805]],[[12068,12068],"mapped",[22823]],[[12069,12069],"mapped",[22899]],[[12070,12070],"mapped",[23376]],[[12071,12071],"mapped",[23424]],[[12072,12072],"mapped",[23544]],[[12073,12073],"mapped",[23567]],[[12074,12074],"mapped",[23586]],[[12075,12075],"mapped",[23608]],[[12076,12076],"mapped",[23662]],[[12077,12077],"mapped",[23665]],[[12078,12078],"mapped",[24027]],[[12079,12079],"mapped",[24037]],[[12080,12080],"mapped",[24049]],[[12081,12081],"mapped",[24062]],[[12082,12082],"mapped",[24178]],[[12083,12083],"mapped",[24186]],[[12084,12084],"mapped",[24191]],[[12085,12085],"mapped",[24308]],[[12086,12086],"mapped",[24318]],[[12087,12087],"mapped",[24331]],[[12088,12088],"mapped",[24339]],[[12089,12089],"mapped",[24400]],[[12090,12090],"mapped",[24417]],[[12091,12091],"mapped",[24435]],[[12092,12092],"mapped",[24515]],[[12093,12093],"mapped",[25096]],[[12094,12094],"mapped",[25142]],[[12095,12095],"mapped",[25163]],[[12096,12096],"mapped",[25903]],[[12097,12097],"mapped",[25908]],[[12098,12098],"mapped",[25991]],[[12099,12099],"mapped",[26007]],[[12100,12100],"mapped",[26020]],[[12101,12101],"mapped",[26041]],[[12102,12102],"mapped",[26080]],[[12103,12103],"mapped",[26085]],[[12104,12104],"mapped",[26352]],[[12105,12105],"mapped",[26376]],[[12106,12106],"mapped",[26408]],[[12107,12107],"mapped",[27424]],[[12108,12108],"mapped",[27490]],[[12109,12109],"mapped",[27513]],[[12110,12110],"mapped",[27571]],[[12111,12111],"mapped",[27595]],[[12112,12112],"mapped",[27604]],[[12113,12113],"mapped",[27611]],[[12114,12114],"mapped",[27663]],[[12115,12115],"mapped",[27668]],[[12116,12116],"mapped",[27700]],[[12117,12117],"mapped",[28779]],[[12118,12118],"mapped",[29226]],[[12119,12119],"mapped",[29238]],[[12120,12120],"mapped",[29243]],[[12121,12121],"mapped",[29247]],[[12122,12122],"mapped",[29255]],[[12123,12123],"mapped",[29273]],[[12124,12124],"mapped",[29275]],[[12125,12125],"mapped",[29356]],[[12126,12126],"mapped",[29572]],[[12127,12127],"mapped",[29577]],[[12128,12128],"mapped",[29916]],[[12129,12129],"mapped",[29926]],[[12130,12130],"mapped",[29976]],[[12131,12131],"mapped",[29983]],[[12132,12132],"mapped",[29992]],[[12133,12133],"mapped",[30000]],[[12134,12134],"mapped",[30091]],[[12135,12135],"mapped",[30098]],[[12136,12136],"mapped",[30326]],[[12137,12137],"mapped",[30333]],[[12138,12138],"mapped",[30382]],[[12139,12139],"mapped",[30399]],[[12140,12140],"mapped",[30446]],[[12141,12141],"mapped",[30683]],[[12142,12142],"mapped",[30690]],[[12143,12143],"mapped",[30707]],[[12144,12144],"mapped",[31034]],[[12145,12145],"mapped",[31160]],[[12146,12146],"mapped",[31166]],[[12147,12147],"mapped",[31348]],[[12148,12148],"mapped",[31435]],[[12149,12149],"mapped",[31481]],[[12150,12150],"mapped",[31859]],[[12151,12151],"mapped",[31992]],[[12152,12152],"mapped",[32566]],[[12153,12153],"mapped",[32593]],[[12154,12154],"mapped",[32650]],[[12155,12155],"mapped",[32701]],[[12156,12156],"mapped",[32769]],[[12157,12157],"mapped",[32780]],[[12158,12158],"mapped",[32786]],[[12159,12159],"mapped",[32819]],[[12160,12160],"mapped",[32895]],[[12161,12161],"mapped",[32905]],[[12162,12162],"mapped",[33251]],[[12163,12163],"mapped",[33258]],[[12164,12164],"mapped",[33267]],[[12165,12165],"mapped",[33276]],[[12166,12166],"mapped",[33292]],[[12167,12167],"mapped",[33307]],[[12168,12168],"mapped",[33311]],[[12169,12169],"mapped",[33390]],[[12170,12170],"mapped",[33394]],[[12171,12171],"mapped",[33400]],[[12172,12172],"mapped",[34381]],[[12173,12173],"mapped",[34411]],[[12174,12174],"mapped",[34880]],[[12175,12175],"mapped",[34892]],[[12176,12176],"mapped",[34915]],[[12177,12177],"mapped",[35198]],[[12178,12178],"mapped",[35211]],[[12179,12179],"mapped",[35282]],[[12180,12180],"mapped",[35328]],[[12181,12181],"mapped",[35895]],[[12182,12182],"mapped",[35910]],[[12183,12183],"mapped",[35925]],[[12184,12184],"mapped",[35960]],[[12185,12185],"mapped",[35997]],[[12186,12186],"mapped",[36196]],[[12187,12187],"mapped",[36208]],[[12188,12188],"mapped",[36275]],[[12189,12189],"mapped",[36523]],[[12190,12190],"mapped",[36554]],[[12191,12191],"mapped",[36763]],[[12192,12192],"mapped",[36784]],[[12193,12193],"mapped",[36789]],[[12194,12194],"mapped",[37009]],[[12195,12195],"mapped",[37193]],[[12196,12196],"mapped",[37318]],[[12197,12197],"mapped",[37324]],[[12198,12198],"mapped",[37329]],[[12199,12199],"mapped",[38263]],[[12200,12200],"mapped",[38272]],[[12201,12201],"mapped",[38428]],[[12202,12202],"mapped",[38582]],[[12203,12203],"mapped",[38585]],[[12204,12204],"mapped",[38632]],[[12205,12205],"mapped",[38737]],[[12206,12206],"mapped",[38750]],[[12207,12207],"mapped",[38754]],[[12208,12208],"mapped",[38761]],[[12209,12209],"mapped",[38859]],[[12210,12210],"mapped",[38893]],[[12211,12211],"mapped",[38899]],[[12212,12212],"mapped",[38913]],[[12213,12213],"mapped",[39080]],[[12214,12214],"mapped",[39131]],[[12215,12215],"mapped",[39135]],[[12216,12216],"mapped",[39318]],[[12217,12217],"mapped",[39321]],[[12218,12218],"mapped",[39340]],[[12219,12219],"mapped",[39592]],[[12220,12220],"mapped",[39640]],[[12221,12221],"mapped",[39647]],[[12222,12222],"mapped",[39717]],[[12223,12223],"mapped",[39727]],[[12224,12224],"mapped",[39730]],[[12225,12225],"mapped",[39740]],[[12226,12226],"mapped",[39770]],[[12227,12227],"mapped",[40165]],[[12228,12228],"mapped",[40565]],[[12229,12229],"mapped",[40575]],[[12230,12230],"mapped",[40613]],[[12231,12231],"mapped",[40635]],[[12232,12232],"mapped",[40643]],[[12233,12233],"mapped",[40653]],[[12234,12234],"mapped",[40657]],[[12235,12235],"mapped",[40697]],[[12236,12236],"mapped",[40701]],[[12237,12237],"mapped",[40718]],[[12238,12238],"mapped",[40723]],[[12239,12239],"mapped",[40736]],[[12240,12240],"mapped",[40763]],[[12241,12241],"mapped",[40778]],[[12242,12242],"mapped",[40786]],[[12243,12243],"mapped",[40845]],[[12244,12244],"mapped",[40860]],[[12245,12245],"mapped",[40864]],[[12246,12271],"disallowed"],[[12272,12283],"disallowed"],[[12284,12287],"disallowed"],[[12288,12288],"disallowed_STD3_mapped",[32]],[[12289,12289],"valid",[],"NV8"],[[12290,12290],"mapped",[46]],[[12291,12292],"valid",[],"NV8"],[[12293,12295],"valid"],[[12296,12329],"valid",[],"NV8"],[[12330,12333],"valid"],[[12334,12341],"valid",[],"NV8"],[[12342,12342],"mapped",[12306]],[[12343,12343],"valid",[],"NV8"],[[12344,12344],"mapped",[21313]],[[12345,12345],"mapped",[21316]],[[12346,12346],"mapped",[21317]],[[12347,12347],"valid",[],"NV8"],[[12348,12348],"valid"],[[12349,12349],"valid",[],"NV8"],[[12350,12350],"valid",[],"NV8"],[[12351,12351],"valid",[],"NV8"],[[12352,12352],"disallowed"],[[12353,12436],"valid"],[[12437,12438],"valid"],[[12439,12440],"disallowed"],[[12441,12442],"valid"],[[12443,12443],"disallowed_STD3_mapped",[32,12441]],[[12444,12444],"disallowed_STD3_mapped",[32,12442]],[[12445,12446],"valid"],[[12447,12447],"mapped",[12424,12426]],[[12448,12448],"valid",[],"NV8"],[[12449,12542],"valid"],[[12543,12543],"mapped",[12467,12488]],[[12544,12548],"disallowed"],[[12549,12588],"valid"],[[12589,12589],"valid"],[[12590,12592],"disallowed"],[[12593,12593],"mapped",[4352]],[[12594,12594],"mapped",[4353]],[[12595,12595],"mapped",[4522]],[[12596,12596],"mapped",[4354]],[[12597,12597],"mapped",[4524]],[[12598,12598],"mapped",[4525]],[[12599,12599],"mapped",[4355]],[[12600,12600],"mapped",[4356]],[[12601,12601],"mapped",[4357]],[[12602,12602],"mapped",[4528]],[[12603,12603],"mapped",[4529]],[[12604,12604],"mapped",[4530]],[[12605,12605],"mapped",[4531]],[[12606,12606],"mapped",[4532]],[[12607,12607],"mapped",[4533]],[[12608,12608],"mapped",[4378]],[[12609,12609],"mapped",[4358]],[[12610,12610],"mapped",[4359]],[[12611,12611],"mapped",[4360]],[[12612,12612],"mapped",[4385]],[[12613,12613],"mapped",[4361]],[[12614,12614],"mapped",[4362]],[[12615,12615],"mapped",[4363]],[[12616,12616],"mapped",[4364]],[[12617,12617],"mapped",[4365]],[[12618,12618],"mapped",[4366]],[[12619,12619],"mapped",[4367]],[[12620,12620],"mapped",[4368]],[[12621,12621],"mapped",[4369]],[[12622,12622],"mapped",[4370]],[[12623,12623],"mapped",[4449]],[[12624,12624],"mapped",[4450]],[[12625,12625],"mapped",[4451]],[[12626,12626],"mapped",[4452]],[[12627,12627],"mapped",[4453]],[[12628,12628],"mapped",[4454]],[[12629,12629],"mapped",[4455]],[[12630,12630],"mapped",[4456]],[[12631,12631],"mapped",[4457]],[[12632,12632],"mapped",[4458]],[[12633,12633],"mapped",[4459]],[[12634,12634],"mapped",[4460]],[[12635,12635],"mapped",[4461]],[[12636,12636],"mapped",[4462]],[[12637,12637],"mapped",[4463]],[[12638,12638],"mapped",[4464]],[[12639,12639],"mapped",[4465]],[[12640,12640],"mapped",[4466]],[[12641,12641],"mapped",[4467]],[[12642,12642],"mapped",[4468]],[[12643,12643],"mapped",[4469]],[[12644,12644],"disallowed"],[[12645,12645],"mapped",[4372]],[[12646,12646],"mapped",[4373]],[[12647,12647],"mapped",[4551]],[[12648,12648],"mapped",[4552]],[[12649,12649],"mapped",[4556]],[[12650,12650],"mapped",[4558]],[[12651,12651],"mapped",[4563]],[[12652,12652],"mapped",[4567]],[[12653,12653],"mapped",[4569]],[[12654,12654],"mapped",[4380]],[[12655,12655],"mapped",[4573]],[[12656,12656],"mapped",[4575]],[[12657,12657],"mapped",[4381]],[[12658,12658],"mapped",[4382]],[[12659,12659],"mapped",[4384]],[[12660,12660],"mapped",[4386]],[[12661,12661],"mapped",[4387]],[[12662,12662],"mapped",[4391]],[[12663,12663],"mapped",[4393]],[[12664,12664],"mapped",[4395]],[[12665,12665],"mapped",[4396]],[[12666,12666],"mapped",[4397]],[[12667,12667],"mapped",[4398]],[[12668,12668],"mapped",[4399]],[[12669,12669],"mapped",[4402]],[[12670,12670],"mapped",[4406]],[[12671,12671],"mapped",[4416]],[[12672,12672],"mapped",[4423]],[[12673,12673],"mapped",[4428]],[[12674,12674],"mapped",[4593]],[[12675,12675],"mapped",[4594]],[[12676,12676],"mapped",[4439]],[[12677,12677],"mapped",[4440]],[[12678,12678],"mapped",[4441]],[[12679,12679],"mapped",[4484]],[[12680,12680],"mapped",[4485]],[[12681,12681],"mapped",[4488]],[[12682,12682],"mapped",[4497]],[[12683,12683],"mapped",[4498]],[[12684,12684],"mapped",[4500]],[[12685,12685],"mapped",[4510]],[[12686,12686],"mapped",[4513]],[[12687,12687],"disallowed"],[[12688,12689],"valid",[],"NV8"],[[12690,12690],"mapped",[19968]],[[12691,12691],"mapped",[20108]],[[12692,12692],"mapped",[19977]],[[12693,12693],"mapped",[22235]],[[12694,12694],"mapped",[19978]],[[12695,12695],"mapped",[20013]],[[12696,12696],"mapped",[19979]],[[12697,12697],"mapped",[30002]],[[12698,12698],"mapped",[20057]],[[12699,12699],"mapped",[19993]],[[12700,12700],"mapped",[19969]],[[12701,12701],"mapped",[22825]],[[12702,12702],"mapped",[22320]],[[12703,12703],"mapped",[20154]],[[12704,12727],"valid"],[[12728,12730],"valid"],[[12731,12735],"disallowed"],[[12736,12751],"valid",[],"NV8"],[[12752,12771],"valid",[],"NV8"],[[12772,12783],"disallowed"],[[12784,12799],"valid"],[[12800,12800],"disallowed_STD3_mapped",[40,4352,41]],[[12801,12801],"disallowed_STD3_mapped",[40,4354,41]],[[12802,12802],"disallowed_STD3_mapped",[40,4355,41]],[[12803,12803],"disallowed_STD3_mapped",[40,4357,41]],[[12804,12804],"disallowed_STD3_mapped",[40,4358,41]],[[12805,12805],"disallowed_STD3_mapped",[40,4359,41]],[[12806,12806],"disallowed_STD3_mapped",[40,4361,41]],[[12807,12807],"disallowed_STD3_mapped",[40,4363,41]],[[12808,12808],"disallowed_STD3_mapped",[40,4364,41]],[[12809,12809],"disallowed_STD3_mapped",[40,4366,41]],[[12810,12810],"disallowed_STD3_mapped",[40,4367,41]],[[12811,12811],"disallowed_STD3_mapped",[40,4368,41]],[[12812,12812],"disallowed_STD3_mapped",[40,4369,41]],[[12813,12813],"disallowed_STD3_mapped",[40,4370,41]],[[12814,12814],"disallowed_STD3_mapped",[40,44032,41]],[[12815,12815],"disallowed_STD3_mapped",[40,45208,41]],[[12816,12816],"disallowed_STD3_mapped",[40,45796,41]],[[12817,12817],"disallowed_STD3_mapped",[40,46972,41]],[[12818,12818],"disallowed_STD3_mapped",[40,47560,41]],[[12819,12819],"disallowed_STD3_mapped",[40,48148,41]],[[12820,12820],"disallowed_STD3_mapped",[40,49324,41]],[[12821,12821],"disallowed_STD3_mapped",[40,50500,41]],[[12822,12822],"disallowed_STD3_mapped",[40,51088,41]],[[12823,12823],"disallowed_STD3_mapped",[40,52264,41]],[[12824,12824],"disallowed_STD3_mapped",[40,52852,41]],[[12825,12825],"disallowed_STD3_mapped",[40,53440,41]],[[12826,12826],"disallowed_STD3_mapped",[40,54028,41]],[[12827,12827],"disallowed_STD3_mapped",[40,54616,41]],[[12828,12828],"disallowed_STD3_mapped",[40,51452,41]],[[12829,12829],"disallowed_STD3_mapped",[40,50724,51204,41]],[[12830,12830],"disallowed_STD3_mapped",[40,50724,54980,41]],[[12831,12831],"disallowed"],[[12832,12832],"disallowed_STD3_mapped",[40,19968,41]],[[12833,12833],"disallowed_STD3_mapped",[40,20108,41]],[[12834,12834],"disallowed_STD3_mapped",[40,19977,41]],[[12835,12835],"disallowed_STD3_mapped",[40,22235,41]],[[12836,12836],"disallowed_STD3_mapped",[40,20116,41]],[[12837,12837],"disallowed_STD3_mapped",[40,20845,41]],[[12838,12838],"disallowed_STD3_mapped",[40,19971,41]],[[12839,12839],"disallowed_STD3_mapped",[40,20843,41]],[[12840,12840],"disallowed_STD3_mapped",[40,20061,41]],[[12841,12841],"disallowed_STD3_mapped",[40,21313,41]],[[12842,12842],"disallowed_STD3_mapped",[40,26376,41]],[[12843,12843],"disallowed_STD3_mapped",[40,28779,41]],[[12844,12844],"disallowed_STD3_mapped",[40,27700,41]],[[12845,12845],"disallowed_STD3_mapped",[40,26408,41]],[[12846,12846],"disallowed_STD3_mapped",[40,37329,41]],[[12847,12847],"disallowed_STD3_mapped",[40,22303,41]],[[12848,12848],"disallowed_STD3_mapped",[40,26085,41]],[[12849,12849],"disallowed_STD3_mapped",[40,26666,41]],[[12850,12850],"disallowed_STD3_mapped",[40,26377,41]],[[12851,12851],"disallowed_STD3_mapped",[40,31038,41]],[[12852,12852],"disallowed_STD3_mapped",[40,21517,41]],[[12853,12853],"disallowed_STD3_mapped",[40,29305,41]],[[12854,12854],"disallowed_STD3_mapped",[40,36001,41]],[[12855,12855],"disallowed_STD3_mapped",[40,31069,41]],[[12856,12856],"disallowed_STD3_mapped",[40,21172,41]],[[12857,12857],"disallowed_STD3_mapped",[40,20195,41]],[[12858,12858],"disallowed_STD3_mapped",[40,21628,41]],[[12859,12859],"disallowed_STD3_mapped",[40,23398,41]],[[12860,12860],"disallowed_STD3_mapped",[40,30435,41]],[[12861,12861],"disallowed_STD3_mapped",[40,20225,41]],[[12862,12862],"disallowed_STD3_mapped",[40,36039,41]],[[12863,12863],"disallowed_STD3_mapped",[40,21332,41]],[[12864,12864],"disallowed_STD3_mapped",[40,31085,41]],[[12865,12865],"disallowed_STD3_mapped",[40,20241,41]],[[12866,12866],"disallowed_STD3_mapped",[40,33258,41]],[[12867,12867],"disallowed_STD3_mapped",[40,33267,41]],[[12868,12868],"mapped",[21839]],[[12869,12869],"mapped",[24188]],[[12870,12870],"mapped",[25991]],[[12871,12871],"mapped",[31631]],[[12872,12879],"valid",[],"NV8"],[[12880,12880],"mapped",[112,116,101]],[[12881,12881],"mapped",[50,49]],[[12882,12882],"mapped",[50,50]],[[12883,12883],"mapped",[50,51]],[[12884,12884],"mapped",[50,52]],[[12885,12885],"mapped",[50,53]],[[12886,12886],"mapped",[50,54]],[[12887,12887],"mapped",[50,55]],[[12888,12888],"mapped",[50,56]],[[12889,12889],"mapped",[50,57]],[[12890,12890],"mapped",[51,48]],[[12891,12891],"mapped",[51,49]],[[12892,12892],"mapped",[51,50]],[[12893,12893],"mapped",[51,51]],[[12894,12894],"mapped",[51,52]],[[12895,12895],"mapped",[51,53]],[[12896,12896],"mapped",[4352]],[[12897,12897],"mapped",[4354]],[[12898,12898],"mapped",[4355]],[[12899,12899],"mapped",[4357]],[[12900,12900],"mapped",[4358]],[[12901,12901],"mapped",[4359]],[[12902,12902],"mapped",[4361]],[[12903,12903],"mapped",[4363]],[[12904,12904],"mapped",[4364]],[[12905,12905],"mapped",[4366]],[[12906,12906],"mapped",[4367]],[[12907,12907],"mapped",[4368]],[[12908,12908],"mapped",[4369]],[[12909,12909],"mapped",[4370]],[[12910,12910],"mapped",[44032]],[[12911,12911],"mapped",[45208]],[[12912,12912],"mapped",[45796]],[[12913,12913],"mapped",[46972]],[[12914,12914],"mapped",[47560]],[[12915,12915],"mapped",[48148]],[[12916,12916],"mapped",[49324]],[[12917,12917],"mapped",[50500]],[[12918,12918],"mapped",[51088]],[[12919,12919],"mapped",[52264]],[[12920,12920],"mapped",[52852]],[[12921,12921],"mapped",[53440]],[[12922,12922],"mapped",[54028]],[[12923,12923],"mapped",[54616]],[[12924,12924],"mapped",[52280,44256]],[[12925,12925],"mapped",[51452,51032]],[[12926,12926],"mapped",[50864]],[[12927,12927],"valid",[],"NV8"],[[12928,12928],"mapped",[19968]],[[12929,12929],"mapped",[20108]],[[12930,12930],"mapped",[19977]],[[12931,12931],"mapped",[22235]],[[12932,12932],"mapped",[20116]],[[12933,12933],"mapped",[20845]],[[12934,12934],"mapped",[19971]],[[12935,12935],"mapped",[20843]],[[12936,12936],"mapped",[20061]],[[12937,12937],"mapped",[21313]],[[12938,12938],"mapped",[26376]],[[12939,12939],"mapped",[28779]],[[12940,12940],"mapped",[27700]],[[12941,12941],"mapped",[26408]],[[12942,12942],"mapped",[37329]],[[12943,12943],"mapped",[22303]],[[12944,12944],"mapped",[26085]],[[12945,12945],"mapped",[26666]],[[12946,12946],"mapped",[26377]],[[12947,12947],"mapped",[31038]],[[12948,12948],"mapped",[21517]],[[12949,12949],"mapped",[29305]],[[12950,12950],"mapped",[36001]],[[12951,12951],"mapped",[31069]],[[12952,12952],"mapped",[21172]],[[12953,12953],"mapped",[31192]],[[12954,12954],"mapped",[30007]],[[12955,12955],"mapped",[22899]],[[12956,12956],"mapped",[36969]],[[12957,12957],"mapped",[20778]],[[12958,12958],"mapped",[21360]],[[12959,12959],"mapped",[27880]],[[12960,12960],"mapped",[38917]],[[12961,12961],"mapped",[20241]],[[12962,12962],"mapped",[20889]],[[12963,12963],"mapped",[27491]],[[12964,12964],"mapped",[19978]],[[12965,12965],"mapped",[20013]],[[12966,12966],"mapped",[19979]],[[12967,12967],"mapped",[24038]],[[12968,12968],"mapped",[21491]],[[12969,12969],"mapped",[21307]],[[12970,12970],"mapped",[23447]],[[12971,12971],"mapped",[23398]],[[12972,12972],"mapped",[30435]],[[12973,12973],"mapped",[20225]],[[12974,12974],"mapped",[36039]],[[12975,12975],"mapped",[21332]],[[12976,12976],"mapped",[22812]],[[12977,12977],"mapped",[51,54]],[[12978,12978],"mapped",[51,55]],[[12979,12979],"mapped",[51,56]],[[12980,12980],"mapped",[51,57]],[[12981,12981],"mapped",[52,48]],[[12982,12982],"mapped",[52,49]],[[12983,12983],"mapped",[52,50]],[[12984,12984],"mapped",[52,51]],[[12985,12985],"mapped",[52,52]],[[12986,12986],"mapped",[52,53]],[[12987,12987],"mapped",[52,54]],[[12988,12988],"mapped",[52,55]],[[12989,12989],"mapped",[52,56]],[[12990,12990],"mapped",[52,57]],[[12991,12991],"mapped",[53,48]],[[12992,12992],"mapped",[49,26376]],[[12993,12993],"mapped",[50,26376]],[[12994,12994],"mapped",[51,26376]],[[12995,12995],"mapped",[52,26376]],[[12996,12996],"mapped",[53,26376]],[[12997,12997],"mapped",[54,26376]],[[12998,12998],"mapped",[55,26376]],[[12999,12999],"mapped",[56,26376]],[[13000,13000],"mapped",[57,26376]],[[13001,13001],"mapped",[49,48,26376]],[[13002,13002],"mapped",[49,49,26376]],[[13003,13003],"mapped",[49,50,26376]],[[13004,13004],"mapped",[104,103]],[[13005,13005],"mapped",[101,114,103]],[[13006,13006],"mapped",[101,118]],[[13007,13007],"mapped",[108,116,100]],[[13008,13008],"mapped",[12450]],[[13009,13009],"mapped",[12452]],[[13010,13010],"mapped",[12454]],[[13011,13011],"mapped",[12456]],[[13012,13012],"mapped",[12458]],[[13013,13013],"mapped",[12459]],[[13014,13014],"mapped",[12461]],[[13015,13015],"mapped",[12463]],[[13016,13016],"mapped",[12465]],[[13017,13017],"mapped",[12467]],[[13018,13018],"mapped",[12469]],[[13019,13019],"mapped",[12471]],[[13020,13020],"mapped",[12473]],[[13021,13021],"mapped",[12475]],[[13022,13022],"mapped",[12477]],[[13023,13023],"mapped",[12479]],[[13024,13024],"mapped",[12481]],[[13025,13025],"mapped",[12484]],[[13026,13026],"mapped",[12486]],[[13027,13027],"mapped",[12488]],[[13028,13028],"mapped",[12490]],[[13029,13029],"mapped",[12491]],[[13030,13030],"mapped",[12492]],[[13031,13031],"mapped",[12493]],[[13032,13032],"mapped",[12494]],[[13033,13033],"mapped",[12495]],[[13034,13034],"mapped",[12498]],[[13035,13035],"mapped",[12501]],[[13036,13036],"mapped",[12504]],[[13037,13037],"mapped",[12507]],[[13038,13038],"mapped",[12510]],[[13039,13039],"mapped",[12511]],[[13040,13040],"mapped",[12512]],[[13041,13041],"mapped",[12513]],[[13042,13042],"mapped",[12514]],[[13043,13043],"mapped",[12516]],[[13044,13044],"mapped",[12518]],[[13045,13045],"mapped",[12520]],[[13046,13046],"mapped",[12521]],[[13047,13047],"mapped",[12522]],[[13048,13048],"mapped",[12523]],[[13049,13049],"mapped",[12524]],[[13050,13050],"mapped",[12525]],[[13051,13051],"mapped",[12527]],[[13052,13052],"mapped",[12528]],[[13053,13053],"mapped",[12529]],[[13054,13054],"mapped",[12530]],[[13055,13055],"disallowed"],[[13056,13056],"mapped",[12450,12497,12540,12488]],[[13057,13057],"mapped",[12450,12523,12501,12449]],[[13058,13058],"mapped",[12450,12531,12506,12450]],[[13059,13059],"mapped",[12450,12540,12523]],[[13060,13060],"mapped",[12452,12491,12531,12464]],[[13061,13061],"mapped",[12452,12531,12481]],[[13062,13062],"mapped",[12454,12457,12531]],[[13063,13063],"mapped",[12456,12473,12463,12540,12489]],[[13064,13064],"mapped",[12456,12540,12459,12540]],[[13065,13065],"mapped",[12458,12531,12473]],[[13066,13066],"mapped",[12458,12540,12512]],[[13067,13067],"mapped",[12459,12452,12522]],[[13068,13068],"mapped",[12459,12521,12483,12488]],[[13069,13069],"mapped",[12459,12525,12522,12540]],[[13070,13070],"mapped",[12460,12525,12531]],[[13071,13071],"mapped",[12460,12531,12510]],[[13072,13072],"mapped",[12462,12460]],[[13073,13073],"mapped",[12462,12491,12540]],[[13074,13074],"mapped",[12461,12517,12522,12540]],[[13075,13075],"mapped",[12462,12523,12480,12540]],[[13076,13076],"mapped",[12461,12525]],[[13077,13077],"mapped",[12461,12525,12464,12521,12512]],[[13078,13078],"mapped",[12461,12525,12513,12540,12488,12523]],[[13079,13079],"mapped",[12461,12525,12527,12483,12488]],[[13080,13080],"mapped",[12464,12521,12512]],[[13081,13081],"mapped",[12464,12521,12512,12488,12531]],[[13082,13082],"mapped",[12463,12523,12476,12452,12525]],[[13083,13083],"mapped",[12463,12525,12540,12493]],[[13084,13084],"mapped",[12465,12540,12473]],[[13085,13085],"mapped",[12467,12523,12490]],[[13086,13086],"mapped",[12467,12540,12509]],[[13087,13087],"mapped",[12469,12452,12463,12523]],[[13088,13088],"mapped",[12469,12531,12481,12540,12512]],[[13089,13089],"mapped",[12471,12522,12531,12464]],[[13090,13090],"mapped",[12475,12531,12481]],[[13091,13091],"mapped",[12475,12531,12488]],[[13092,13092],"mapped",[12480,12540,12473]],[[13093,13093],"mapped",[12487,12471]],[[13094,13094],"mapped",[12489,12523]],[[13095,13095],"mapped",[12488,12531]],[[13096,13096],"mapped",[12490,12494]],[[13097,13097],"mapped",[12494,12483,12488]],[[13098,13098],"mapped",[12495,12452,12484]],[[13099,13099],"mapped",[12497,12540,12475,12531,12488]],[[13100,13100],"mapped",[12497,12540,12484]],[[13101,13101],"mapped",[12496,12540,12524,12523]],[[13102,13102],"mapped",[12500,12450,12473,12488,12523]],[[13103,13103],"mapped",[12500,12463,12523]],[[13104,13104],"mapped",[12500,12467]],[[13105,13105],"mapped",[12499,12523]],[[13106,13106],"mapped",[12501,12449,12521,12483,12489]],[[13107,13107],"mapped",[12501,12451,12540,12488]],[[13108,13108],"mapped",[12502,12483,12471,12455,12523]],[[13109,13109],"mapped",[12501,12521,12531]],[[13110,13110],"mapped",[12504,12463,12479,12540,12523]],[[13111,13111],"mapped",[12506,12477]],[[13112,13112],"mapped",[12506,12491,12498]],[[13113,13113],"mapped",[12504,12523,12484]],[[13114,13114],"mapped",[12506,12531,12473]],[[13115,13115],"mapped",[12506,12540,12472]],[[13116,13116],"mapped",[12505,12540,12479]],[[13117,13117],"mapped",[12509,12452,12531,12488]],[[13118,13118],"mapped",[12508,12523,12488]],[[13119,13119],"mapped",[12507,12531]],[[13120,13120],"mapped",[12509,12531,12489]],[[13121,13121],"mapped",[12507,12540,12523]],[[13122,13122],"mapped",[12507,12540,12531]],[[13123,13123],"mapped",[12510,12452,12463,12525]],[[13124,13124],"mapped",[12510,12452,12523]],[[13125,13125],"mapped",[12510,12483,12495]],[[13126,13126],"mapped",[12510,12523,12463]],[[13127,13127],"mapped",[12510,12531,12471,12519,12531]],[[13128,13128],"mapped",[12511,12463,12525,12531]],[[13129,13129],"mapped",[12511,12522]],[[13130,13130],"mapped",[12511,12522,12496,12540,12523]],[[13131,13131],"mapped",[12513,12460]],[[13132,13132],"mapped",[12513,12460,12488,12531]],[[13133,13133],"mapped",[12513,12540,12488,12523]],[[13134,13134],"mapped",[12516,12540,12489]],[[13135,13135],"mapped",[12516,12540,12523]],[[13136,13136],"mapped",[12518,12450,12531]],[[13137,13137],"mapped",[12522,12483,12488,12523]],[[13138,13138],"mapped",[12522,12521]],[[13139,13139],"mapped",[12523,12500,12540]],[[13140,13140],"mapped",[12523,12540,12502,12523]],[[13141,13141],"mapped",[12524,12512]],[[13142,13142],"mapped",[12524,12531,12488,12466,12531]],[[13143,13143],"mapped",[12527,12483,12488]],[[13144,13144],"mapped",[48,28857]],[[13145,13145],"mapped",[49,28857]],[[13146,13146],"mapped",[50,28857]],[[13147,13147],"mapped",[51,28857]],[[13148,13148],"mapped",[52,28857]],[[13149,13149],"mapped",[53,28857]],[[13150,13150],"mapped",[54,28857]],[[13151,13151],"mapped",[55,28857]],[[13152,13152],"mapped",[56,28857]],[[13153,13153],"mapped",[57,28857]],[[13154,13154],"mapped",[49,48,28857]],[[13155,13155],"mapped",[49,49,28857]],[[13156,13156],"mapped",[49,50,28857]],[[13157,13157],"mapped",[49,51,28857]],[[13158,13158],"mapped",[49,52,28857]],[[13159,13159],"mapped",[49,53,28857]],[[13160,13160],"mapped",[49,54,28857]],[[13161,13161],"mapped",[49,55,28857]],[[13162,13162],"mapped",[49,56,28857]],[[13163,13163],"mapped",[49,57,28857]],[[13164,13164],"mapped",[50,48,28857]],[[13165,13165],"mapped",[50,49,28857]],[[13166,13166],"mapped",[50,50,28857]],[[13167,13167],"mapped",[50,51,28857]],[[13168,13168],"mapped",[50,52,28857]],[[13169,13169],"mapped",[104,112,97]],[[13170,13170],"mapped",[100,97]],[[13171,13171],"mapped",[97,117]],[[13172,13172],"mapped",[98,97,114]],[[13173,13173],"mapped",[111,118]],[[13174,13174],"mapped",[112,99]],[[13175,13175],"mapped",[100,109]],[[13176,13176],"mapped",[100,109,50]],[[13177,13177],"mapped",[100,109,51]],[[13178,13178],"mapped",[105,117]],[[13179,13179],"mapped",[24179,25104]],[[13180,13180],"mapped",[26157,21644]],[[13181,13181],"mapped",[22823,27491]],[[13182,13182],"mapped",[26126,27835]],[[13183,13183],"mapped",[26666,24335,20250,31038]],[[13184,13184],"mapped",[112,97]],[[13185,13185],"mapped",[110,97]],[[13186,13186],"mapped",[956,97]],[[13187,13187],"mapped",[109,97]],[[13188,13188],"mapped",[107,97]],[[13189,13189],"mapped",[107,98]],[[13190,13190],"mapped",[109,98]],[[13191,13191],"mapped",[103,98]],[[13192,13192],"mapped",[99,97,108]],[[13193,13193],"mapped",[107,99,97,108]],[[13194,13194],"mapped",[112,102]],[[13195,13195],"mapped",[110,102]],[[13196,13196],"mapped",[956,102]],[[13197,13197],"mapped",[956,103]],[[13198,13198],"mapped",[109,103]],[[13199,13199],"mapped",[107,103]],[[13200,13200],"mapped",[104,122]],[[13201,13201],"mapped",[107,104,122]],[[13202,13202],"mapped",[109,104,122]],[[13203,13203],"mapped",[103,104,122]],[[13204,13204],"mapped",[116,104,122]],[[13205,13205],"mapped",[956,108]],[[13206,13206],"mapped",[109,108]],[[13207,13207],"mapped",[100,108]],[[13208,13208],"mapped",[107,108]],[[13209,13209],"mapped",[102,109]],[[13210,13210],"mapped",[110,109]],[[13211,13211],"mapped",[956,109]],[[13212,13212],"mapped",[109,109]],[[13213,13213],"mapped",[99,109]],[[13214,13214],"mapped",[107,109]],[[13215,13215],"mapped",[109,109,50]],[[13216,13216],"mapped",[99,109,50]],[[13217,13217],"mapped",[109,50]],[[13218,13218],"mapped",[107,109,50]],[[13219,13219],"mapped",[109,109,51]],[[13220,13220],"mapped",[99,109,51]],[[13221,13221],"mapped",[109,51]],[[13222,13222],"mapped",[107,109,51]],[[13223,13223],"mapped",[109,8725,115]],[[13224,13224],"mapped",[109,8725,115,50]],[[13225,13225],"mapped",[112,97]],[[13226,13226],"mapped",[107,112,97]],[[13227,13227],"mapped",[109,112,97]],[[13228,13228],"mapped",[103,112,97]],[[13229,13229],"mapped",[114,97,100]],[[13230,13230],"mapped",[114,97,100,8725,115]],[[13231,13231],"mapped",[114,97,100,8725,115,50]],[[13232,13232],"mapped",[112,115]],[[13233,13233],"mapped",[110,115]],[[13234,13234],"mapped",[956,115]],[[13235,13235],"mapped",[109,115]],[[13236,13236],"mapped",[112,118]],[[13237,13237],"mapped",[110,118]],[[13238,13238],"mapped",[956,118]],[[13239,13239],"mapped",[109,118]],[[13240,13240],"mapped",[107,118]],[[13241,13241],"mapped",[109,118]],[[13242,13242],"mapped",[112,119]],[[13243,13243],"mapped",[110,119]],[[13244,13244],"mapped",[956,119]],[[13245,13245],"mapped",[109,119]],[[13246,13246],"mapped",[107,119]],[[13247,13247],"mapped",[109,119]],[[13248,13248],"mapped",[107,969]],[[13249,13249],"mapped",[109,969]],[[13250,13250],"disallowed"],[[13251,13251],"mapped",[98,113]],[[13252,13252],"mapped",[99,99]],[[13253,13253],"mapped",[99,100]],[[13254,13254],"mapped",[99,8725,107,103]],[[13255,13255],"disallowed"],[[13256,13256],"mapped",[100,98]],[[13257,13257],"mapped",[103,121]],[[13258,13258],"mapped",[104,97]],[[13259,13259],"mapped",[104,112]],[[13260,13260],"mapped",[105,110]],[[13261,13261],"mapped",[107,107]],[[13262,13262],"mapped",[107,109]],[[13263,13263],"mapped",[107,116]],[[13264,13264],"mapped",[108,109]],[[13265,13265],"mapped",[108,110]],[[13266,13266],"mapped",[108,111,103]],[[13267,13267],"mapped",[108,120]],[[13268,13268],"mapped",[109,98]],[[13269,13269],"mapped",[109,105,108]],[[13270,13270],"mapped",[109,111,108]],[[13271,13271],"mapped",[112,104]],[[13272,13272],"disallowed"],[[13273,13273],"mapped",[112,112,109]],[[13274,13274],"mapped",[112,114]],[[13275,13275],"mapped",[115,114]],[[13276,13276],"mapped",[115,118]],[[13277,13277],"mapped",[119,98]],[[13278,13278],"mapped",[118,8725,109]],[[13279,13279],"mapped",[97,8725,109]],[[13280,13280],"mapped",[49,26085]],[[13281,13281],"mapped",[50,26085]],[[13282,13282],"mapped",[51,26085]],[[13283,13283],"mapped",[52,26085]],[[13284,13284],"mapped",[53,26085]],[[13285,13285],"mapped",[54,26085]],[[13286,13286],"mapped",[55,26085]],[[13287,13287],"mapped",[56,26085]],[[13288,13288],"mapped",[57,26085]],[[13289,13289],"mapped",[49,48,26085]],[[13290,13290],"mapped",[49,49,26085]],[[13291,13291],"mapped",[49,50,26085]],[[13292,13292],"mapped",[49,51,26085]],[[13293,13293],"mapped",[49,52,26085]],[[13294,13294],"mapped",[49,53,26085]],[[13295,13295],"mapped",[49,54,26085]],[[13296,13296],"mapped",[49,55,26085]],[[13297,13297],"mapped",[49,56,26085]],[[13298,13298],"mapped",[49,57,26085]],[[13299,13299],"mapped",[50,48,26085]],[[13300,13300],"mapped",[50,49,26085]],[[13301,13301],"mapped",[50,50,26085]],[[13302,13302],"mapped",[50,51,26085]],[[13303,13303],"mapped",[50,52,26085]],[[13304,13304],"mapped",[50,53,26085]],[[13305,13305],"mapped",[50,54,26085]],[[13306,13306],"mapped",[50,55,26085]],[[13307,13307],"mapped",[50,56,26085]],[[13308,13308],"mapped",[50,57,26085]],[[13309,13309],"mapped",[51,48,26085]],[[13310,13310],"mapped",[51,49,26085]],[[13311,13311],"mapped",[103,97,108]],[[13312,19893],"valid"],[[19894,19903],"disallowed"],[[19904,19967],"valid",[],"NV8"],[[19968,40869],"valid"],[[40870,40891],"valid"],[[40892,40899],"valid"],[[40900,40907],"valid"],[[40908,40908],"valid"],[[40909,40917],"valid"],[[40918,40959],"disallowed"],[[40960,42124],"valid"],[[42125,42127],"disallowed"],[[42128,42145],"valid",[],"NV8"],[[42146,42147],"valid",[],"NV8"],[[42148,42163],"valid",[],"NV8"],[[42164,42164],"valid",[],"NV8"],[[42165,42176],"valid",[],"NV8"],[[42177,42177],"valid",[],"NV8"],[[42178,42180],"valid",[],"NV8"],[[42181,42181],"valid",[],"NV8"],[[42182,42182],"valid",[],"NV8"],[[42183,42191],"disallowed"],[[42192,42237],"valid"],[[42238,42239],"valid",[],"NV8"],[[42240,42508],"valid"],[[42509,42511],"valid",[],"NV8"],[[42512,42539],"valid"],[[42540,42559],"disallowed"],[[42560,42560],"mapped",[42561]],[[42561,42561],"valid"],[[42562,42562],"mapped",[42563]],[[42563,42563],"valid"],[[42564,42564],"mapped",[42565]],[[42565,42565],"valid"],[[42566,42566],"mapped",[42567]],[[42567,42567],"valid"],[[42568,42568],"mapped",[42569]],[[42569,42569],"valid"],[[42570,42570],"mapped",[42571]],[[42571,42571],"valid"],[[42572,42572],"mapped",[42573]],[[42573,42573],"valid"],[[42574,42574],"mapped",[42575]],[[42575,42575],"valid"],[[42576,42576],"mapped",[42577]],[[42577,42577],"valid"],[[42578,42578],"mapped",[42579]],[[42579,42579],"valid"],[[42580,42580],"mapped",[42581]],[[42581,42581],"valid"],[[42582,42582],"mapped",[42583]],[[42583,42583],"valid"],[[42584,42584],"mapped",[42585]],[[42585,42585],"valid"],[[42586,42586],"mapped",[42587]],[[42587,42587],"valid"],[[42588,42588],"mapped",[42589]],[[42589,42589],"valid"],[[42590,42590],"mapped",[42591]],[[42591,42591],"valid"],[[42592,42592],"mapped",[42593]],[[42593,42593],"valid"],[[42594,42594],"mapped",[42595]],[[42595,42595],"valid"],[[42596,42596],"mapped",[42597]],[[42597,42597],"valid"],[[42598,42598],"mapped",[42599]],[[42599,42599],"valid"],[[42600,42600],"mapped",[42601]],[[42601,42601],"valid"],[[42602,42602],"mapped",[42603]],[[42603,42603],"valid"],[[42604,42604],"mapped",[42605]],[[42605,42607],"valid"],[[42608,42611],"valid",[],"NV8"],[[42612,42619],"valid"],[[42620,42621],"valid"],[[42622,42622],"valid",[],"NV8"],[[42623,42623],"valid"],[[42624,42624],"mapped",[42625]],[[42625,42625],"valid"],[[42626,42626],"mapped",[42627]],[[42627,42627],"valid"],[[42628,42628],"mapped",[42629]],[[42629,42629],"valid"],[[42630,42630],"mapped",[42631]],[[42631,42631],"valid"],[[42632,42632],"mapped",[42633]],[[42633,42633],"valid"],[[42634,42634],"mapped",[42635]],[[42635,42635],"valid"],[[42636,42636],"mapped",[42637]],[[42637,42637],"valid"],[[42638,42638],"mapped",[42639]],[[42639,42639],"valid"],[[42640,42640],"mapped",[42641]],[[42641,42641],"valid"],[[42642,42642],"mapped",[42643]],[[42643,42643],"valid"],[[42644,42644],"mapped",[42645]],[[42645,42645],"valid"],[[42646,42646],"mapped",[42647]],[[42647,42647],"valid"],[[42648,42648],"mapped",[42649]],[[42649,42649],"valid"],[[42650,42650],"mapped",[42651]],[[42651,42651],"valid"],[[42652,42652],"mapped",[1098]],[[42653,42653],"mapped",[1100]],[[42654,42654],"valid"],[[42655,42655],"valid"],[[42656,42725],"valid"],[[42726,42735],"valid",[],"NV8"],[[42736,42737],"valid"],[[42738,42743],"valid",[],"NV8"],[[42744,42751],"disallowed"],[[42752,42774],"valid",[],"NV8"],[[42775,42778],"valid"],[[42779,42783],"valid"],[[42784,42785],"valid",[],"NV8"],[[42786,42786],"mapped",[42787]],[[42787,42787],"valid"],[[42788,42788],"mapped",[42789]],[[42789,42789],"valid"],[[42790,42790],"mapped",[42791]],[[42791,42791],"valid"],[[42792,42792],"mapped",[42793]],[[42793,42793],"valid"],[[42794,42794],"mapped",[42795]],[[42795,42795],"valid"],[[42796,42796],"mapped",[42797]],[[42797,42797],"valid"],[[42798,42798],"mapped",[42799]],[[42799,42801],"valid"],[[42802,42802],"mapped",[42803]],[[42803,42803],"valid"],[[42804,42804],"mapped",[42805]],[[42805,42805],"valid"],[[42806,42806],"mapped",[42807]],[[42807,42807],"valid"],[[42808,42808],"mapped",[42809]],[[42809,42809],"valid"],[[42810,42810],"mapped",[42811]],[[42811,42811],"valid"],[[42812,42812],"mapped",[42813]],[[42813,42813],"valid"],[[42814,42814],"mapped",[42815]],[[42815,42815],"valid"],[[42816,42816],"mapped",[42817]],[[42817,42817],"valid"],[[42818,42818],"mapped",[42819]],[[42819,42819],"valid"],[[42820,42820],"mapped",[42821]],[[42821,42821],"valid"],[[42822,42822],"mapped",[42823]],[[42823,42823],"valid"],[[42824,42824],"mapped",[42825]],[[42825,42825],"valid"],[[42826,42826],"mapped",[42827]],[[42827,42827],"valid"],[[42828,42828],"mapped",[42829]],[[42829,42829],"valid"],[[42830,42830],"mapped",[42831]],[[42831,42831],"valid"],[[42832,42832],"mapped",[42833]],[[42833,42833],"valid"],[[42834,42834],"mapped",[42835]],[[42835,42835],"valid"],[[42836,42836],"mapped",[42837]],[[42837,42837],"valid"],[[42838,42838],"mapped",[42839]],[[42839,42839],"valid"],[[42840,42840],"mapped",[42841]],[[42841,42841],"valid"],[[42842,42842],"mapped",[42843]],[[42843,42843],"valid"],[[42844,42844],"mapped",[42845]],[[42845,42845],"valid"],[[42846,42846],"mapped",[42847]],[[42847,42847],"valid"],[[42848,42848],"mapped",[42849]],[[42849,42849],"valid"],[[42850,42850],"mapped",[42851]],[[42851,42851],"valid"],[[42852,42852],"mapped",[42853]],[[42853,42853],"valid"],[[42854,42854],"mapped",[42855]],[[42855,42855],"valid"],[[42856,42856],"mapped",[42857]],[[42857,42857],"valid"],[[42858,42858],"mapped",[42859]],[[42859,42859],"valid"],[[42860,42860],"mapped",[42861]],[[42861,42861],"valid"],[[42862,42862],"mapped",[42863]],[[42863,42863],"valid"],[[42864,42864],"mapped",[42863]],[[42865,42872],"valid"],[[42873,42873],"mapped",[42874]],[[42874,42874],"valid"],[[42875,42875],"mapped",[42876]],[[42876,42876],"valid"],[[42877,42877],"mapped",[7545]],[[42878,42878],"mapped",[42879]],[[42879,42879],"valid"],[[42880,42880],"mapped",[42881]],[[42881,42881],"valid"],[[42882,42882],"mapped",[42883]],[[42883,42883],"valid"],[[42884,42884],"mapped",[42885]],[[42885,42885],"valid"],[[42886,42886],"mapped",[42887]],[[42887,42888],"valid"],[[42889,42890],"valid",[],"NV8"],[[42891,42891],"mapped",[42892]],[[42892,42892],"valid"],[[42893,42893],"mapped",[613]],[[42894,42894],"valid"],[[42895,42895],"valid"],[[42896,42896],"mapped",[42897]],[[42897,42897],"valid"],[[42898,42898],"mapped",[42899]],[[42899,42899],"valid"],[[42900,42901],"valid"],[[42902,42902],"mapped",[42903]],[[42903,42903],"valid"],[[42904,42904],"mapped",[42905]],[[42905,42905],"valid"],[[42906,42906],"mapped",[42907]],[[42907,42907],"valid"],[[42908,42908],"mapped",[42909]],[[42909,42909],"valid"],[[42910,42910],"mapped",[42911]],[[42911,42911],"valid"],[[42912,42912],"mapped",[42913]],[[42913,42913],"valid"],[[42914,42914],"mapped",[42915]],[[42915,42915],"valid"],[[42916,42916],"mapped",[42917]],[[42917,42917],"valid"],[[42918,42918],"mapped",[42919]],[[42919,42919],"valid"],[[42920,42920],"mapped",[42921]],[[42921,42921],"valid"],[[42922,42922],"mapped",[614]],[[42923,42923],"mapped",[604]],[[42924,42924],"mapped",[609]],[[42925,42925],"mapped",[620]],[[42926,42927],"disallowed"],[[42928,42928],"mapped",[670]],[[42929,42929],"mapped",[647]],[[42930,42930],"mapped",[669]],[[42931,42931],"mapped",[43859]],[[42932,42932],"mapped",[42933]],[[42933,42933],"valid"],[[42934,42934],"mapped",[42935]],[[42935,42935],"valid"],[[42936,42998],"disallowed"],[[42999,42999],"valid"],[[43000,43000],"mapped",[295]],[[43001,43001],"mapped",[339]],[[43002,43002],"valid"],[[43003,43007],"valid"],[[43008,43047],"valid"],[[43048,43051],"valid",[],"NV8"],[[43052,43055],"disallowed"],[[43056,43065],"valid",[],"NV8"],[[43066,43071],"disallowed"],[[43072,43123],"valid"],[[43124,43127],"valid",[],"NV8"],[[43128,43135],"disallowed"],[[43136,43204],"valid"],[[43205,43213],"disallowed"],[[43214,43215],"valid",[],"NV8"],[[43216,43225],"valid"],[[43226,43231],"disallowed"],[[43232,43255],"valid"],[[43256,43258],"valid",[],"NV8"],[[43259,43259],"valid"],[[43260,43260],"valid",[],"NV8"],[[43261,43261],"valid"],[[43262,43263],"disallowed"],[[43264,43309],"valid"],[[43310,43311],"valid",[],"NV8"],[[43312,43347],"valid"],[[43348,43358],"disallowed"],[[43359,43359],"valid",[],"NV8"],[[43360,43388],"valid",[],"NV8"],[[43389,43391],"disallowed"],[[43392,43456],"valid"],[[43457,43469],"valid",[],"NV8"],[[43470,43470],"disallowed"],[[43471,43481],"valid"],[[43482,43485],"disallowed"],[[43486,43487],"valid",[],"NV8"],[[43488,43518],"valid"],[[43519,43519],"disallowed"],[[43520,43574],"valid"],[[43575,43583],"disallowed"],[[43584,43597],"valid"],[[43598,43599],"disallowed"],[[43600,43609],"valid"],[[43610,43611],"disallowed"],[[43612,43615],"valid",[],"NV8"],[[43616,43638],"valid"],[[43639,43641],"valid",[],"NV8"],[[43642,43643],"valid"],[[43644,43647],"valid"],[[43648,43714],"valid"],[[43715,43738],"disallowed"],[[43739,43741],"valid"],[[43742,43743],"valid",[],"NV8"],[[43744,43759],"valid"],[[43760,43761],"valid",[],"NV8"],[[43762,43766],"valid"],[[43767,43776],"disallowed"],[[43777,43782],"valid"],[[43783,43784],"disallowed"],[[43785,43790],"valid"],[[43791,43792],"disallowed"],[[43793,43798],"valid"],[[43799,43807],"disallowed"],[[43808,43814],"valid"],[[43815,43815],"disallowed"],[[43816,43822],"valid"],[[43823,43823],"disallowed"],[[43824,43866],"valid"],[[43867,43867],"valid",[],"NV8"],[[43868,43868],"mapped",[42791]],[[43869,43869],"mapped",[43831]],[[43870,43870],"mapped",[619]],[[43871,43871],"mapped",[43858]],[[43872,43875],"valid"],[[43876,43877],"valid"],[[43878,43887],"disallowed"],[[43888,43888],"mapped",[5024]],[[43889,43889],"mapped",[5025]],[[43890,43890],"mapped",[5026]],[[43891,43891],"mapped",[5027]],[[43892,43892],"mapped",[5028]],[[43893,43893],"mapped",[5029]],[[43894,43894],"mapped",[5030]],[[43895,43895],"mapped",[5031]],[[43896,43896],"mapped",[5032]],[[43897,43897],"mapped",[5033]],[[43898,43898],"mapped",[5034]],[[43899,43899],"mapped",[5035]],[[43900,43900],"mapped",[5036]],[[43901,43901],"mapped",[5037]],[[43902,43902],"mapped",[5038]],[[43903,43903],"mapped",[5039]],[[43904,43904],"mapped",[5040]],[[43905,43905],"mapped",[5041]],[[43906,43906],"mapped",[5042]],[[43907,43907],"mapped",[5043]],[[43908,43908],"mapped",[5044]],[[43909,43909],"mapped",[5045]],[[43910,43910],"mapped",[5046]],[[43911,43911],"mapped",[5047]],[[43912,43912],"mapped",[5048]],[[43913,43913],"mapped",[5049]],[[43914,43914],"mapped",[5050]],[[43915,43915],"mapped",[5051]],[[43916,43916],"mapped",[5052]],[[43917,43917],"mapped",[5053]],[[43918,43918],"mapped",[5054]],[[43919,43919],"mapped",[5055]],[[43920,43920],"mapped",[5056]],[[43921,43921],"mapped",[5057]],[[43922,43922],"mapped",[5058]],[[43923,43923],"mapped",[5059]],[[43924,43924],"mapped",[5060]],[[43925,43925],"mapped",[5061]],[[43926,43926],"mapped",[5062]],[[43927,43927],"mapped",[5063]],[[43928,43928],"mapped",[5064]],[[43929,43929],"mapped",[5065]],[[43930,43930],"mapped",[5066]],[[43931,43931],"mapped",[5067]],[[43932,43932],"mapped",[5068]],[[43933,43933],"mapped",[5069]],[[43934,43934],"mapped",[5070]],[[43935,43935],"mapped",[5071]],[[43936,43936],"mapped",[5072]],[[43937,43937],"mapped",[5073]],[[43938,43938],"mapped",[5074]],[[43939,43939],"mapped",[5075]],[[43940,43940],"mapped",[5076]],[[43941,43941],"mapped",[5077]],[[43942,43942],"mapped",[5078]],[[43943,43943],"mapped",[5079]],[[43944,43944],"mapped",[5080]],[[43945,43945],"mapped",[5081]],[[43946,43946],"mapped",[5082]],[[43947,43947],"mapped",[5083]],[[43948,43948],"mapped",[5084]],[[43949,43949],"mapped",[5085]],[[43950,43950],"mapped",[5086]],[[43951,43951],"mapped",[5087]],[[43952,43952],"mapped",[5088]],[[43953,43953],"mapped",[5089]],[[43954,43954],"mapped",[5090]],[[43955,43955],"mapped",[5091]],[[43956,43956],"mapped",[5092]],[[43957,43957],"mapped",[5093]],[[43958,43958],"mapped",[5094]],[[43959,43959],"mapped",[5095]],[[43960,43960],"mapped",[5096]],[[43961,43961],"mapped",[5097]],[[43962,43962],"mapped",[5098]],[[43963,43963],"mapped",[5099]],[[43964,43964],"mapped",[5100]],[[43965,43965],"mapped",[5101]],[[43966,43966],"mapped",[5102]],[[43967,43967],"mapped",[5103]],[[43968,44010],"valid"],[[44011,44011],"valid",[],"NV8"],[[44012,44013],"valid"],[[44014,44015],"disallowed"],[[44016,44025],"valid"],[[44026,44031],"disallowed"],[[44032,55203],"valid"],[[55204,55215],"disallowed"],[[55216,55238],"valid",[],"NV8"],[[55239,55242],"disallowed"],[[55243,55291],"valid",[],"NV8"],[[55292,55295],"disallowed"],[[55296,57343],"disallowed"],[[57344,63743],"disallowed"],[[63744,63744],"mapped",[35912]],[[63745,63745],"mapped",[26356]],[[63746,63746],"mapped",[36554]],[[63747,63747],"mapped",[36040]],[[63748,63748],"mapped",[28369]],[[63749,63749],"mapped",[20018]],[[63750,63750],"mapped",[21477]],[[63751,63752],"mapped",[40860]],[[63753,63753],"mapped",[22865]],[[63754,63754],"mapped",[37329]],[[63755,63755],"mapped",[21895]],[[63756,63756],"mapped",[22856]],[[63757,63757],"mapped",[25078]],[[63758,63758],"mapped",[30313]],[[63759,63759],"mapped",[32645]],[[63760,63760],"mapped",[34367]],[[63761,63761],"mapped",[34746]],[[63762,63762],"mapped",[35064]],[[63763,63763],"mapped",[37007]],[[63764,63764],"mapped",[27138]],[[63765,63765],"mapped",[27931]],[[63766,63766],"mapped",[28889]],[[63767,63767],"mapped",[29662]],[[63768,63768],"mapped",[33853]],[[63769,63769],"mapped",[37226]],[[63770,63770],"mapped",[39409]],[[63771,63771],"mapped",[20098]],[[63772,63772],"mapped",[21365]],[[63773,63773],"mapped",[27396]],[[63774,63774],"mapped",[29211]],[[63775,63775],"mapped",[34349]],[[63776,63776],"mapped",[40478]],[[63777,63777],"mapped",[23888]],[[63778,63778],"mapped",[28651]],[[63779,63779],"mapped",[34253]],[[63780,63780],"mapped",[35172]],[[63781,63781],"mapped",[25289]],[[63782,63782],"mapped",[33240]],[[63783,63783],"mapped",[34847]],[[63784,63784],"mapped",[24266]],[[63785,63785],"mapped",[26391]],[[63786,63786],"mapped",[28010]],[[63787,63787],"mapped",[29436]],[[63788,63788],"mapped",[37070]],[[63789,63789],"mapped",[20358]],[[63790,63790],"mapped",[20919]],[[63791,63791],"mapped",[21214]],[[63792,63792],"mapped",[25796]],[[63793,63793],"mapped",[27347]],[[63794,63794],"mapped",[29200]],[[63795,63795],"mapped",[30439]],[[63796,63796],"mapped",[32769]],[[63797,63797],"mapped",[34310]],[[63798,63798],"mapped",[34396]],[[63799,63799],"mapped",[36335]],[[63800,63800],"mapped",[38706]],[[63801,63801],"mapped",[39791]],[[63802,63802],"mapped",[40442]],[[63803,63803],"mapped",[30860]],[[63804,63804],"mapped",[31103]],[[63805,63805],"mapped",[32160]],[[63806,63806],"mapped",[33737]],[[63807,63807],"mapped",[37636]],[[63808,63808],"mapped",[40575]],[[63809,63809],"mapped",[35542]],[[63810,63810],"mapped",[22751]],[[63811,63811],"mapped",[24324]],[[63812,63812],"mapped",[31840]],[[63813,63813],"mapped",[32894]],[[63814,63814],"mapped",[29282]],[[63815,63815],"mapped",[30922]],[[63816,63816],"mapped",[36034]],[[63817,63817],"mapped",[38647]],[[63818,63818],"mapped",[22744]],[[63819,63819],"mapped",[23650]],[[63820,63820],"mapped",[27155]],[[63821,63821],"mapped",[28122]],[[63822,63822],"mapped",[28431]],[[63823,63823],"mapped",[32047]],[[63824,63824],"mapped",[32311]],[[63825,63825],"mapped",[38475]],[[63826,63826],"mapped",[21202]],[[63827,63827],"mapped",[32907]],[[63828,63828],"mapped",[20956]],[[63829,63829],"mapped",[20940]],[[63830,63830],"mapped",[31260]],[[63831,63831],"mapped",[32190]],[[63832,63832],"mapped",[33777]],[[63833,63833],"mapped",[38517]],[[63834,63834],"mapped",[35712]],[[63835,63835],"mapped",[25295]],[[63836,63836],"mapped",[27138]],[[63837,63837],"mapped",[35582]],[[63838,63838],"mapped",[20025]],[[63839,63839],"mapped",[23527]],[[63840,63840],"mapped",[24594]],[[63841,63841],"mapped",[29575]],[[63842,63842],"mapped",[30064]],[[63843,63843],"mapped",[21271]],[[63844,63844],"mapped",[30971]],[[63845,63845],"mapped",[20415]],[[63846,63846],"mapped",[24489]],[[63847,63847],"mapped",[19981]],[[63848,63848],"mapped",[27852]],[[63849,63849],"mapped",[25976]],[[63850,63850],"mapped",[32034]],[[63851,63851],"mapped",[21443]],[[63852,63852],"mapped",[22622]],[[63853,63853],"mapped",[30465]],[[63854,63854],"mapped",[33865]],[[63855,63855],"mapped",[35498]],[[63856,63856],"mapped",[27578]],[[63857,63857],"mapped",[36784]],[[63858,63858],"mapped",[27784]],[[63859,63859],"mapped",[25342]],[[63860,63860],"mapped",[33509]],[[63861,63861],"mapped",[25504]],[[63862,63862],"mapped",[30053]],[[63863,63863],"mapped",[20142]],[[63864,63864],"mapped",[20841]],[[63865,63865],"mapped",[20937]],[[63866,63866],"mapped",[26753]],[[63867,63867],"mapped",[31975]],[[63868,63868],"mapped",[33391]],[[63869,63869],"mapped",[35538]],[[63870,63870],"mapped",[37327]],[[63871,63871],"mapped",[21237]],[[63872,63872],"mapped",[21570]],[[63873,63873],"mapped",[22899]],[[63874,63874],"mapped",[24300]],[[63875,63875],"mapped",[26053]],[[63876,63876],"mapped",[28670]],[[63877,63877],"mapped",[31018]],[[63878,63878],"mapped",[38317]],[[63879,63879],"mapped",[39530]],[[63880,63880],"mapped",[40599]],[[63881,63881],"mapped",[40654]],[[63882,63882],"mapped",[21147]],[[63883,63883],"mapped",[26310]],[[63884,63884],"mapped",[27511]],[[63885,63885],"mapped",[36706]],[[63886,63886],"mapped",[24180]],[[63887,63887],"mapped",[24976]],[[63888,63888],"mapped",[25088]],[[63889,63889],"mapped",[25754]],[[63890,63890],"mapped",[28451]],[[63891,63891],"mapped",[29001]],[[63892,63892],"mapped",[29833]],[[63893,63893],"mapped",[31178]],[[63894,63894],"mapped",[32244]],[[63895,63895],"mapped",[32879]],[[63896,63896],"mapped",[36646]],[[63897,63897],"mapped",[34030]],[[63898,63898],"mapped",[36899]],[[63899,63899],"mapped",[37706]],[[63900,63900],"mapped",[21015]],[[63901,63901],"mapped",[21155]],[[63902,63902],"mapped",[21693]],[[63903,63903],"mapped",[28872]],[[63904,63904],"mapped",[35010]],[[63905,63905],"mapped",[35498]],[[63906,63906],"mapped",[24265]],[[63907,63907],"mapped",[24565]],[[63908,63908],"mapped",[25467]],[[63909,63909],"mapped",[27566]],[[63910,63910],"mapped",[31806]],[[63911,63911],"mapped",[29557]],[[63912,63912],"mapped",[20196]],[[63913,63913],"mapped",[22265]],[[63914,63914],"mapped",[23527]],[[63915,63915],"mapped",[23994]],[[63916,63916],"mapped",[24604]],[[63917,63917],"mapped",[29618]],[[63918,63918],"mapped",[29801]],[[63919,63919],"mapped",[32666]],[[63920,63920],"mapped",[32838]],[[63921,63921],"mapped",[37428]],[[63922,63922],"mapped",[38646]],[[63923,63923],"mapped",[38728]],[[63924,63924],"mapped",[38936]],[[63925,63925],"mapped",[20363]],[[63926,63926],"mapped",[31150]],[[63927,63927],"mapped",[37300]],[[63928,63928],"mapped",[38584]],[[63929,63929],"mapped",[24801]],[[63930,63930],"mapped",[20102]],[[63931,63931],"mapped",[20698]],[[63932,63932],"mapped",[23534]],[[63933,63933],"mapped",[23615]],[[63934,63934],"mapped",[26009]],[[63935,63935],"mapped",[27138]],[[63936,63936],"mapped",[29134]],[[63937,63937],"mapped",[30274]],[[63938,63938],"mapped",[34044]],[[63939,63939],"mapped",[36988]],[[63940,63940],"mapped",[40845]],[[63941,63941],"mapped",[26248]],[[63942,63942],"mapped",[38446]],[[63943,63943],"mapped",[21129]],[[63944,63944],"mapped",[26491]],[[63945,63945],"mapped",[26611]],[[63946,63946],"mapped",[27969]],[[63947,63947],"mapped",[28316]],[[63948,63948],"mapped",[29705]],[[63949,63949],"mapped",[30041]],[[63950,63950],"mapped",[30827]],[[63951,63951],"mapped",[32016]],[[63952,63952],"mapped",[39006]],[[63953,63953],"mapped",[20845]],[[63954,63954],"mapped",[25134]],[[63955,63955],"mapped",[38520]],[[63956,63956],"mapped",[20523]],[[63957,63957],"mapped",[23833]],[[63958,63958],"mapped",[28138]],[[63959,63959],"mapped",[36650]],[[63960,63960],"mapped",[24459]],[[63961,63961],"mapped",[24900]],[[63962,63962],"mapped",[26647]],[[63963,63963],"mapped",[29575]],[[63964,63964],"mapped",[38534]],[[63965,63965],"mapped",[21033]],[[63966,63966],"mapped",[21519]],[[63967,63967],"mapped",[23653]],[[63968,63968],"mapped",[26131]],[[63969,63969],"mapped",[26446]],[[63970,63970],"mapped",[26792]],[[63971,63971],"mapped",[27877]],[[63972,63972],"mapped",[29702]],[[63973,63973],"mapped",[30178]],[[63974,63974],"mapped",[32633]],[[63975,63975],"mapped",[35023]],[[63976,63976],"mapped",[35041]],[[63977,63977],"mapped",[37324]],[[63978,63978],"mapped",[38626]],[[63979,63979],"mapped",[21311]],[[63980,63980],"mapped",[28346]],[[63981,63981],"mapped",[21533]],[[63982,63982],"mapped",[29136]],[[63983,63983],"mapped",[29848]],[[63984,63984],"mapped",[34298]],[[63985,63985],"mapped",[38563]],[[63986,63986],"mapped",[40023]],[[63987,63987],"mapped",[40607]],[[63988,63988],"mapped",[26519]],[[63989,63989],"mapped",[28107]],[[63990,63990],"mapped",[33256]],[[63991,63991],"mapped",[31435]],[[63992,63992],"mapped",[31520]],[[63993,63993],"mapped",[31890]],[[63994,63994],"mapped",[29376]],[[63995,63995],"mapped",[28825]],[[63996,63996],"mapped",[35672]],[[63997,63997],"mapped",[20160]],[[63998,63998],"mapped",[33590]],[[63999,63999],"mapped",[21050]],[[64000,64000],"mapped",[20999]],[[64001,64001],"mapped",[24230]],[[64002,64002],"mapped",[25299]],[[64003,64003],"mapped",[31958]],[[64004,64004],"mapped",[23429]],[[64005,64005],"mapped",[27934]],[[64006,64006],"mapped",[26292]],[[64007,64007],"mapped",[36667]],[[64008,64008],"mapped",[34892]],[[64009,64009],"mapped",[38477]],[[64010,64010],"mapped",[35211]],[[64011,64011],"mapped",[24275]],[[64012,64012],"mapped",[20800]],[[64013,64013],"mapped",[21952]],[[64014,64015],"valid"],[[64016,64016],"mapped",[22618]],[[64017,64017],"valid"],[[64018,64018],"mapped",[26228]],[[64019,64020],"valid"],[[64021,64021],"mapped",[20958]],[[64022,64022],"mapped",[29482]],[[64023,64023],"mapped",[30410]],[[64024,64024],"mapped",[31036]],[[64025,64025],"mapped",[31070]],[[64026,64026],"mapped",[31077]],[[64027,64027],"mapped",[31119]],[[64028,64028],"mapped",[38742]],[[64029,64029],"mapped",[31934]],[[64030,64030],"mapped",[32701]],[[64031,64031],"valid"],[[64032,64032],"mapped",[34322]],[[64033,64033],"valid"],[[64034,64034],"mapped",[35576]],[[64035,64036],"valid"],[[64037,64037],"mapped",[36920]],[[64038,64038],"mapped",[37117]],[[64039,64041],"valid"],[[64042,64042],"mapped",[39151]],[[64043,64043],"mapped",[39164]],[[64044,64044],"mapped",[39208]],[[64045,64045],"mapped",[40372]],[[64046,64046],"mapped",[37086]],[[64047,64047],"mapped",[38583]],[[64048,64048],"mapped",[20398]],[[64049,64049],"mapped",[20711]],[[64050,64050],"mapped",[20813]],[[64051,64051],"mapped",[21193]],[[64052,64052],"mapped",[21220]],[[64053,64053],"mapped",[21329]],[[64054,64054],"mapped",[21917]],[[64055,64055],"mapped",[22022]],[[64056,64056],"mapped",[22120]],[[64057,64057],"mapped",[22592]],[[64058,64058],"mapped",[22696]],[[64059,64059],"mapped",[23652]],[[64060,64060],"mapped",[23662]],[[64061,64061],"mapped",[24724]],[[64062,64062],"mapped",[24936]],[[64063,64063],"mapped",[24974]],[[64064,64064],"mapped",[25074]],[[64065,64065],"mapped",[25935]],[[64066,64066],"mapped",[26082]],[[64067,64067],"mapped",[26257]],[[64068,64068],"mapped",[26757]],[[64069,64069],"mapped",[28023]],[[64070,64070],"mapped",[28186]],[[64071,64071],"mapped",[28450]],[[64072,64072],"mapped",[29038]],[[64073,64073],"mapped",[29227]],[[64074,64074],"mapped",[29730]],[[64075,64075],"mapped",[30865]],[[64076,64076],"mapped",[31038]],[[64077,64077],"mapped",[31049]],[[64078,64078],"mapped",[31048]],[[64079,64079],"mapped",[31056]],[[64080,64080],"mapped",[31062]],[[64081,64081],"mapped",[31069]],[[64082,64082],"mapped",[31117]],[[64083,64083],"mapped",[31118]],[[64084,64084],"mapped",[31296]],[[64085,64085],"mapped",[31361]],[[64086,64086],"mapped",[31680]],[[64087,64087],"mapped",[32244]],[[64088,64088],"mapped",[32265]],[[64089,64089],"mapped",[32321]],[[64090,64090],"mapped",[32626]],[[64091,64091],"mapped",[32773]],[[64092,64092],"mapped",[33261]],[[64093,64094],"mapped",[33401]],[[64095,64095],"mapped",[33879]],[[64096,64096],"mapped",[35088]],[[64097,64097],"mapped",[35222]],[[64098,64098],"mapped",[35585]],[[64099,64099],"mapped",[35641]],[[64100,64100],"mapped",[36051]],[[64101,64101],"mapped",[36104]],[[64102,64102],"mapped",[36790]],[[64103,64103],"mapped",[36920]],[[64104,64104],"mapped",[38627]],[[64105,64105],"mapped",[38911]],[[64106,64106],"mapped",[38971]],[[64107,64107],"mapped",[24693]],[[64108,64108],"mapped",[148206]],[[64109,64109],"mapped",[33304]],[[64110,64111],"disallowed"],[[64112,64112],"mapped",[20006]],[[64113,64113],"mapped",[20917]],[[64114,64114],"mapped",[20840]],[[64115,64115],"mapped",[20352]],[[64116,64116],"mapped",[20805]],[[64117,64117],"mapped",[20864]],[[64118,64118],"mapped",[21191]],[[64119,64119],"mapped",[21242]],[[64120,64120],"mapped",[21917]],[[64121,64121],"mapped",[21845]],[[64122,64122],"mapped",[21913]],[[64123,64123],"mapped",[21986]],[[64124,64124],"mapped",[22618]],[[64125,64125],"mapped",[22707]],[[64126,64126],"mapped",[22852]],[[64127,64127],"mapped",[22868]],[[64128,64128],"mapped",[23138]],[[64129,64129],"mapped",[23336]],[[64130,64130],"mapped",[24274]],[[64131,64131],"mapped",[24281]],[[64132,64132],"mapped",[24425]],[[64133,64133],"mapped",[24493]],[[64134,64134],"mapped",[24792]],[[64135,64135],"mapped",[24910]],[[64136,64136],"mapped",[24840]],[[64137,64137],"mapped",[24974]],[[64138,64138],"mapped",[24928]],[[64139,64139],"mapped",[25074]],[[64140,64140],"mapped",[25140]],[[64141,64141],"mapped",[25540]],[[64142,64142],"mapped",[25628]],[[64143,64143],"mapped",[25682]],[[64144,64144],"mapped",[25942]],[[64145,64145],"mapped",[26228]],[[64146,64146],"mapped",[26391]],[[64147,64147],"mapped",[26395]],[[64148,64148],"mapped",[26454]],[[64149,64149],"mapped",[27513]],[[64150,64150],"mapped",[27578]],[[64151,64151],"mapped",[27969]],[[64152,64152],"mapped",[28379]],[[64153,64153],"mapped",[28363]],[[64154,64154],"mapped",[28450]],[[64155,64155],"mapped",[28702]],[[64156,64156],"mapped",[29038]],[[64157,64157],"mapped",[30631]],[[64158,64158],"mapped",[29237]],[[64159,64159],"mapped",[29359]],[[64160,64160],"mapped",[29482]],[[64161,64161],"mapped",[29809]],[[64162,64162],"mapped",[29958]],[[64163,64163],"mapped",[30011]],[[64164,64164],"mapped",[30237]],[[64165,64165],"mapped",[30239]],[[64166,64166],"mapped",[30410]],[[64167,64167],"mapped",[30427]],[[64168,64168],"mapped",[30452]],[[64169,64169],"mapped",[30538]],[[64170,64170],"mapped",[30528]],[[64171,64171],"mapped",[30924]],[[64172,64172],"mapped",[31409]],[[64173,64173],"mapped",[31680]],[[64174,64174],"mapped",[31867]],[[64175,64175],"mapped",[32091]],[[64176,64176],"mapped",[32244]],[[64177,64177],"mapped",[32574]],[[64178,64178],"mapped",[32773]],[[64179,64179],"mapped",[33618]],[[64180,64180],"mapped",[33775]],[[64181,64181],"mapped",[34681]],[[64182,64182],"mapped",[35137]],[[64183,64183],"mapped",[35206]],[[64184,64184],"mapped",[35222]],[[64185,64185],"mapped",[35519]],[[64186,64186],"mapped",[35576]],[[64187,64187],"mapped",[35531]],[[64188,64188],"mapped",[35585]],[[64189,64189],"mapped",[35582]],[[64190,64190],"mapped",[35565]],[[64191,64191],"mapped",[35641]],[[64192,64192],"mapped",[35722]],[[64193,64193],"mapped",[36104]],[[64194,64194],"mapped",[36664]],[[64195,64195],"mapped",[36978]],[[64196,64196],"mapped",[37273]],[[64197,64197],"mapped",[37494]],[[64198,64198],"mapped",[38524]],[[64199,64199],"mapped",[38627]],[[64200,64200],"mapped",[38742]],[[64201,64201],"mapped",[38875]],[[64202,64202],"mapped",[38911]],[[64203,64203],"mapped",[38923]],[[64204,64204],"mapped",[38971]],[[64205,64205],"mapped",[39698]],[[64206,64206],"mapped",[40860]],[[64207,64207],"mapped",[141386]],[[64208,64208],"mapped",[141380]],[[64209,64209],"mapped",[144341]],[[64210,64210],"mapped",[15261]],[[64211,64211],"mapped",[16408]],[[64212,64212],"mapped",[16441]],[[64213,64213],"mapped",[152137]],[[64214,64214],"mapped",[154832]],[[64215,64215],"mapped",[163539]],[[64216,64216],"mapped",[40771]],[[64217,64217],"mapped",[40846]],[[64218,64255],"disallowed"],[[64256,64256],"mapped",[102,102]],[[64257,64257],"mapped",[102,105]],[[64258,64258],"mapped",[102,108]],[[64259,64259],"mapped",[102,102,105]],[[64260,64260],"mapped",[102,102,108]],[[64261,64262],"mapped",[115,116]],[[64263,64274],"disallowed"],[[64275,64275],"mapped",[1396,1398]],[[64276,64276],"mapped",[1396,1381]],[[64277,64277],"mapped",[1396,1387]],[[64278,64278],"mapped",[1406,1398]],[[64279,64279],"mapped",[1396,1389]],[[64280,64284],"disallowed"],[[64285,64285],"mapped",[1497,1460]],[[64286,64286],"valid"],[[64287,64287],"mapped",[1522,1463]],[[64288,64288],"mapped",[1506]],[[64289,64289],"mapped",[1488]],[[64290,64290],"mapped",[1491]],[[64291,64291],"mapped",[1492]],[[64292,64292],"mapped",[1499]],[[64293,64293],"mapped",[1500]],[[64294,64294],"mapped",[1501]],[[64295,64295],"mapped",[1512]],[[64296,64296],"mapped",[1514]],[[64297,64297],"disallowed_STD3_mapped",[43]],[[64298,64298],"mapped",[1513,1473]],[[64299,64299],"mapped",[1513,1474]],[[64300,64300],"mapped",[1513,1468,1473]],[[64301,64301],"mapped",[1513,1468,1474]],[[64302,64302],"mapped",[1488,1463]],[[64303,64303],"mapped",[1488,1464]],[[64304,64304],"mapped",[1488,1468]],[[64305,64305],"mapped",[1489,1468]],[[64306,64306],"mapped",[1490,1468]],[[64307,64307],"mapped",[1491,1468]],[[64308,64308],"mapped",[1492,1468]],[[64309,64309],"mapped",[1493,1468]],[[64310,64310],"mapped",[1494,1468]],[[64311,64311],"disallowed"],[[64312,64312],"mapped",[1496,1468]],[[64313,64313],"mapped",[1497,1468]],[[64314,64314],"mapped",[1498,1468]],[[64315,64315],"mapped",[1499,1468]],[[64316,64316],"mapped",[1500,1468]],[[64317,64317],"disallowed"],[[64318,64318],"mapped",[1502,1468]],[[64319,64319],"disallowed"],[[64320,64320],"mapped",[1504,1468]],[[64321,64321],"mapped",[1505,1468]],[[64322,64322],"disallowed"],[[64323,64323],"mapped",[1507,1468]],[[64324,64324],"mapped",[1508,1468]],[[64325,64325],"disallowed"],[[64326,64326],"mapped",[1510,1468]],[[64327,64327],"mapped",[1511,1468]],[[64328,64328],"mapped",[1512,1468]],[[64329,64329],"mapped",[1513,1468]],[[64330,64330],"mapped",[1514,1468]],[[64331,64331],"mapped",[1493,1465]],[[64332,64332],"mapped",[1489,1471]],[[64333,64333],"mapped",[1499,1471]],[[64334,64334],"mapped",[1508,1471]],[[64335,64335],"mapped",[1488,1500]],[[64336,64337],"mapped",[1649]],[[64338,64341],"mapped",[1659]],[[64342,64345],"mapped",[1662]],[[64346,64349],"mapped",[1664]],[[64350,64353],"mapped",[1658]],[[64354,64357],"mapped",[1663]],[[64358,64361],"mapped",[1657]],[[64362,64365],"mapped",[1700]],[[64366,64369],"mapped",[1702]],[[64370,64373],"mapped",[1668]],[[64374,64377],"mapped",[1667]],[[64378,64381],"mapped",[1670]],[[64382,64385],"mapped",[1671]],[[64386,64387],"mapped",[1677]],[[64388,64389],"mapped",[1676]],[[64390,64391],"mapped",[1678]],[[64392,64393],"mapped",[1672]],[[64394,64395],"mapped",[1688]],[[64396,64397],"mapped",[1681]],[[64398,64401],"mapped",[1705]],[[64402,64405],"mapped",[1711]],[[64406,64409],"mapped",[1715]],[[64410,64413],"mapped",[1713]],[[64414,64415],"mapped",[1722]],[[64416,64419],"mapped",[1723]],[[64420,64421],"mapped",[1728]],[[64422,64425],"mapped",[1729]],[[64426,64429],"mapped",[1726]],[[64430,64431],"mapped",[1746]],[[64432,64433],"mapped",[1747]],[[64434,64449],"valid",[],"NV8"],[[64450,64466],"disallowed"],[[64467,64470],"mapped",[1709]],[[64471,64472],"mapped",[1735]],[[64473,64474],"mapped",[1734]],[[64475,64476],"mapped",[1736]],[[64477,64477],"mapped",[1735,1652]],[[64478,64479],"mapped",[1739]],[[64480,64481],"mapped",[1733]],[[64482,64483],"mapped",[1737]],[[64484,64487],"mapped",[1744]],[[64488,64489],"mapped",[1609]],[[64490,64491],"mapped",[1574,1575]],[[64492,64493],"mapped",[1574,1749]],[[64494,64495],"mapped",[1574,1608]],[[64496,64497],"mapped",[1574,1735]],[[64498,64499],"mapped",[1574,1734]],[[64500,64501],"mapped",[1574,1736]],[[64502,64504],"mapped",[1574,1744]],[[64505,64507],"mapped",[1574,1609]],[[64508,64511],"mapped",[1740]],[[64512,64512],"mapped",[1574,1580]],[[64513,64513],"mapped",[1574,1581]],[[64514,64514],"mapped",[1574,1605]],[[64515,64515],"mapped",[1574,1609]],[[64516,64516],"mapped",[1574,1610]],[[64517,64517],"mapped",[1576,1580]],[[64518,64518],"mapped",[1576,1581]],[[64519,64519],"mapped",[1576,1582]],[[64520,64520],"mapped",[1576,1605]],[[64521,64521],"mapped",[1576,1609]],[[64522,64522],"mapped",[1576,1610]],[[64523,64523],"mapped",[1578,1580]],[[64524,64524],"mapped",[1578,1581]],[[64525,64525],"mapped",[1578,1582]],[[64526,64526],"mapped",[1578,1605]],[[64527,64527],"mapped",[1578,1609]],[[64528,64528],"mapped",[1578,1610]],[[64529,64529],"mapped",[1579,1580]],[[64530,64530],"mapped",[1579,1605]],[[64531,64531],"mapped",[1579,1609]],[[64532,64532],"mapped",[1579,1610]],[[64533,64533],"mapped",[1580,1581]],[[64534,64534],"mapped",[1580,1605]],[[64535,64535],"mapped",[1581,1580]],[[64536,64536],"mapped",[1581,1605]],[[64537,64537],"mapped",[1582,1580]],[[64538,64538],"mapped",[1582,1581]],[[64539,64539],"mapped",[1582,1605]],[[64540,64540],"mapped",[1587,1580]],[[64541,64541],"mapped",[1587,1581]],[[64542,64542],"mapped",[1587,1582]],[[64543,64543],"mapped",[1587,1605]],[[64544,64544],"mapped",[1589,1581]],[[64545,64545],"mapped",[1589,1605]],[[64546,64546],"mapped",[1590,1580]],[[64547,64547],"mapped",[1590,1581]],[[64548,64548],"mapped",[1590,1582]],[[64549,64549],"mapped",[1590,1605]],[[64550,64550],"mapped",[1591,1581]],[[64551,64551],"mapped",[1591,1605]],[[64552,64552],"mapped",[1592,1605]],[[64553,64553],"mapped",[1593,1580]],[[64554,64554],"mapped",[1593,1605]],[[64555,64555],"mapped",[1594,1580]],[[64556,64556],"mapped",[1594,1605]],[[64557,64557],"mapped",[1601,1580]],[[64558,64558],"mapped",[1601,1581]],[[64559,64559],"mapped",[1601,1582]],[[64560,64560],"mapped",[1601,1605]],[[64561,64561],"mapped",[1601,1609]],[[64562,64562],"mapped",[1601,1610]],[[64563,64563],"mapped",[1602,1581]],[[64564,64564],"mapped",[1602,1605]],[[64565,64565],"mapped",[1602,1609]],[[64566,64566],"mapped",[1602,1610]],[[64567,64567],"mapped",[1603,1575]],[[64568,64568],"mapped",[1603,1580]],[[64569,64569],"mapped",[1603,1581]],[[64570,64570],"mapped",[1603,1582]],[[64571,64571],"mapped",[1603,1604]],[[64572,64572],"mapped",[1603,1605]],[[64573,64573],"mapped",[1603,1609]],[[64574,64574],"mapped",[1603,1610]],[[64575,64575],"mapped",[1604,1580]],[[64576,64576],"mapped",[1604,1581]],[[64577,64577],"mapped",[1604,1582]],[[64578,64578],"mapped",[1604,1605]],[[64579,64579],"mapped",[1604,1609]],[[64580,64580],"mapped",[1604,1610]],[[64581,64581],"mapped",[1605,1580]],[[64582,64582],"mapped",[1605,1581]],[[64583,64583],"mapped",[1605,1582]],[[64584,64584],"mapped",[1605,1605]],[[64585,64585],"mapped",[1605,1609]],[[64586,64586],"mapped",[1605,1610]],[[64587,64587],"mapped",[1606,1580]],[[64588,64588],"mapped",[1606,1581]],[[64589,64589],"mapped",[1606,1582]],[[64590,64590],"mapped",[1606,1605]],[[64591,64591],"mapped",[1606,1609]],[[64592,64592],"mapped",[1606,1610]],[[64593,64593],"mapped",[1607,1580]],[[64594,64594],"mapped",[1607,1605]],[[64595,64595],"mapped",[1607,1609]],[[64596,64596],"mapped",[1607,1610]],[[64597,64597],"mapped",[1610,1580]],[[64598,64598],"mapped",[1610,1581]],[[64599,64599],"mapped",[1610,1582]],[[64600,64600],"mapped",[1610,1605]],[[64601,64601],"mapped",[1610,1609]],[[64602,64602],"mapped",[1610,1610]],[[64603,64603],"mapped",[1584,1648]],[[64604,64604],"mapped",[1585,1648]],[[64605,64605],"mapped",[1609,1648]],[[64606,64606],"disallowed_STD3_mapped",[32,1612,1617]],[[64607,64607],"disallowed_STD3_mapped",[32,1613,1617]],[[64608,64608],"disallowed_STD3_mapped",[32,1614,1617]],[[64609,64609],"disallowed_STD3_mapped",[32,1615,1617]],[[64610,64610],"disallowed_STD3_mapped",[32,1616,1617]],[[64611,64611],"disallowed_STD3_mapped",[32,1617,1648]],[[64612,64612],"mapped",[1574,1585]],[[64613,64613],"mapped",[1574,1586]],[[64614,64614],"mapped",[1574,1605]],[[64615,64615],"mapped",[1574,1606]],[[64616,64616],"mapped",[1574,1609]],[[64617,64617],"mapped",[1574,1610]],[[64618,64618],"mapped",[1576,1585]],[[64619,64619],"mapped",[1576,1586]],[[64620,64620],"mapped",[1576,1605]],[[64621,64621],"mapped",[1576,1606]],[[64622,64622],"mapped",[1576,1609]],[[64623,64623],"mapped",[1576,1610]],[[64624,64624],"mapped",[1578,1585]],[[64625,64625],"mapped",[1578,1586]],[[64626,64626],"mapped",[1578,1605]],[[64627,64627],"mapped",[1578,1606]],[[64628,64628],"mapped",[1578,1609]],[[64629,64629],"mapped",[1578,1610]],[[64630,64630],"mapped",[1579,1585]],[[64631,64631],"mapped",[1579,1586]],[[64632,64632],"mapped",[1579,1605]],[[64633,64633],"mapped",[1579,1606]],[[64634,64634],"mapped",[1579,1609]],[[64635,64635],"mapped",[1579,1610]],[[64636,64636],"mapped",[1601,1609]],[[64637,64637],"mapped",[1601,1610]],[[64638,64638],"mapped",[1602,1609]],[[64639,64639],"mapped",[1602,1610]],[[64640,64640],"mapped",[1603,1575]],[[64641,64641],"mapped",[1603,1604]],[[64642,64642],"mapped",[1603,1605]],[[64643,64643],"mapped",[1603,1609]],[[64644,64644],"mapped",[1603,1610]],[[64645,64645],"mapped",[1604,1605]],[[64646,64646],"mapped",[1604,1609]],[[64647,64647],"mapped",[1604,1610]],[[64648,64648],"mapped",[1605,1575]],[[64649,64649],"mapped",[1605,1605]],[[64650,64650],"mapped",[1606,1585]],[[64651,64651],"mapped",[1606,1586]],[[64652,64652],"mapped",[1606,1605]],[[64653,64653],"mapped",[1606,1606]],[[64654,64654],"mapped",[1606,1609]],[[64655,64655],"mapped",[1606,1610]],[[64656,64656],"mapped",[1609,1648]],[[64657,64657],"mapped",[1610,1585]],[[64658,64658],"mapped",[1610,1586]],[[64659,64659],"mapped",[1610,1605]],[[64660,64660],"mapped",[1610,1606]],[[64661,64661],"mapped",[1610,1609]],[[64662,64662],"mapped",[1610,1610]],[[64663,64663],"mapped",[1574,1580]],[[64664,64664],"mapped",[1574,1581]],[[64665,64665],"mapped",[1574,1582]],[[64666,64666],"mapped",[1574,1605]],[[64667,64667],"mapped",[1574,1607]],[[64668,64668],"mapped",[1576,1580]],[[64669,64669],"mapped",[1576,1581]],[[64670,64670],"mapped",[1576,1582]],[[64671,64671],"mapped",[1576,1605]],[[64672,64672],"mapped",[1576,1607]],[[64673,64673],"mapped",[1578,1580]],[[64674,64674],"mapped",[1578,1581]],[[64675,64675],"mapped",[1578,1582]],[[64676,64676],"mapped",[1578,1605]],[[64677,64677],"mapped",[1578,1607]],[[64678,64678],"mapped",[1579,1605]],[[64679,64679],"mapped",[1580,1581]],[[64680,64680],"mapped",[1580,1605]],[[64681,64681],"mapped",[1581,1580]],[[64682,64682],"mapped",[1581,1605]],[[64683,64683],"mapped",[1582,1580]],[[64684,64684],"mapped",[1582,1605]],[[64685,64685],"mapped",[1587,1580]],[[64686,64686],"mapped",[1587,1581]],[[64687,64687],"mapped",[1587,1582]],[[64688,64688],"mapped",[1587,1605]],[[64689,64689],"mapped",[1589,1581]],[[64690,64690],"mapped",[1589,1582]],[[64691,64691],"mapped",[1589,1605]],[[64692,64692],"mapped",[1590,1580]],[[64693,64693],"mapped",[1590,1581]],[[64694,64694],"mapped",[1590,1582]],[[64695,64695],"mapped",[1590,1605]],[[64696,64696],"mapped",[1591,1581]],[[64697,64697],"mapped",[1592,1605]],[[64698,64698],"mapped",[1593,1580]],[[64699,64699],"mapped",[1593,1605]],[[64700,64700],"mapped",[1594,1580]],[[64701,64701],"mapped",[1594,1605]],[[64702,64702],"mapped",[1601,1580]],[[64703,64703],"mapped",[1601,1581]],[[64704,64704],"mapped",[1601,1582]],[[64705,64705],"mapped",[1601,1605]],[[64706,64706],"mapped",[1602,1581]],[[64707,64707],"mapped",[1602,1605]],[[64708,64708],"mapped",[1603,1580]],[[64709,64709],"mapped",[1603,1581]],[[64710,64710],"mapped",[1603,1582]],[[64711,64711],"mapped",[1603,1604]],[[64712,64712],"mapped",[1603,1605]],[[64713,64713],"mapped",[1604,1580]],[[64714,64714],"mapped",[1604,1581]],[[64715,64715],"mapped",[1604,1582]],[[64716,64716],"mapped",[1604,1605]],[[64717,64717],"mapped",[1604,1607]],[[64718,64718],"mapped",[1605,1580]],[[64719,64719],"mapped",[1605,1581]],[[64720,64720],"mapped",[1605,1582]],[[64721,64721],"mapped",[1605,1605]],[[64722,64722],"mapped",[1606,1580]],[[64723,64723],"mapped",[1606,1581]],[[64724,64724],"mapped",[1606,1582]],[[64725,64725],"mapped",[1606,1605]],[[64726,64726],"mapped",[1606,1607]],[[64727,64727],"mapped",[1607,1580]],[[64728,64728],"mapped",[1607,1605]],[[64729,64729],"mapped",[1607,1648]],[[64730,64730],"mapped",[1610,1580]],[[64731,64731],"mapped",[1610,1581]],[[64732,64732],"mapped",[1610,1582]],[[64733,64733],"mapped",[1610,1605]],[[64734,64734],"mapped",[1610,1607]],[[64735,64735],"mapped",[1574,1605]],[[64736,64736],"mapped",[1574,1607]],[[64737,64737],"mapped",[1576,1605]],[[64738,64738],"mapped",[1576,1607]],[[64739,64739],"mapped",[1578,1605]],[[64740,64740],"mapped",[1578,1607]],[[64741,64741],"mapped",[1579,1605]],[[64742,64742],"mapped",[1579,1607]],[[64743,64743],"mapped",[1587,1605]],[[64744,64744],"mapped",[1587,1607]],[[64745,64745],"mapped",[1588,1605]],[[64746,64746],"mapped",[1588,1607]],[[64747,64747],"mapped",[1603,1604]],[[64748,64748],"mapped",[1603,1605]],[[64749,64749],"mapped",[1604,1605]],[[64750,64750],"mapped",[1606,1605]],[[64751,64751],"mapped",[1606,1607]],[[64752,64752],"mapped",[1610,1605]],[[64753,64753],"mapped",[1610,1607]],[[64754,64754],"mapped",[1600,1614,1617]],[[64755,64755],"mapped",[1600,1615,1617]],[[64756,64756],"mapped",[1600,1616,1617]],[[64757,64757],"mapped",[1591,1609]],[[64758,64758],"mapped",[1591,1610]],[[64759,64759],"mapped",[1593,1609]],[[64760,64760],"mapped",[1593,1610]],[[64761,64761],"mapped",[1594,1609]],[[64762,64762],"mapped",[1594,1610]],[[64763,64763],"mapped",[1587,1609]],[[64764,64764],"mapped",[1587,1610]],[[64765,64765],"mapped",[1588,1609]],[[64766,64766],"mapped",[1588,1610]],[[64767,64767],"mapped",[1581,1609]],[[64768,64768],"mapped",[1581,1610]],[[64769,64769],"mapped",[1580,1609]],[[64770,64770],"mapped",[1580,1610]],[[64771,64771],"mapped",[1582,1609]],[[64772,64772],"mapped",[1582,1610]],[[64773,64773],"mapped",[1589,1609]],[[64774,64774],"mapped",[1589,1610]],[[64775,64775],"mapped",[1590,1609]],[[64776,64776],"mapped",[1590,1610]],[[64777,64777],"mapped",[1588,1580]],[[64778,64778],"mapped",[1588,1581]],[[64779,64779],"mapped",[1588,1582]],[[64780,64780],"mapped",[1588,1605]],[[64781,64781],"mapped",[1588,1585]],[[64782,64782],"mapped",[1587,1585]],[[64783,64783],"mapped",[1589,1585]],[[64784,64784],"mapped",[1590,1585]],[[64785,64785],"mapped",[1591,1609]],[[64786,64786],"mapped",[1591,1610]],[[64787,64787],"mapped",[1593,1609]],[[64788,64788],"mapped",[1593,1610]],[[64789,64789],"mapped",[1594,1609]],[[64790,64790],"mapped",[1594,1610]],[[64791,64791],"mapped",[1587,1609]],[[64792,64792],"mapped",[1587,1610]],[[64793,64793],"mapped",[1588,1609]],[[64794,64794],"mapped",[1588,1610]],[[64795,64795],"mapped",[1581,1609]],[[64796,64796],"mapped",[1581,1610]],[[64797,64797],"mapped",[1580,1609]],[[64798,64798],"mapped",[1580,1610]],[[64799,64799],"mapped",[1582,1609]],[[64800,64800],"mapped",[1582,1610]],[[64801,64801],"mapped",[1589,1609]],[[64802,64802],"mapped",[1589,1610]],[[64803,64803],"mapped",[1590,1609]],[[64804,64804],"mapped",[1590,1610]],[[64805,64805],"mapped",[1588,1580]],[[64806,64806],"mapped",[1588,1581]],[[64807,64807],"mapped",[1588,1582]],[[64808,64808],"mapped",[1588,1605]],[[64809,64809],"mapped",[1588,1585]],[[64810,64810],"mapped",[1587,1585]],[[64811,64811],"mapped",[1589,1585]],[[64812,64812],"mapped",[1590,1585]],[[64813,64813],"mapped",[1588,1580]],[[64814,64814],"mapped",[1588,1581]],[[64815,64815],"mapped",[1588,1582]],[[64816,64816],"mapped",[1588,1605]],[[64817,64817],"mapped",[1587,1607]],[[64818,64818],"mapped",[1588,1607]],[[64819,64819],"mapped",[1591,1605]],[[64820,64820],"mapped",[1587,1580]],[[64821,64821],"mapped",[1587,1581]],[[64822,64822],"mapped",[1587,1582]],[[64823,64823],"mapped",[1588,1580]],[[64824,64824],"mapped",[1588,1581]],[[64825,64825],"mapped",[1588,1582]],[[64826,64826],"mapped",[1591,1605]],[[64827,64827],"mapped",[1592,1605]],[[64828,64829],"mapped",[1575,1611]],[[64830,64831],"valid",[],"NV8"],[[64832,64847],"disallowed"],[[64848,64848],"mapped",[1578,1580,1605]],[[64849,64850],"mapped",[1578,1581,1580]],[[64851,64851],"mapped",[1578,1581,1605]],[[64852,64852],"mapped",[1578,1582,1605]],[[64853,64853],"mapped",[1578,1605,1580]],[[64854,64854],"mapped",[1578,1605,1581]],[[64855,64855],"mapped",[1578,1605,1582]],[[64856,64857],"mapped",[1580,1605,1581]],[[64858,64858],"mapped",[1581,1605,1610]],[[64859,64859],"mapped",[1581,1605,1609]],[[64860,64860],"mapped",[1587,1581,1580]],[[64861,64861],"mapped",[1587,1580,1581]],[[64862,64862],"mapped",[1587,1580,1609]],[[64863,64864],"mapped",[1587,1605,1581]],[[64865,64865],"mapped",[1587,1605,1580]],[[64866,64867],"mapped",[1587,1605,1605]],[[64868,64869],"mapped",[1589,1581,1581]],[[64870,64870],"mapped",[1589,1605,1605]],[[64871,64872],"mapped",[1588,1581,1605]],[[64873,64873],"mapped",[1588,1580,1610]],[[64874,64875],"mapped",[1588,1605,1582]],[[64876,64877],"mapped",[1588,1605,1605]],[[64878,64878],"mapped",[1590,1581,1609]],[[64879,64880],"mapped",[1590,1582,1605]],[[64881,64882],"mapped",[1591,1605,1581]],[[64883,64883],"mapped",[1591,1605,1605]],[[64884,64884],"mapped",[1591,1605,1610]],[[64885,64885],"mapped",[1593,1580,1605]],[[64886,64887],"mapped",[1593,1605,1605]],[[64888,64888],"mapped",[1593,1605,1609]],[[64889,64889],"mapped",[1594,1605,1605]],[[64890,64890],"mapped",[1594,1605,1610]],[[64891,64891],"mapped",[1594,1605,1609]],[[64892,64893],"mapped",[1601,1582,1605]],[[64894,64894],"mapped",[1602,1605,1581]],[[64895,64895],"mapped",[1602,1605,1605]],[[64896,64896],"mapped",[1604,1581,1605]],[[64897,64897],"mapped",[1604,1581,1610]],[[64898,64898],"mapped",[1604,1581,1609]],[[64899,64900],"mapped",[1604,1580,1580]],[[64901,64902],"mapped",[1604,1582,1605]],[[64903,64904],"mapped",[1604,1605,1581]],[[64905,64905],"mapped",[1605,1581,1580]],[[64906,64906],"mapped",[1605,1581,1605]],[[64907,64907],"mapped",[1605,1581,1610]],[[64908,64908],"mapped",[1605,1580,1581]],[[64909,64909],"mapped",[1605,1580,1605]],[[64910,64910],"mapped",[1605,1582,1580]],[[64911,64911],"mapped",[1605,1582,1605]],[[64912,64913],"disallowed"],[[64914,64914],"mapped",[1605,1580,1582]],[[64915,64915],"mapped",[1607,1605,1580]],[[64916,64916],"mapped",[1607,1605,1605]],[[64917,64917],"mapped",[1606,1581,1605]],[[64918,64918],"mapped",[1606,1581,1609]],[[64919,64920],"mapped",[1606,1580,1605]],[[64921,64921],"mapped",[1606,1580,1609]],[[64922,64922],"mapped",[1606,1605,1610]],[[64923,64923],"mapped",[1606,1605,1609]],[[64924,64925],"mapped",[1610,1605,1605]],[[64926,64926],"mapped",[1576,1582,1610]],[[64927,64927],"mapped",[1578,1580,1610]],[[64928,64928],"mapped",[1578,1580,1609]],[[64929,64929],"mapped",[1578,1582,1610]],[[64930,64930],"mapped",[1578,1582,1609]],[[64931,64931],"mapped",[1578,1605,1610]],[[64932,64932],"mapped",[1578,1605,1609]],[[64933,64933],"mapped",[1580,1605,1610]],[[64934,64934],"mapped",[1580,1581,1609]],[[64935,64935],"mapped",[1580,1605,1609]],[[64936,64936],"mapped",[1587,1582,1609]],[[64937,64937],"mapped",[1589,1581,1610]],[[64938,64938],"mapped",[1588,1581,1610]],[[64939,64939],"mapped",[1590,1581,1610]],[[64940,64940],"mapped",[1604,1580,1610]],[[64941,64941],"mapped",[1604,1605,1610]],[[64942,64942],"mapped",[1610,1581,1610]],[[64943,64943],"mapped",[1610,1580,1610]],[[64944,64944],"mapped",[1610,1605,1610]],[[64945,64945],"mapped",[1605,1605,1610]],[[64946,64946],"mapped",[1602,1605,1610]],[[64947,64947],"mapped",[1606,1581,1610]],[[64948,64948],"mapped",[1602,1605,1581]],[[64949,64949],"mapped",[1604,1581,1605]],[[64950,64950],"mapped",[1593,1605,1610]],[[64951,64951],"mapped",[1603,1605,1610]],[[64952,64952],"mapped",[1606,1580,1581]],[[64953,64953],"mapped",[1605,1582,1610]],[[64954,64954],"mapped",[1604,1580,1605]],[[64955,64955],"mapped",[1603,1605,1605]],[[64956,64956],"mapped",[1604,1580,1605]],[[64957,64957],"mapped",[1606,1580,1581]],[[64958,64958],"mapped",[1580,1581,1610]],[[64959,64959],"mapped",[1581,1580,1610]],[[64960,64960],"mapped",[1605,1580,1610]],[[64961,64961],"mapped",[1601,1605,1610]],[[64962,64962],"mapped",[1576,1581,1610]],[[64963,64963],"mapped",[1603,1605,1605]],[[64964,64964],"mapped",[1593,1580,1605]],[[64965,64965],"mapped",[1589,1605,1605]],[[64966,64966],"mapped",[1587,1582,1610]],[[64967,64967],"mapped",[1606,1580,1610]],[[64968,64975],"disallowed"],[[64976,65007],"disallowed"],[[65008,65008],"mapped",[1589,1604,1746]],[[65009,65009],"mapped",[1602,1604,1746]],[[65010,65010],"mapped",[1575,1604,1604,1607]],[[65011,65011],"mapped",[1575,1603,1576,1585]],[[65012,65012],"mapped",[1605,1581,1605,1583]],[[65013,65013],"mapped",[1589,1604,1593,1605]],[[65014,65014],"mapped",[1585,1587,1608,1604]],[[65015,65015],"mapped",[1593,1604,1610,1607]],[[65016,65016],"mapped",[1608,1587,1604,1605]],[[65017,65017],"mapped",[1589,1604,1609]],[[65018,65018],"disallowed_STD3_mapped",[1589,1604,1609,32,1575,1604,1604,1607,32,1593,1604,1610,1607,32,1608,1587,1604,1605]],[[65019,65019],"disallowed_STD3_mapped",[1580,1604,32,1580,1604,1575,1604,1607]],[[65020,65020],"mapped",[1585,1740,1575,1604]],[[65021,65021],"valid",[],"NV8"],[[65022,65023],"disallowed"],[[65024,65039],"ignored"],[[65040,65040],"disallowed_STD3_mapped",[44]],[[65041,65041],"mapped",[12289]],[[65042,65042],"disallowed"],[[65043,65043],"disallowed_STD3_mapped",[58]],[[65044,65044],"disallowed_STD3_mapped",[59]],[[65045,65045],"disallowed_STD3_mapped",[33]],[[65046,65046],"disallowed_STD3_mapped",[63]],[[65047,65047],"mapped",[12310]],[[65048,65048],"mapped",[12311]],[[65049,65049],"disallowed"],[[65050,65055],"disallowed"],[[65056,65059],"valid"],[[65060,65062],"valid"],[[65063,65069],"valid"],[[65070,65071],"valid"],[[65072,65072],"disallowed"],[[65073,65073],"mapped",[8212]],[[65074,65074],"mapped",[8211]],[[65075,65076],"disallowed_STD3_mapped",[95]],[[65077,65077],"disallowed_STD3_mapped",[40]],[[65078,65078],"disallowed_STD3_mapped",[41]],[[65079,65079],"disallowed_STD3_mapped",[123]],[[65080,65080],"disallowed_STD3_mapped",[125]],[[65081,65081],"mapped",[12308]],[[65082,65082],"mapped",[12309]],[[65083,65083],"mapped",[12304]],[[65084,65084],"mapped",[12305]],[[65085,65085],"mapped",[12298]],[[65086,65086],"mapped",[12299]],[[65087,65087],"mapped",[12296]],[[65088,65088],"mapped",[12297]],[[65089,65089],"mapped",[12300]],[[65090,65090],"mapped",[12301]],[[65091,65091],"mapped",[12302]],[[65092,65092],"mapped",[12303]],[[65093,65094],"valid",[],"NV8"],[[65095,65095],"disallowed_STD3_mapped",[91]],[[65096,65096],"disallowed_STD3_mapped",[93]],[[65097,65100],"disallowed_STD3_mapped",[32,773]],[[65101,65103],"disallowed_STD3_mapped",[95]],[[65104,65104],"disallowed_STD3_mapped",[44]],[[65105,65105],"mapped",[12289]],[[65106,65106],"disallowed"],[[65107,65107],"disallowed"],[[65108,65108],"disallowed_STD3_mapped",[59]],[[65109,65109],"disallowed_STD3_mapped",[58]],[[65110,65110],"disallowed_STD3_mapped",[63]],[[65111,65111],"disallowed_STD3_mapped",[33]],[[65112,65112],"mapped",[8212]],[[65113,65113],"disallowed_STD3_mapped",[40]],[[65114,65114],"disallowed_STD3_mapped",[41]],[[65115,65115],"disallowed_STD3_mapped",[123]],[[65116,65116],"disallowed_STD3_mapped",[125]],[[65117,65117],"mapped",[12308]],[[65118,65118],"mapped",[12309]],[[65119,65119],"disallowed_STD3_mapped",[35]],[[65120,65120],"disallowed_STD3_mapped",[38]],[[65121,65121],"disallowed_STD3_mapped",[42]],[[65122,65122],"disallowed_STD3_mapped",[43]],[[65123,65123],"mapped",[45]],[[65124,65124],"disallowed_STD3_mapped",[60]],[[65125,65125],"disallowed_STD3_mapped",[62]],[[65126,65126],"disallowed_STD3_mapped",[61]],[[65127,65127],"disallowed"],[[65128,65128],"disallowed_STD3_mapped",[92]],[[65129,65129],"disallowed_STD3_mapped",[36]],[[65130,65130],"disallowed_STD3_mapped",[37]],[[65131,65131],"disallowed_STD3_mapped",[64]],[[65132,65135],"disallowed"],[[65136,65136],"disallowed_STD3_mapped",[32,1611]],[[65137,65137],"mapped",[1600,1611]],[[65138,65138],"disallowed_STD3_mapped",[32,1612]],[[65139,65139],"valid"],[[65140,65140],"disallowed_STD3_mapped",[32,1613]],[[65141,65141],"disallowed"],[[65142,65142],"disallowed_STD3_mapped",[32,1614]],[[65143,65143],"mapped",[1600,1614]],[[65144,65144],"disallowed_STD3_mapped",[32,1615]],[[65145,65145],"mapped",[1600,1615]],[[65146,65146],"disallowed_STD3_mapped",[32,1616]],[[65147,65147],"mapped",[1600,1616]],[[65148,65148],"disallowed_STD3_mapped",[32,1617]],[[65149,65149],"mapped",[1600,1617]],[[65150,65150],"disallowed_STD3_mapped",[32,1618]],[[65151,65151],"mapped",[1600,1618]],[[65152,65152],"mapped",[1569]],[[65153,65154],"mapped",[1570]],[[65155,65156],"mapped",[1571]],[[65157,65158],"mapped",[1572]],[[65159,65160],"mapped",[1573]],[[65161,65164],"mapped",[1574]],[[65165,65166],"mapped",[1575]],[[65167,65170],"mapped",[1576]],[[65171,65172],"mapped",[1577]],[[65173,65176],"mapped",[1578]],[[65177,65180],"mapped",[1579]],[[65181,65184],"mapped",[1580]],[[65185,65188],"mapped",[1581]],[[65189,65192],"mapped",[1582]],[[65193,65194],"mapped",[1583]],[[65195,65196],"mapped",[1584]],[[65197,65198],"mapped",[1585]],[[65199,65200],"mapped",[1586]],[[65201,65204],"mapped",[1587]],[[65205,65208],"mapped",[1588]],[[65209,65212],"mapped",[1589]],[[65213,65216],"mapped",[1590]],[[65217,65220],"mapped",[1591]],[[65221,65224],"mapped",[1592]],[[65225,65228],"mapped",[1593]],[[65229,65232],"mapped",[1594]],[[65233,65236],"mapped",[1601]],[[65237,65240],"mapped",[1602]],[[65241,65244],"mapped",[1603]],[[65245,65248],"mapped",[1604]],[[65249,65252],"mapped",[1605]],[[65253,65256],"mapped",[1606]],[[65257,65260],"mapped",[1607]],[[65261,65262],"mapped",[1608]],[[65263,65264],"mapped",[1609]],[[65265,65268],"mapped",[1610]],[[65269,65270],"mapped",[1604,1570]],[[65271,65272],"mapped",[1604,1571]],[[65273,65274],"mapped",[1604,1573]],[[65275,65276],"mapped",[1604,1575]],[[65277,65278],"disallowed"],[[65279,65279],"ignored"],[[65280,65280],"disallowed"],[[65281,65281],"disallowed_STD3_mapped",[33]],[[65282,65282],"disallowed_STD3_mapped",[34]],[[65283,65283],"disallowed_STD3_mapped",[35]],[[65284,65284],"disallowed_STD3_mapped",[36]],[[65285,65285],"disallowed_STD3_mapped",[37]],[[65286,65286],"disallowed_STD3_mapped",[38]],[[65287,65287],"disallowed_STD3_mapped",[39]],[[65288,65288],"disallowed_STD3_mapped",[40]],[[65289,65289],"disallowed_STD3_mapped",[41]],[[65290,65290],"disallowed_STD3_mapped",[42]],[[65291,65291],"disallowed_STD3_mapped",[43]],[[65292,65292],"disallowed_STD3_mapped",[44]],[[65293,65293],"mapped",[45]],[[65294,65294],"mapped",[46]],[[65295,65295],"disallowed_STD3_mapped",[47]],[[65296,65296],"mapped",[48]],[[65297,65297],"mapped",[49]],[[65298,65298],"mapped",[50]],[[65299,65299],"mapped",[51]],[[65300,65300],"mapped",[52]],[[65301,65301],"mapped",[53]],[[65302,65302],"mapped",[54]],[[65303,65303],"mapped",[55]],[[65304,65304],"mapped",[56]],[[65305,65305],"mapped",[57]],[[65306,65306],"disallowed_STD3_mapped",[58]],[[65307,65307],"disallowed_STD3_mapped",[59]],[[65308,65308],"disallowed_STD3_mapped",[60]],[[65309,65309],"disallowed_STD3_mapped",[61]],[[65310,65310],"disallowed_STD3_mapped",[62]],[[65311,65311],"disallowed_STD3_mapped",[63]],[[65312,65312],"disallowed_STD3_mapped",[64]],[[65313,65313],"mapped",[97]],[[65314,65314],"mapped",[98]],[[65315,65315],"mapped",[99]],[[65316,65316],"mapped",[100]],[[65317,65317],"mapped",[101]],[[65318,65318],"mapped",[102]],[[65319,65319],"mapped",[103]],[[65320,65320],"mapped",[104]],[[65321,65321],"mapped",[105]],[[65322,65322],"mapped",[106]],[[65323,65323],"mapped",[107]],[[65324,65324],"mapped",[108]],[[65325,65325],"mapped",[109]],[[65326,65326],"mapped",[110]],[[65327,65327],"mapped",[111]],[[65328,65328],"mapped",[112]],[[65329,65329],"mapped",[113]],[[65330,65330],"mapped",[114]],[[65331,65331],"mapped",[115]],[[65332,65332],"mapped",[116]],[[65333,65333],"mapped",[117]],[[65334,65334],"mapped",[118]],[[65335,65335],"mapped",[119]],[[65336,65336],"mapped",[120]],[[65337,65337],"mapped",[121]],[[65338,65338],"mapped",[122]],[[65339,65339],"disallowed_STD3_mapped",[91]],[[65340,65340],"disallowed_STD3_mapped",[92]],[[65341,65341],"disallowed_STD3_mapped",[93]],[[65342,65342],"disallowed_STD3_mapped",[94]],[[65343,65343],"disallowed_STD3_mapped",[95]],[[65344,65344],"disallowed_STD3_mapped",[96]],[[65345,65345],"mapped",[97]],[[65346,65346],"mapped",[98]],[[65347,65347],"mapped",[99]],[[65348,65348],"mapped",[100]],[[65349,65349],"mapped",[101]],[[65350,65350],"mapped",[102]],[[65351,65351],"mapped",[103]],[[65352,65352],"mapped",[104]],[[65353,65353],"mapped",[105]],[[65354,65354],"mapped",[106]],[[65355,65355],"mapped",[107]],[[65356,65356],"mapped",[108]],[[65357,65357],"mapped",[109]],[[65358,65358],"mapped",[110]],[[65359,65359],"mapped",[111]],[[65360,65360],"mapped",[112]],[[65361,65361],"mapped",[113]],[[65362,65362],"mapped",[114]],[[65363,65363],"mapped",[115]],[[65364,65364],"mapped",[116]],[[65365,65365],"mapped",[117]],[[65366,65366],"mapped",[118]],[[65367,65367],"mapped",[119]],[[65368,65368],"mapped",[120]],[[65369,65369],"mapped",[121]],[[65370,65370],"mapped",[122]],[[65371,65371],"disallowed_STD3_mapped",[123]],[[65372,65372],"disallowed_STD3_mapped",[124]],[[65373,65373],"disallowed_STD3_mapped",[125]],[[65374,65374],"disallowed_STD3_mapped",[126]],[[65375,65375],"mapped",[10629]],[[65376,65376],"mapped",[10630]],[[65377,65377],"mapped",[46]],[[65378,65378],"mapped",[12300]],[[65379,65379],"mapped",[12301]],[[65380,65380],"mapped",[12289]],[[65381,65381],"mapped",[12539]],[[65382,65382],"mapped",[12530]],[[65383,65383],"mapped",[12449]],[[65384,65384],"mapped",[12451]],[[65385,65385],"mapped",[12453]],[[65386,65386],"mapped",[12455]],[[65387,65387],"mapped",[12457]],[[65388,65388],"mapped",[12515]],[[65389,65389],"mapped",[12517]],[[65390,65390],"mapped",[12519]],[[65391,65391],"mapped",[12483]],[[65392,65392],"mapped",[12540]],[[65393,65393],"mapped",[12450]],[[65394,65394],"mapped",[12452]],[[65395,65395],"mapped",[12454]],[[65396,65396],"mapped",[12456]],[[65397,65397],"mapped",[12458]],[[65398,65398],"mapped",[12459]],[[65399,65399],"mapped",[12461]],[[65400,65400],"mapped",[12463]],[[65401,65401],"mapped",[12465]],[[65402,65402],"mapped",[12467]],[[65403,65403],"mapped",[12469]],[[65404,65404],"mapped",[12471]],[[65405,65405],"mapped",[12473]],[[65406,65406],"mapped",[12475]],[[65407,65407],"mapped",[12477]],[[65408,65408],"mapped",[12479]],[[65409,65409],"mapped",[12481]],[[65410,65410],"mapped",[12484]],[[65411,65411],"mapped",[12486]],[[65412,65412],"mapped",[12488]],[[65413,65413],"mapped",[12490]],[[65414,65414],"mapped",[12491]],[[65415,65415],"mapped",[12492]],[[65416,65416],"mapped",[12493]],[[65417,65417],"mapped",[12494]],[[65418,65418],"mapped",[12495]],[[65419,65419],"mapped",[12498]],[[65420,65420],"mapped",[12501]],[[65421,65421],"mapped",[12504]],[[65422,65422],"mapped",[12507]],[[65423,65423],"mapped",[12510]],[[65424,65424],"mapped",[12511]],[[65425,65425],"mapped",[12512]],[[65426,65426],"mapped",[12513]],[[65427,65427],"mapped",[12514]],[[65428,65428],"mapped",[12516]],[[65429,65429],"mapped",[12518]],[[65430,65430],"mapped",[12520]],[[65431,65431],"mapped",[12521]],[[65432,65432],"mapped",[12522]],[[65433,65433],"mapped",[12523]],[[65434,65434],"mapped",[12524]],[[65435,65435],"mapped",[12525]],[[65436,65436],"mapped",[12527]],[[65437,65437],"mapped",[12531]],[[65438,65438],"mapped",[12441]],[[65439,65439],"mapped",[12442]],[[65440,65440],"disallowed"],[[65441,65441],"mapped",[4352]],[[65442,65442],"mapped",[4353]],[[65443,65443],"mapped",[4522]],[[65444,65444],"mapped",[4354]],[[65445,65445],"mapped",[4524]],[[65446,65446],"mapped",[4525]],[[65447,65447],"mapped",[4355]],[[65448,65448],"mapped",[4356]],[[65449,65449],"mapped",[4357]],[[65450,65450],"mapped",[4528]],[[65451,65451],"mapped",[4529]],[[65452,65452],"mapped",[4530]],[[65453,65453],"mapped",[4531]],[[65454,65454],"mapped",[4532]],[[65455,65455],"mapped",[4533]],[[65456,65456],"mapped",[4378]],[[65457,65457],"mapped",[4358]],[[65458,65458],"mapped",[4359]],[[65459,65459],"mapped",[4360]],[[65460,65460],"mapped",[4385]],[[65461,65461],"mapped",[4361]],[[65462,65462],"mapped",[4362]],[[65463,65463],"mapped",[4363]],[[65464,65464],"mapped",[4364]],[[65465,65465],"mapped",[4365]],[[65466,65466],"mapped",[4366]],[[65467,65467],"mapped",[4367]],[[65468,65468],"mapped",[4368]],[[65469,65469],"mapped",[4369]],[[65470,65470],"mapped",[4370]],[[65471,65473],"disallowed"],[[65474,65474],"mapped",[4449]],[[65475,65475],"mapped",[4450]],[[65476,65476],"mapped",[4451]],[[65477,65477],"mapped",[4452]],[[65478,65478],"mapped",[4453]],[[65479,65479],"mapped",[4454]],[[65480,65481],"disallowed"],[[65482,65482],"mapped",[4455]],[[65483,65483],"mapped",[4456]],[[65484,65484],"mapped",[4457]],[[65485,65485],"mapped",[4458]],[[65486,65486],"mapped",[4459]],[[65487,65487],"mapped",[4460]],[[65488,65489],"disallowed"],[[65490,65490],"mapped",[4461]],[[65491,65491],"mapped",[4462]],[[65492,65492],"mapped",[4463]],[[65493,65493],"mapped",[4464]],[[65494,65494],"mapped",[4465]],[[65495,65495],"mapped",[4466]],[[65496,65497],"disallowed"],[[65498,65498],"mapped",[4467]],[[65499,65499],"mapped",[4468]],[[65500,65500],"mapped",[4469]],[[65501,65503],"disallowed"],[[65504,65504],"mapped",[162]],[[65505,65505],"mapped",[163]],[[65506,65506],"mapped",[172]],[[65507,65507],"disallowed_STD3_mapped",[32,772]],[[65508,65508],"mapped",[166]],[[65509,65509],"mapped",[165]],[[65510,65510],"mapped",[8361]],[[65511,65511],"disallowed"],[[65512,65512],"mapped",[9474]],[[65513,65513],"mapped",[8592]],[[65514,65514],"mapped",[8593]],[[65515,65515],"mapped",[8594]],[[65516,65516],"mapped",[8595]],[[65517,65517],"mapped",[9632]],[[65518,65518],"mapped",[9675]],[[65519,65528],"disallowed"],[[65529,65531],"disallowed"],[[65532,65532],"disallowed"],[[65533,65533],"disallowed"],[[65534,65535],"disallowed"],[[65536,65547],"valid"],[[65548,65548],"disallowed"],[[65549,65574],"valid"],[[65575,65575],"disallowed"],[[65576,65594],"valid"],[[65595,65595],"disallowed"],[[65596,65597],"valid"],[[65598,65598],"disallowed"],[[65599,65613],"valid"],[[65614,65615],"disallowed"],[[65616,65629],"valid"],[[65630,65663],"disallowed"],[[65664,65786],"valid"],[[65787,65791],"disallowed"],[[65792,65794],"valid",[],"NV8"],[[65795,65798],"disallowed"],[[65799,65843],"valid",[],"NV8"],[[65844,65846],"disallowed"],[[65847,65855],"valid",[],"NV8"],[[65856,65930],"valid",[],"NV8"],[[65931,65932],"valid",[],"NV8"],[[65933,65935],"disallowed"],[[65936,65947],"valid",[],"NV8"],[[65948,65951],"disallowed"],[[65952,65952],"valid",[],"NV8"],[[65953,65999],"disallowed"],[[66000,66044],"valid",[],"NV8"],[[66045,66045],"valid"],[[66046,66175],"disallowed"],[[66176,66204],"valid"],[[66205,66207],"disallowed"],[[66208,66256],"valid"],[[66257,66271],"disallowed"],[[66272,66272],"valid"],[[66273,66299],"valid",[],"NV8"],[[66300,66303],"disallowed"],[[66304,66334],"valid"],[[66335,66335],"valid"],[[66336,66339],"valid",[],"NV8"],[[66340,66351],"disallowed"],[[66352,66368],"valid"],[[66369,66369],"valid",[],"NV8"],[[66370,66377],"valid"],[[66378,66378],"valid",[],"NV8"],[[66379,66383],"disallowed"],[[66384,66426],"valid"],[[66427,66431],"disallowed"],[[66432,66461],"valid"],[[66462,66462],"disallowed"],[[66463,66463],"valid",[],"NV8"],[[66464,66499],"valid"],[[66500,66503],"disallowed"],[[66504,66511],"valid"],[[66512,66517],"valid",[],"NV8"],[[66518,66559],"disallowed"],[[66560,66560],"mapped",[66600]],[[66561,66561],"mapped",[66601]],[[66562,66562],"mapped",[66602]],[[66563,66563],"mapped",[66603]],[[66564,66564],"mapped",[66604]],[[66565,66565],"mapped",[66605]],[[66566,66566],"mapped",[66606]],[[66567,66567],"mapped",[66607]],[[66568,66568],"mapped",[66608]],[[66569,66569],"mapped",[66609]],[[66570,66570],"mapped",[66610]],[[66571,66571],"mapped",[66611]],[[66572,66572],"mapped",[66612]],[[66573,66573],"mapped",[66613]],[[66574,66574],"mapped",[66614]],[[66575,66575],"mapped",[66615]],[[66576,66576],"mapped",[66616]],[[66577,66577],"mapped",[66617]],[[66578,66578],"mapped",[66618]],[[66579,66579],"mapped",[66619]],[[66580,66580],"mapped",[66620]],[[66581,66581],"mapped",[66621]],[[66582,66582],"mapped",[66622]],[[66583,66583],"mapped",[66623]],[[66584,66584],"mapped",[66624]],[[66585,66585],"mapped",[66625]],[[66586,66586],"mapped",[66626]],[[66587,66587],"mapped",[66627]],[[66588,66588],"mapped",[66628]],[[66589,66589],"mapped",[66629]],[[66590,66590],"mapped",[66630]],[[66591,66591],"mapped",[66631]],[[66592,66592],"mapped",[66632]],[[66593,66593],"mapped",[66633]],[[66594,66594],"mapped",[66634]],[[66595,66595],"mapped",[66635]],[[66596,66596],"mapped",[66636]],[[66597,66597],"mapped",[66637]],[[66598,66598],"mapped",[66638]],[[66599,66599],"mapped",[66639]],[[66600,66637],"valid"],[[66638,66717],"valid"],[[66718,66719],"disallowed"],[[66720,66729],"valid"],[[66730,66815],"disallowed"],[[66816,66855],"valid"],[[66856,66863],"disallowed"],[[66864,66915],"valid"],[[66916,66926],"disallowed"],[[66927,66927],"valid",[],"NV8"],[[66928,67071],"disallowed"],[[67072,67382],"valid"],[[67383,67391],"disallowed"],[[67392,67413],"valid"],[[67414,67423],"disallowed"],[[67424,67431],"valid"],[[67432,67583],"disallowed"],[[67584,67589],"valid"],[[67590,67591],"disallowed"],[[67592,67592],"valid"],[[67593,67593],"disallowed"],[[67594,67637],"valid"],[[67638,67638],"disallowed"],[[67639,67640],"valid"],[[67641,67643],"disallowed"],[[67644,67644],"valid"],[[67645,67646],"disallowed"],[[67647,67647],"valid"],[[67648,67669],"valid"],[[67670,67670],"disallowed"],[[67671,67679],"valid",[],"NV8"],[[67680,67702],"valid"],[[67703,67711],"valid",[],"NV8"],[[67712,67742],"valid"],[[67743,67750],"disallowed"],[[67751,67759],"valid",[],"NV8"],[[67760,67807],"disallowed"],[[67808,67826],"valid"],[[67827,67827],"disallowed"],[[67828,67829],"valid"],[[67830,67834],"disallowed"],[[67835,67839],"valid",[],"NV8"],[[67840,67861],"valid"],[[67862,67865],"valid",[],"NV8"],[[67866,67867],"valid",[],"NV8"],[[67868,67870],"disallowed"],[[67871,67871],"valid",[],"NV8"],[[67872,67897],"valid"],[[67898,67902],"disallowed"],[[67903,67903],"valid",[],"NV8"],[[67904,67967],"disallowed"],[[67968,68023],"valid"],[[68024,68027],"disallowed"],[[68028,68029],"valid",[],"NV8"],[[68030,68031],"valid"],[[68032,68047],"valid",[],"NV8"],[[68048,68049],"disallowed"],[[68050,68095],"valid",[],"NV8"],[[68096,68099],"valid"],[[68100,68100],"disallowed"],[[68101,68102],"valid"],[[68103,68107],"disallowed"],[[68108,68115],"valid"],[[68116,68116],"disallowed"],[[68117,68119],"valid"],[[68120,68120],"disallowed"],[[68121,68147],"valid"],[[68148,68151],"disallowed"],[[68152,68154],"valid"],[[68155,68158],"disallowed"],[[68159,68159],"valid"],[[68160,68167],"valid",[],"NV8"],[[68168,68175],"disallowed"],[[68176,68184],"valid",[],"NV8"],[[68185,68191],"disallowed"],[[68192,68220],"valid"],[[68221,68223],"valid",[],"NV8"],[[68224,68252],"valid"],[[68253,68255],"valid",[],"NV8"],[[68256,68287],"disallowed"],[[68288,68295],"valid"],[[68296,68296],"valid",[],"NV8"],[[68297,68326],"valid"],[[68327,68330],"disallowed"],[[68331,68342],"valid",[],"NV8"],[[68343,68351],"disallowed"],[[68352,68405],"valid"],[[68406,68408],"disallowed"],[[68409,68415],"valid",[],"NV8"],[[68416,68437],"valid"],[[68438,68439],"disallowed"],[[68440,68447],"valid",[],"NV8"],[[68448,68466],"valid"],[[68467,68471],"disallowed"],[[68472,68479],"valid",[],"NV8"],[[68480,68497],"valid"],[[68498,68504],"disallowed"],[[68505,68508],"valid",[],"NV8"],[[68509,68520],"disallowed"],[[68521,68527],"valid",[],"NV8"],[[68528,68607],"disallowed"],[[68608,68680],"valid"],[[68681,68735],"disallowed"],[[68736,68736],"mapped",[68800]],[[68737,68737],"mapped",[68801]],[[68738,68738],"mapped",[68802]],[[68739,68739],"mapped",[68803]],[[68740,68740],"mapped",[68804]],[[68741,68741],"mapped",[68805]],[[68742,68742],"mapped",[68806]],[[68743,68743],"mapped",[68807]],[[68744,68744],"mapped",[68808]],[[68745,68745],"mapped",[68809]],[[68746,68746],"mapped",[68810]],[[68747,68747],"mapped",[68811]],[[68748,68748],"mapped",[68812]],[[68749,68749],"mapped",[68813]],[[68750,68750],"mapped",[68814]],[[68751,68751],"mapped",[68815]],[[68752,68752],"mapped",[68816]],[[68753,68753],"mapped",[68817]],[[68754,68754],"mapped",[68818]],[[68755,68755],"mapped",[68819]],[[68756,68756],"mapped",[68820]],[[68757,68757],"mapped",[68821]],[[68758,68758],"mapped",[68822]],[[68759,68759],"mapped",[68823]],[[68760,68760],"mapped",[68824]],[[68761,68761],"mapped",[68825]],[[68762,68762],"mapped",[68826]],[[68763,68763],"mapped",[68827]],[[68764,68764],"mapped",[68828]],[[68765,68765],"mapped",[68829]],[[68766,68766],"mapped",[68830]],[[68767,68767],"mapped",[68831]],[[68768,68768],"mapped",[68832]],[[68769,68769],"mapped",[68833]],[[68770,68770],"mapped",[68834]],[[68771,68771],"mapped",[68835]],[[68772,68772],"mapped",[68836]],[[68773,68773],"mapped",[68837]],[[68774,68774],"mapped",[68838]],[[68775,68775],"mapped",[68839]],[[68776,68776],"mapped",[68840]],[[68777,68777],"mapped",[68841]],[[68778,68778],"mapped",[68842]],[[68779,68779],"mapped",[68843]],[[68780,68780],"mapped",[68844]],[[68781,68781],"mapped",[68845]],[[68782,68782],"mapped",[68846]],[[68783,68783],"mapped",[68847]],[[68784,68784],"mapped",[68848]],[[68785,68785],"mapped",[68849]],[[68786,68786],"mapped",[68850]],[[68787,68799],"disallowed"],[[68800,68850],"valid"],[[68851,68857],"disallowed"],[[68858,68863],"valid",[],"NV8"],[[68864,69215],"disallowed"],[[69216,69246],"valid",[],"NV8"],[[69247,69631],"disallowed"],[[69632,69702],"valid"],[[69703,69709],"valid",[],"NV8"],[[69710,69713],"disallowed"],[[69714,69733],"valid",[],"NV8"],[[69734,69743],"valid"],[[69744,69758],"disallowed"],[[69759,69759],"valid"],[[69760,69818],"valid"],[[69819,69820],"valid",[],"NV8"],[[69821,69821],"disallowed"],[[69822,69825],"valid",[],"NV8"],[[69826,69839],"disallowed"],[[69840,69864],"valid"],[[69865,69871],"disallowed"],[[69872,69881],"valid"],[[69882,69887],"disallowed"],[[69888,69940],"valid"],[[69941,69941],"disallowed"],[[69942,69951],"valid"],[[69952,69955],"valid",[],"NV8"],[[69956,69967],"disallowed"],[[69968,70003],"valid"],[[70004,70005],"valid",[],"NV8"],[[70006,70006],"valid"],[[70007,70015],"disallowed"],[[70016,70084],"valid"],[[70085,70088],"valid",[],"NV8"],[[70089,70089],"valid",[],"NV8"],[[70090,70092],"valid"],[[70093,70093],"valid",[],"NV8"],[[70094,70095],"disallowed"],[[70096,70105],"valid"],[[70106,70106],"valid"],[[70107,70107],"valid",[],"NV8"],[[70108,70108],"valid"],[[70109,70111],"valid",[],"NV8"],[[70112,70112],"disallowed"],[[70113,70132],"valid",[],"NV8"],[[70133,70143],"disallowed"],[[70144,70161],"valid"],[[70162,70162],"disallowed"],[[70163,70199],"valid"],[[70200,70205],"valid",[],"NV8"],[[70206,70271],"disallowed"],[[70272,70278],"valid"],[[70279,70279],"disallowed"],[[70280,70280],"valid"],[[70281,70281],"disallowed"],[[70282,70285],"valid"],[[70286,70286],"disallowed"],[[70287,70301],"valid"],[[70302,70302],"disallowed"],[[70303,70312],"valid"],[[70313,70313],"valid",[],"NV8"],[[70314,70319],"disallowed"],[[70320,70378],"valid"],[[70379,70383],"disallowed"],[[70384,70393],"valid"],[[70394,70399],"disallowed"],[[70400,70400],"valid"],[[70401,70403],"valid"],[[70404,70404],"disallowed"],[[70405,70412],"valid"],[[70413,70414],"disallowed"],[[70415,70416],"valid"],[[70417,70418],"disallowed"],[[70419,70440],"valid"],[[70441,70441],"disallowed"],[[70442,70448],"valid"],[[70449,70449],"disallowed"],[[70450,70451],"valid"],[[70452,70452],"disallowed"],[[70453,70457],"valid"],[[70458,70459],"disallowed"],[[70460,70468],"valid"],[[70469,70470],"disallowed"],[[70471,70472],"valid"],[[70473,70474],"disallowed"],[[70475,70477],"valid"],[[70478,70479],"disallowed"],[[70480,70480],"valid"],[[70481,70486],"disallowed"],[[70487,70487],"valid"],[[70488,70492],"disallowed"],[[70493,70499],"valid"],[[70500,70501],"disallowed"],[[70502,70508],"valid"],[[70509,70511],"disallowed"],[[70512,70516],"valid"],[[70517,70783],"disallowed"],[[70784,70853],"valid"],[[70854,70854],"valid",[],"NV8"],[[70855,70855],"valid"],[[70856,70863],"disallowed"],[[70864,70873],"valid"],[[70874,71039],"disallowed"],[[71040,71093],"valid"],[[71094,71095],"disallowed"],[[71096,71104],"valid"],[[71105,71113],"valid",[],"NV8"],[[71114,71127],"valid",[],"NV8"],[[71128,71133],"valid"],[[71134,71167],"disallowed"],[[71168,71232],"valid"],[[71233,71235],"valid",[],"NV8"],[[71236,71236],"valid"],[[71237,71247],"disallowed"],[[71248,71257],"valid"],[[71258,71295],"disallowed"],[[71296,71351],"valid"],[[71352,71359],"disallowed"],[[71360,71369],"valid"],[[71370,71423],"disallowed"],[[71424,71449],"valid"],[[71450,71452],"disallowed"],[[71453,71467],"valid"],[[71468,71471],"disallowed"],[[71472,71481],"valid"],[[71482,71487],"valid",[],"NV8"],[[71488,71839],"disallowed"],[[71840,71840],"mapped",[71872]],[[71841,71841],"mapped",[71873]],[[71842,71842],"mapped",[71874]],[[71843,71843],"mapped",[71875]],[[71844,71844],"mapped",[71876]],[[71845,71845],"mapped",[71877]],[[71846,71846],"mapped",[71878]],[[71847,71847],"mapped",[71879]],[[71848,71848],"mapped",[71880]],[[71849,71849],"mapped",[71881]],[[71850,71850],"mapped",[71882]],[[71851,71851],"mapped",[71883]],[[71852,71852],"mapped",[71884]],[[71853,71853],"mapped",[71885]],[[71854,71854],"mapped",[71886]],[[71855,71855],"mapped",[71887]],[[71856,71856],"mapped",[71888]],[[71857,71857],"mapped",[71889]],[[71858,71858],"mapped",[71890]],[[71859,71859],"mapped",[71891]],[[71860,71860],"mapped",[71892]],[[71861,71861],"mapped",[71893]],[[71862,71862],"mapped",[71894]],[[71863,71863],"mapped",[71895]],[[71864,71864],"mapped",[71896]],[[71865,71865],"mapped",[71897]],[[71866,71866],"mapped",[71898]],[[71867,71867],"mapped",[71899]],[[71868,71868],"mapped",[71900]],[[71869,71869],"mapped",[71901]],[[71870,71870],"mapped",[71902]],[[71871,71871],"mapped",[71903]],[[71872,71913],"valid"],[[71914,71922],"valid",[],"NV8"],[[71923,71934],"disallowed"],[[71935,71935],"valid"],[[71936,72383],"disallowed"],[[72384,72440],"valid"],[[72441,73727],"disallowed"],[[73728,74606],"valid"],[[74607,74648],"valid"],[[74649,74649],"valid"],[[74650,74751],"disallowed"],[[74752,74850],"valid",[],"NV8"],[[74851,74862],"valid",[],"NV8"],[[74863,74863],"disallowed"],[[74864,74867],"valid",[],"NV8"],[[74868,74868],"valid",[],"NV8"],[[74869,74879],"disallowed"],[[74880,75075],"valid"],[[75076,77823],"disallowed"],[[77824,78894],"valid"],[[78895,82943],"disallowed"],[[82944,83526],"valid"],[[83527,92159],"disallowed"],[[92160,92728],"valid"],[[92729,92735],"disallowed"],[[92736,92766],"valid"],[[92767,92767],"disallowed"],[[92768,92777],"valid"],[[92778,92781],"disallowed"],[[92782,92783],"valid",[],"NV8"],[[92784,92879],"disallowed"],[[92880,92909],"valid"],[[92910,92911],"disallowed"],[[92912,92916],"valid"],[[92917,92917],"valid",[],"NV8"],[[92918,92927],"disallowed"],[[92928,92982],"valid"],[[92983,92991],"valid",[],"NV8"],[[92992,92995],"valid"],[[92996,92997],"valid",[],"NV8"],[[92998,93007],"disallowed"],[[93008,93017],"valid"],[[93018,93018],"disallowed"],[[93019,93025],"valid",[],"NV8"],[[93026,93026],"disallowed"],[[93027,93047],"valid"],[[93048,93052],"disallowed"],[[93053,93071],"valid"],[[93072,93951],"disallowed"],[[93952,94020],"valid"],[[94021,94031],"disallowed"],[[94032,94078],"valid"],[[94079,94094],"disallowed"],[[94095,94111],"valid"],[[94112,110591],"disallowed"],[[110592,110593],"valid"],[[110594,113663],"disallowed"],[[113664,113770],"valid"],[[113771,113775],"disallowed"],[[113776,113788],"valid"],[[113789,113791],"disallowed"],[[113792,113800],"valid"],[[113801,113807],"disallowed"],[[113808,113817],"valid"],[[113818,113819],"disallowed"],[[113820,113820],"valid",[],"NV8"],[[113821,113822],"valid"],[[113823,113823],"valid",[],"NV8"],[[113824,113827],"ignored"],[[113828,118783],"disallowed"],[[118784,119029],"valid",[],"NV8"],[[119030,119039],"disallowed"],[[119040,119078],"valid",[],"NV8"],[[119079,119080],"disallowed"],[[119081,119081],"valid",[],"NV8"],[[119082,119133],"valid",[],"NV8"],[[119134,119134],"mapped",[119127,119141]],[[119135,119135],"mapped",[119128,119141]],[[119136,119136],"mapped",[119128,119141,119150]],[[119137,119137],"mapped",[119128,119141,119151]],[[119138,119138],"mapped",[119128,119141,119152]],[[119139,119139],"mapped",[119128,119141,119153]],[[119140,119140],"mapped",[119128,119141,119154]],[[119141,119154],"valid",[],"NV8"],[[119155,119162],"disallowed"],[[119163,119226],"valid",[],"NV8"],[[119227,119227],"mapped",[119225,119141]],[[119228,119228],"mapped",[119226,119141]],[[119229,119229],"mapped",[119225,119141,119150]],[[119230,119230],"mapped",[119226,119141,119150]],[[119231,119231],"mapped",[119225,119141,119151]],[[119232,119232],"mapped",[119226,119141,119151]],[[119233,119261],"valid",[],"NV8"],[[119262,119272],"valid",[],"NV8"],[[119273,119295],"disallowed"],[[119296,119365],"valid",[],"NV8"],[[119366,119551],"disallowed"],[[119552,119638],"valid",[],"NV8"],[[119639,119647],"disallowed"],[[119648,119665],"valid",[],"NV8"],[[119666,119807],"disallowed"],[[119808,119808],"mapped",[97]],[[119809,119809],"mapped",[98]],[[119810,119810],"mapped",[99]],[[119811,119811],"mapped",[100]],[[119812,119812],"mapped",[101]],[[119813,119813],"mapped",[102]],[[119814,119814],"mapped",[103]],[[119815,119815],"mapped",[104]],[[119816,119816],"mapped",[105]],[[119817,119817],"mapped",[106]],[[119818,119818],"mapped",[107]],[[119819,119819],"mapped",[108]],[[119820,119820],"mapped",[109]],[[119821,119821],"mapped",[110]],[[119822,119822],"mapped",[111]],[[119823,119823],"mapped",[112]],[[119824,119824],"mapped",[113]],[[119825,119825],"mapped",[114]],[[119826,119826],"mapped",[115]],[[119827,119827],"mapped",[116]],[[119828,119828],"mapped",[117]],[[119829,119829],"mapped",[118]],[[119830,119830],"mapped",[119]],[[119831,119831],"mapped",[120]],[[119832,119832],"mapped",[121]],[[119833,119833],"mapped",[122]],[[119834,119834],"mapped",[97]],[[119835,119835],"mapped",[98]],[[119836,119836],"mapped",[99]],[[119837,119837],"mapped",[100]],[[119838,119838],"mapped",[101]],[[119839,119839],"mapped",[102]],[[119840,119840],"mapped",[103]],[[119841,119841],"mapped",[104]],[[119842,119842],"mapped",[105]],[[119843,119843],"mapped",[106]],[[119844,119844],"mapped",[107]],[[119845,119845],"mapped",[108]],[[119846,119846],"mapped",[109]],[[119847,119847],"mapped",[110]],[[119848,119848],"mapped",[111]],[[119849,119849],"mapped",[112]],[[119850,119850],"mapped",[113]],[[119851,119851],"mapped",[114]],[[119852,119852],"mapped",[115]],[[119853,119853],"mapped",[116]],[[119854,119854],"mapped",[117]],[[119855,119855],"mapped",[118]],[[119856,119856],"mapped",[119]],[[119857,119857],"mapped",[120]],[[119858,119858],"mapped",[121]],[[119859,119859],"mapped",[122]],[[119860,119860],"mapped",[97]],[[119861,119861],"mapped",[98]],[[119862,119862],"mapped",[99]],[[119863,119863],"mapped",[100]],[[119864,119864],"mapped",[101]],[[119865,119865],"mapped",[102]],[[119866,119866],"mapped",[103]],[[119867,119867],"mapped",[104]],[[119868,119868],"mapped",[105]],[[119869,119869],"mapped",[106]],[[119870,119870],"mapped",[107]],[[119871,119871],"mapped",[108]],[[119872,119872],"mapped",[109]],[[119873,119873],"mapped",[110]],[[119874,119874],"mapped",[111]],[[119875,119875],"mapped",[112]],[[119876,119876],"mapped",[113]],[[119877,119877],"mapped",[114]],[[119878,119878],"mapped",[115]],[[119879,119879],"mapped",[116]],[[119880,119880],"mapped",[117]],[[119881,119881],"mapped",[118]],[[119882,119882],"mapped",[119]],[[119883,119883],"mapped",[120]],[[119884,119884],"mapped",[121]],[[119885,119885],"mapped",[122]],[[119886,119886],"mapped",[97]],[[119887,119887],"mapped",[98]],[[119888,119888],"mapped",[99]],[[119889,119889],"mapped",[100]],[[119890,119890],"mapped",[101]],[[119891,119891],"mapped",[102]],[[119892,119892],"mapped",[103]],[[119893,119893],"disallowed"],[[119894,119894],"mapped",[105]],[[119895,119895],"mapped",[106]],[[119896,119896],"mapped",[107]],[[119897,119897],"mapped",[108]],[[119898,119898],"mapped",[109]],[[119899,119899],"mapped",[110]],[[119900,119900],"mapped",[111]],[[119901,119901],"mapped",[112]],[[119902,119902],"mapped",[113]],[[119903,119903],"mapped",[114]],[[119904,119904],"mapped",[115]],[[119905,119905],"mapped",[116]],[[119906,119906],"mapped",[117]],[[119907,119907],"mapped",[118]],[[119908,119908],"mapped",[119]],[[119909,119909],"mapped",[120]],[[119910,119910],"mapped",[121]],[[119911,119911],"mapped",[122]],[[119912,119912],"mapped",[97]],[[119913,119913],"mapped",[98]],[[119914,119914],"mapped",[99]],[[119915,119915],"mapped",[100]],[[119916,119916],"mapped",[101]],[[119917,119917],"mapped",[102]],[[119918,119918],"mapped",[103]],[[119919,119919],"mapped",[104]],[[119920,119920],"mapped",[105]],[[119921,119921],"mapped",[106]],[[119922,119922],"mapped",[107]],[[119923,119923],"mapped",[108]],[[119924,119924],"mapped",[109]],[[119925,119925],"mapped",[110]],[[119926,119926],"mapped",[111]],[[119927,119927],"mapped",[112]],[[119928,119928],"mapped",[113]],[[119929,119929],"mapped",[114]],[[119930,119930],"mapped",[115]],[[119931,119931],"mapped",[116]],[[119932,119932],"mapped",[117]],[[119933,119933],"mapped",[118]],[[119934,119934],"mapped",[119]],[[119935,119935],"mapped",[120]],[[119936,119936],"mapped",[121]],[[119937,119937],"mapped",[122]],[[119938,119938],"mapped",[97]],[[119939,119939],"mapped",[98]],[[119940,119940],"mapped",[99]],[[119941,119941],"mapped",[100]],[[119942,119942],"mapped",[101]],[[119943,119943],"mapped",[102]],[[119944,119944],"mapped",[103]],[[119945,119945],"mapped",[104]],[[119946,119946],"mapped",[105]],[[119947,119947],"mapped",[106]],[[119948,119948],"mapped",[107]],[[119949,119949],"mapped",[108]],[[119950,119950],"mapped",[109]],[[119951,119951],"mapped",[110]],[[119952,119952],"mapped",[111]],[[119953,119953],"mapped",[112]],[[119954,119954],"mapped",[113]],[[119955,119955],"mapped",[114]],[[119956,119956],"mapped",[115]],[[119957,119957],"mapped",[116]],[[119958,119958],"mapped",[117]],[[119959,119959],"mapped",[118]],[[119960,119960],"mapped",[119]],[[119961,119961],"mapped",[120]],[[119962,119962],"mapped",[121]],[[119963,119963],"mapped",[122]],[[119964,119964],"mapped",[97]],[[119965,119965],"disallowed"],[[119966,119966],"mapped",[99]],[[119967,119967],"mapped",[100]],[[119968,119969],"disallowed"],[[119970,119970],"mapped",[103]],[[119971,119972],"disallowed"],[[119973,119973],"mapped",[106]],[[119974,119974],"mapped",[107]],[[119975,119976],"disallowed"],[[119977,119977],"mapped",[110]],[[119978,119978],"mapped",[111]],[[119979,119979],"mapped",[112]],[[119980,119980],"mapped",[113]],[[119981,119981],"disallowed"],[[119982,119982],"mapped",[115]],[[119983,119983],"mapped",[116]],[[119984,119984],"mapped",[117]],[[119985,119985],"mapped",[118]],[[119986,119986],"mapped",[119]],[[119987,119987],"mapped",[120]],[[119988,119988],"mapped",[121]],[[119989,119989],"mapped",[122]],[[119990,119990],"mapped",[97]],[[119991,119991],"mapped",[98]],[[119992,119992],"mapped",[99]],[[119993,119993],"mapped",[100]],[[119994,119994],"disallowed"],[[119995,119995],"mapped",[102]],[[119996,119996],"disallowed"],[[119997,119997],"mapped",[104]],[[119998,119998],"mapped",[105]],[[119999,119999],"mapped",[106]],[[120000,120000],"mapped",[107]],[[120001,120001],"mapped",[108]],[[120002,120002],"mapped",[109]],[[120003,120003],"mapped",[110]],[[120004,120004],"disallowed"],[[120005,120005],"mapped",[112]],[[120006,120006],"mapped",[113]],[[120007,120007],"mapped",[114]],[[120008,120008],"mapped",[115]],[[120009,120009],"mapped",[116]],[[120010,120010],"mapped",[117]],[[120011,120011],"mapped",[118]],[[120012,120012],"mapped",[119]],[[120013,120013],"mapped",[120]],[[120014,120014],"mapped",[121]],[[120015,120015],"mapped",[122]],[[120016,120016],"mapped",[97]],[[120017,120017],"mapped",[98]],[[120018,120018],"mapped",[99]],[[120019,120019],"mapped",[100]],[[120020,120020],"mapped",[101]],[[120021,120021],"mapped",[102]],[[120022,120022],"mapped",[103]],[[120023,120023],"mapped",[104]],[[120024,120024],"mapped",[105]],[[120025,120025],"mapped",[106]],[[120026,120026],"mapped",[107]],[[120027,120027],"mapped",[108]],[[120028,120028],"mapped",[109]],[[120029,120029],"mapped",[110]],[[120030,120030],"mapped",[111]],[[120031,120031],"mapped",[112]],[[120032,120032],"mapped",[113]],[[120033,120033],"mapped",[114]],[[120034,120034],"mapped",[115]],[[120035,120035],"mapped",[116]],[[120036,120036],"mapped",[117]],[[120037,120037],"mapped",[118]],[[120038,120038],"mapped",[119]],[[120039,120039],"mapped",[120]],[[120040,120040],"mapped",[121]],[[120041,120041],"mapped",[122]],[[120042,120042],"mapped",[97]],[[120043,120043],"mapped",[98]],[[120044,120044],"mapped",[99]],[[120045,120045],"mapped",[100]],[[120046,120046],"mapped",[101]],[[120047,120047],"mapped",[102]],[[120048,120048],"mapped",[103]],[[120049,120049],"mapped",[104]],[[120050,120050],"mapped",[105]],[[120051,120051],"mapped",[106]],[[120052,120052],"mapped",[107]],[[120053,120053],"mapped",[108]],[[120054,120054],"mapped",[109]],[[120055,120055],"mapped",[110]],[[120056,120056],"mapped",[111]],[[120057,120057],"mapped",[112]],[[120058,120058],"mapped",[113]],[[120059,120059],"mapped",[114]],[[120060,120060],"mapped",[115]],[[120061,120061],"mapped",[116]],[[120062,120062],"mapped",[117]],[[120063,120063],"mapped",[118]],[[120064,120064],"mapped",[119]],[[120065,120065],"mapped",[120]],[[120066,120066],"mapped",[121]],[[120067,120067],"mapped",[122]],[[120068,120068],"mapped",[97]],[[120069,120069],"mapped",[98]],[[120070,120070],"disallowed"],[[120071,120071],"mapped",[100]],[[120072,120072],"mapped",[101]],[[120073,120073],"mapped",[102]],[[120074,120074],"mapped",[103]],[[120075,120076],"disallowed"],[[120077,120077],"mapped",[106]],[[120078,120078],"mapped",[107]],[[120079,120079],"mapped",[108]],[[120080,120080],"mapped",[109]],[[120081,120081],"mapped",[110]],[[120082,120082],"mapped",[111]],[[120083,120083],"mapped",[112]],[[120084,120084],"mapped",[113]],[[120085,120085],"disallowed"],[[120086,120086],"mapped",[115]],[[120087,120087],"mapped",[116]],[[120088,120088],"mapped",[117]],[[120089,120089],"mapped",[118]],[[120090,120090],"mapped",[119]],[[120091,120091],"mapped",[120]],[[120092,120092],"mapped",[121]],[[120093,120093],"disallowed"],[[120094,120094],"mapped",[97]],[[120095,120095],"mapped",[98]],[[120096,120096],"mapped",[99]],[[120097,120097],"mapped",[100]],[[120098,120098],"mapped",[101]],[[120099,120099],"mapped",[102]],[[120100,120100],"mapped",[103]],[[120101,120101],"mapped",[104]],[[120102,120102],"mapped",[105]],[[120103,120103],"mapped",[106]],[[120104,120104],"mapped",[107]],[[120105,120105],"mapped",[108]],[[120106,120106],"mapped",[109]],[[120107,120107],"mapped",[110]],[[120108,120108],"mapped",[111]],[[120109,120109],"mapped",[112]],[[120110,120110],"mapped",[113]],[[120111,120111],"mapped",[114]],[[120112,120112],"mapped",[115]],[[120113,120113],"mapped",[116]],[[120114,120114],"mapped",[117]],[[120115,120115],"mapped",[118]],[[120116,120116],"mapped",[119]],[[120117,120117],"mapped",[120]],[[120118,120118],"mapped",[121]],[[120119,120119],"mapped",[122]],[[120120,120120],"mapped",[97]],[[120121,120121],"mapped",[98]],[[120122,120122],"disallowed"],[[120123,120123],"mapped",[100]],[[120124,120124],"mapped",[101]],[[120125,120125],"mapped",[102]],[[120126,120126],"mapped",[103]],[[120127,120127],"disallowed"],[[120128,120128],"mapped",[105]],[[120129,120129],"mapped",[106]],[[120130,120130],"mapped",[107]],[[120131,120131],"mapped",[108]],[[120132,120132],"mapped",[109]],[[120133,120133],"disallowed"],[[120134,120134],"mapped",[111]],[[120135,120137],"disallowed"],[[120138,120138],"mapped",[115]],[[120139,120139],"mapped",[116]],[[120140,120140],"mapped",[117]],[[120141,120141],"mapped",[118]],[[120142,120142],"mapped",[119]],[[120143,120143],"mapped",[120]],[[120144,120144],"mapped",[121]],[[120145,120145],"disallowed"],[[120146,120146],"mapped",[97]],[[120147,120147],"mapped",[98]],[[120148,120148],"mapped",[99]],[[120149,120149],"mapped",[100]],[[120150,120150],"mapped",[101]],[[120151,120151],"mapped",[102]],[[120152,120152],"mapped",[103]],[[120153,120153],"mapped",[104]],[[120154,120154],"mapped",[105]],[[120155,120155],"mapped",[106]],[[120156,120156],"mapped",[107]],[[120157,120157],"mapped",[108]],[[120158,120158],"mapped",[109]],[[120159,120159],"mapped",[110]],[[120160,120160],"mapped",[111]],[[120161,120161],"mapped",[112]],[[120162,120162],"mapped",[113]],[[120163,120163],"mapped",[114]],[[120164,120164],"mapped",[115]],[[120165,120165],"mapped",[116]],[[120166,120166],"mapped",[117]],[[120167,120167],"mapped",[118]],[[120168,120168],"mapped",[119]],[[120169,120169],"mapped",[120]],[[120170,120170],"mapped",[121]],[[120171,120171],"mapped",[122]],[[120172,120172],"mapped",[97]],[[120173,120173],"mapped",[98]],[[120174,120174],"mapped",[99]],[[120175,120175],"mapped",[100]],[[120176,120176],"mapped",[101]],[[120177,120177],"mapped",[102]],[[120178,120178],"mapped",[103]],[[120179,120179],"mapped",[104]],[[120180,120180],"mapped",[105]],[[120181,120181],"mapped",[106]],[[120182,120182],"mapped",[107]],[[120183,120183],"mapped",[108]],[[120184,120184],"mapped",[109]],[[120185,120185],"mapped",[110]],[[120186,120186],"mapped",[111]],[[120187,120187],"mapped",[112]],[[120188,120188],"mapped",[113]],[[120189,120189],"mapped",[114]],[[120190,120190],"mapped",[115]],[[120191,120191],"mapped",[116]],[[120192,120192],"mapped",[117]],[[120193,120193],"mapped",[118]],[[120194,120194],"mapped",[119]],[[120195,120195],"mapped",[120]],[[120196,120196],"mapped",[121]],[[120197,120197],"mapped",[122]],[[120198,120198],"mapped",[97]],[[120199,120199],"mapped",[98]],[[120200,120200],"mapped",[99]],[[120201,120201],"mapped",[100]],[[120202,120202],"mapped",[101]],[[120203,120203],"mapped",[102]],[[120204,120204],"mapped",[103]],[[120205,120205],"mapped",[104]],[[120206,120206],"mapped",[105]],[[120207,120207],"mapped",[106]],[[120208,120208],"mapped",[107]],[[120209,120209],"mapped",[108]],[[120210,120210],"mapped",[109]],[[120211,120211],"mapped",[110]],[[120212,120212],"mapped",[111]],[[120213,120213],"mapped",[112]],[[120214,120214],"mapped",[113]],[[120215,120215],"mapped",[114]],[[120216,120216],"mapped",[115]],[[120217,120217],"mapped",[116]],[[120218,120218],"mapped",[117]],[[120219,120219],"mapped",[118]],[[120220,120220],"mapped",[119]],[[120221,120221],"mapped",[120]],[[120222,120222],"mapped",[121]],[[120223,120223],"mapped",[122]],[[120224,120224],"mapped",[97]],[[120225,120225],"mapped",[98]],[[120226,120226],"mapped",[99]],[[120227,120227],"mapped",[100]],[[120228,120228],"mapped",[101]],[[120229,120229],"mapped",[102]],[[120230,120230],"mapped",[103]],[[120231,120231],"mapped",[104]],[[120232,120232],"mapped",[105]],[[120233,120233],"mapped",[106]],[[120234,120234],"mapped",[107]],[[120235,120235],"mapped",[108]],[[120236,120236],"mapped",[109]],[[120237,120237],"mapped",[110]],[[120238,120238],"mapped",[111]],[[120239,120239],"mapped",[112]],[[120240,120240],"mapped",[113]],[[120241,120241],"mapped",[114]],[[120242,120242],"mapped",[115]],[[120243,120243],"mapped",[116]],[[120244,120244],"mapped",[117]],[[120245,120245],"mapped",[118]],[[120246,120246],"mapped",[119]],[[120247,120247],"mapped",[120]],[[120248,120248],"mapped",[121]],[[120249,120249],"mapped",[122]],[[120250,120250],"mapped",[97]],[[120251,120251],"mapped",[98]],[[120252,120252],"mapped",[99]],[[120253,120253],"mapped",[100]],[[120254,120254],"mapped",[101]],[[120255,120255],"mapped",[102]],[[120256,120256],"mapped",[103]],[[120257,120257],"mapped",[104]],[[120258,120258],"mapped",[105]],[[120259,120259],"mapped",[106]],[[120260,120260],"mapped",[107]],[[120261,120261],"mapped",[108]],[[120262,120262],"mapped",[109]],[[120263,120263],"mapped",[110]],[[120264,120264],"mapped",[111]],[[120265,120265],"mapped",[112]],[[120266,120266],"mapped",[113]],[[120267,120267],"mapped",[114]],[[120268,120268],"mapped",[115]],[[120269,120269],"mapped",[116]],[[120270,120270],"mapped",[117]],[[120271,120271],"mapped",[118]],[[120272,120272],"mapped",[119]],[[120273,120273],"mapped",[120]],[[120274,120274],"mapped",[121]],[[120275,120275],"mapped",[122]],[[120276,120276],"mapped",[97]],[[120277,120277],"mapped",[98]],[[120278,120278],"mapped",[99]],[[120279,120279],"mapped",[100]],[[120280,120280],"mapped",[101]],[[120281,120281],"mapped",[102]],[[120282,120282],"mapped",[103]],[[120283,120283],"mapped",[104]],[[120284,120284],"mapped",[105]],[[120285,120285],"mapped",[106]],[[120286,120286],"mapped",[107]],[[120287,120287],"mapped",[108]],[[120288,120288],"mapped",[109]],[[120289,120289],"mapped",[110]],[[120290,120290],"mapped",[111]],[[120291,120291],"mapped",[112]],[[120292,120292],"mapped",[113]],[[120293,120293],"mapped",[114]],[[120294,120294],"mapped",[115]],[[120295,120295],"mapped",[116]],[[120296,120296],"mapped",[117]],[[120297,120297],"mapped",[118]],[[120298,120298],"mapped",[119]],[[120299,120299],"mapped",[120]],[[120300,120300],"mapped",[121]],[[120301,120301],"mapped",[122]],[[120302,120302],"mapped",[97]],[[120303,120303],"mapped",[98]],[[120304,120304],"mapped",[99]],[[120305,120305],"mapped",[100]],[[120306,120306],"mapped",[101]],[[120307,120307],"mapped",[102]],[[120308,120308],"mapped",[103]],[[120309,120309],"mapped",[104]],[[120310,120310],"mapped",[105]],[[120311,120311],"mapped",[106]],[[120312,120312],"mapped",[107]],[[120313,120313],"mapped",[108]],[[120314,120314],"mapped",[109]],[[120315,120315],"mapped",[110]],[[120316,120316],"mapped",[111]],[[120317,120317],"mapped",[112]],[[120318,120318],"mapped",[113]],[[120319,120319],"mapped",[114]],[[120320,120320],"mapped",[115]],[[120321,120321],"mapped",[116]],[[120322,120322],"mapped",[117]],[[120323,120323],"mapped",[118]],[[120324,120324],"mapped",[119]],[[120325,120325],"mapped",[120]],[[120326,120326],"mapped",[121]],[[120327,120327],"mapped",[122]],[[120328,120328],"mapped",[97]],[[120329,120329],"mapped",[98]],[[120330,120330],"mapped",[99]],[[120331,120331],"mapped",[100]],[[120332,120332],"mapped",[101]],[[120333,120333],"mapped",[102]],[[120334,120334],"mapped",[103]],[[120335,120335],"mapped",[104]],[[120336,120336],"mapped",[105]],[[120337,120337],"mapped",[106]],[[120338,120338],"mapped",[107]],[[120339,120339],"mapped",[108]],[[120340,120340],"mapped",[109]],[[120341,120341],"mapped",[110]],[[120342,120342],"mapped",[111]],[[120343,120343],"mapped",[112]],[[120344,120344],"mapped",[113]],[[120345,120345],"mapped",[114]],[[120346,120346],"mapped",[115]],[[120347,120347],"mapped",[116]],[[120348,120348],"mapped",[117]],[[120349,120349],"mapped",[118]],[[120350,120350],"mapped",[119]],[[120351,120351],"mapped",[120]],[[120352,120352],"mapped",[121]],[[120353,120353],"mapped",[122]],[[120354,120354],"mapped",[97]],[[120355,120355],"mapped",[98]],[[120356,120356],"mapped",[99]],[[120357,120357],"mapped",[100]],[[120358,120358],"mapped",[101]],[[120359,120359],"mapped",[102]],[[120360,120360],"mapped",[103]],[[120361,120361],"mapped",[104]],[[120362,120362],"mapped",[105]],[[120363,120363],"mapped",[106]],[[120364,120364],"mapped",[107]],[[120365,120365],"mapped",[108]],[[120366,120366],"mapped",[109]],[[120367,120367],"mapped",[110]],[[120368,120368],"mapped",[111]],[[120369,120369],"mapped",[112]],[[120370,120370],"mapped",[113]],[[120371,120371],"mapped",[114]],[[120372,120372],"mapped",[115]],[[120373,120373],"mapped",[116]],[[120374,120374],"mapped",[117]],[[120375,120375],"mapped",[118]],[[120376,120376],"mapped",[119]],[[120377,120377],"mapped",[120]],[[120378,120378],"mapped",[121]],[[120379,120379],"mapped",[122]],[[120380,120380],"mapped",[97]],[[120381,120381],"mapped",[98]],[[120382,120382],"mapped",[99]],[[120383,120383],"mapped",[100]],[[120384,120384],"mapped",[101]],[[120385,120385],"mapped",[102]],[[120386,120386],"mapped",[103]],[[120387,120387],"mapped",[104]],[[120388,120388],"mapped",[105]],[[120389,120389],"mapped",[106]],[[120390,120390],"mapped",[107]],[[120391,120391],"mapped",[108]],[[120392,120392],"mapped",[109]],[[120393,120393],"mapped",[110]],[[120394,120394],"mapped",[111]],[[120395,120395],"mapped",[112]],[[120396,120396],"mapped",[113]],[[120397,120397],"mapped",[114]],[[120398,120398],"mapped",[115]],[[120399,120399],"mapped",[116]],[[120400,120400],"mapped",[117]],[[120401,120401],"mapped",[118]],[[120402,120402],"mapped",[119]],[[120403,120403],"mapped",[120]],[[120404,120404],"mapped",[121]],[[120405,120405],"mapped",[122]],[[120406,120406],"mapped",[97]],[[120407,120407],"mapped",[98]],[[120408,120408],"mapped",[99]],[[120409,120409],"mapped",[100]],[[120410,120410],"mapped",[101]],[[120411,120411],"mapped",[102]],[[120412,120412],"mapped",[103]],[[120413,120413],"mapped",[104]],[[120414,120414],"mapped",[105]],[[120415,120415],"mapped",[106]],[[120416,120416],"mapped",[107]],[[120417,120417],"mapped",[108]],[[120418,120418],"mapped",[109]],[[120419,120419],"mapped",[110]],[[120420,120420],"mapped",[111]],[[120421,120421],"mapped",[112]],[[120422,120422],"mapped",[113]],[[120423,120423],"mapped",[114]],[[120424,120424],"mapped",[115]],[[120425,120425],"mapped",[116]],[[120426,120426],"mapped",[117]],[[120427,120427],"mapped",[118]],[[120428,120428],"mapped",[119]],[[120429,120429],"mapped",[120]],[[120430,120430],"mapped",[121]],[[120431,120431],"mapped",[122]],[[120432,120432],"mapped",[97]],[[120433,120433],"mapped",[98]],[[120434,120434],"mapped",[99]],[[120435,120435],"mapped",[100]],[[120436,120436],"mapped",[101]],[[120437,120437],"mapped",[102]],[[120438,120438],"mapped",[103]],[[120439,120439],"mapped",[104]],[[120440,120440],"mapped",[105]],[[120441,120441],"mapped",[106]],[[120442,120442],"mapped",[107]],[[120443,120443],"mapped",[108]],[[120444,120444],"mapped",[109]],[[120445,120445],"mapped",[110]],[[120446,120446],"mapped",[111]],[[120447,120447],"mapped",[112]],[[120448,120448],"mapped",[113]],[[120449,120449],"mapped",[114]],[[120450,120450],"mapped",[115]],[[120451,120451],"mapped",[116]],[[120452,120452],"mapped",[117]],[[120453,120453],"mapped",[118]],[[120454,120454],"mapped",[119]],[[120455,120455],"mapped",[120]],[[120456,120456],"mapped",[121]],[[120457,120457],"mapped",[122]],[[120458,120458],"mapped",[97]],[[120459,120459],"mapped",[98]],[[120460,120460],"mapped",[99]],[[120461,120461],"mapped",[100]],[[120462,120462],"mapped",[101]],[[120463,120463],"mapped",[102]],[[120464,120464],"mapped",[103]],[[120465,120465],"mapped",[104]],[[120466,120466],"mapped",[105]],[[120467,120467],"mapped",[106]],[[120468,120468],"mapped",[107]],[[120469,120469],"mapped",[108]],[[120470,120470],"mapped",[109]],[[120471,120471],"mapped",[110]],[[120472,120472],"mapped",[111]],[[120473,120473],"mapped",[112]],[[120474,120474],"mapped",[113]],[[120475,120475],"mapped",[114]],[[120476,120476],"mapped",[115]],[[120477,120477],"mapped",[116]],[[120478,120478],"mapped",[117]],[[120479,120479],"mapped",[118]],[[120480,120480],"mapped",[119]],[[120481,120481],"mapped",[120]],[[120482,120482],"mapped",[121]],[[120483,120483],"mapped",[122]],[[120484,120484],"mapped",[305]],[[120485,120485],"mapped",[567]],[[120486,120487],"disallowed"],[[120488,120488],"mapped",[945]],[[120489,120489],"mapped",[946]],[[120490,120490],"mapped",[947]],[[120491,120491],"mapped",[948]],[[120492,120492],"mapped",[949]],[[120493,120493],"mapped",[950]],[[120494,120494],"mapped",[951]],[[120495,120495],"mapped",[952]],[[120496,120496],"mapped",[953]],[[120497,120497],"mapped",[954]],[[120498,120498],"mapped",[955]],[[120499,120499],"mapped",[956]],[[120500,120500],"mapped",[957]],[[120501,120501],"mapped",[958]],[[120502,120502],"mapped",[959]],[[120503,120503],"mapped",[960]],[[120504,120504],"mapped",[961]],[[120505,120505],"mapped",[952]],[[120506,120506],"mapped",[963]],[[120507,120507],"mapped",[964]],[[120508,120508],"mapped",[965]],[[120509,120509],"mapped",[966]],[[120510,120510],"mapped",[967]],[[120511,120511],"mapped",[968]],[[120512,120512],"mapped",[969]],[[120513,120513],"mapped",[8711]],[[120514,120514],"mapped",[945]],[[120515,120515],"mapped",[946]],[[120516,120516],"mapped",[947]],[[120517,120517],"mapped",[948]],[[120518,120518],"mapped",[949]],[[120519,120519],"mapped",[950]],[[120520,120520],"mapped",[951]],[[120521,120521],"mapped",[952]],[[120522,120522],"mapped",[953]],[[120523,120523],"mapped",[954]],[[120524,120524],"mapped",[955]],[[120525,120525],"mapped",[956]],[[120526,120526],"mapped",[957]],[[120527,120527],"mapped",[958]],[[120528,120528],"mapped",[959]],[[120529,120529],"mapped",[960]],[[120530,120530],"mapped",[961]],[[120531,120532],"mapped",[963]],[[120533,120533],"mapped",[964]],[[120534,120534],"mapped",[965]],[[120535,120535],"mapped",[966]],[[120536,120536],"mapped",[967]],[[120537,120537],"mapped",[968]],[[120538,120538],"mapped",[969]],[[120539,120539],"mapped",[8706]],[[120540,120540],"mapped",[949]],[[120541,120541],"mapped",[952]],[[120542,120542],"mapped",[954]],[[120543,120543],"mapped",[966]],[[120544,120544],"mapped",[961]],[[120545,120545],"mapped",[960]],[[120546,120546],"mapped",[945]],[[120547,120547],"mapped",[946]],[[120548,120548],"mapped",[947]],[[120549,120549],"mapped",[948]],[[120550,120550],"mapped",[949]],[[120551,120551],"mapped",[950]],[[120552,120552],"mapped",[951]],[[120553,120553],"mapped",[952]],[[120554,120554],"mapped",[953]],[[120555,120555],"mapped",[954]],[[120556,120556],"mapped",[955]],[[120557,120557],"mapped",[956]],[[120558,120558],"mapped",[957]],[[120559,120559],"mapped",[958]],[[120560,120560],"mapped",[959]],[[120561,120561],"mapped",[960]],[[120562,120562],"mapped",[961]],[[120563,120563],"mapped",[952]],[[120564,120564],"mapped",[963]],[[120565,120565],"mapped",[964]],[[120566,120566],"mapped",[965]],[[120567,120567],"mapped",[966]],[[120568,120568],"mapped",[967]],[[120569,120569],"mapped",[968]],[[120570,120570],"mapped",[969]],[[120571,120571],"mapped",[8711]],[[120572,120572],"mapped",[945]],[[120573,120573],"mapped",[946]],[[120574,120574],"mapped",[947]],[[120575,120575],"mapped",[948]],[[120576,120576],"mapped",[949]],[[120577,120577],"mapped",[950]],[[120578,120578],"mapped",[951]],[[120579,120579],"mapped",[952]],[[120580,120580],"mapped",[953]],[[120581,120581],"mapped",[954]],[[120582,120582],"mapped",[955]],[[120583,120583],"mapped",[956]],[[120584,120584],"mapped",[957]],[[120585,120585],"mapped",[958]],[[120586,120586],"mapped",[959]],[[120587,120587],"mapped",[960]],[[120588,120588],"mapped",[961]],[[120589,120590],"mapped",[963]],[[120591,120591],"mapped",[964]],[[120592,120592],"mapped",[965]],[[120593,120593],"mapped",[966]],[[120594,120594],"mapped",[967]],[[120595,120595],"mapped",[968]],[[120596,120596],"mapped",[969]],[[120597,120597],"mapped",[8706]],[[120598,120598],"mapped",[949]],[[120599,120599],"mapped",[952]],[[120600,120600],"mapped",[954]],[[120601,120601],"mapped",[966]],[[120602,120602],"mapped",[961]],[[120603,120603],"mapped",[960]],[[120604,120604],"mapped",[945]],[[120605,120605],"mapped",[946]],[[120606,120606],"mapped",[947]],[[120607,120607],"mapped",[948]],[[120608,120608],"mapped",[949]],[[120609,120609],"mapped",[950]],[[120610,120610],"mapped",[951]],[[120611,120611],"mapped",[952]],[[120612,120612],"mapped",[953]],[[120613,120613],"mapped",[954]],[[120614,120614],"mapped",[955]],[[120615,120615],"mapped",[956]],[[120616,120616],"mapped",[957]],[[120617,120617],"mapped",[958]],[[120618,120618],"mapped",[959]],[[120619,120619],"mapped",[960]],[[120620,120620],"mapped",[961]],[[120621,120621],"mapped",[952]],[[120622,120622],"mapped",[963]],[[120623,120623],"mapped",[964]],[[120624,120624],"mapped",[965]],[[120625,120625],"mapped",[966]],[[120626,120626],"mapped",[967]],[[120627,120627],"mapped",[968]],[[120628,120628],"mapped",[969]],[[120629,120629],"mapped",[8711]],[[120630,120630],"mapped",[945]],[[120631,120631],"mapped",[946]],[[120632,120632],"mapped",[947]],[[120633,120633],"mapped",[948]],[[120634,120634],"mapped",[949]],[[120635,120635],"mapped",[950]],[[120636,120636],"mapped",[951]],[[120637,120637],"mapped",[952]],[[120638,120638],"mapped",[953]],[[120639,120639],"mapped",[954]],[[120640,120640],"mapped",[955]],[[120641,120641],"mapped",[956]],[[120642,120642],"mapped",[957]],[[120643,120643],"mapped",[958]],[[120644,120644],"mapped",[959]],[[120645,120645],"mapped",[960]],[[120646,120646],"mapped",[961]],[[120647,120648],"mapped",[963]],[[120649,120649],"mapped",[964]],[[120650,120650],"mapped",[965]],[[120651,120651],"mapped",[966]],[[120652,120652],"mapped",[967]],[[120653,120653],"mapped",[968]],[[120654,120654],"mapped",[969]],[[120655,120655],"mapped",[8706]],[[120656,120656],"mapped",[949]],[[120657,120657],"mapped",[952]],[[120658,120658],"mapped",[954]],[[120659,120659],"mapped",[966]],[[120660,120660],"mapped",[961]],[[120661,120661],"mapped",[960]],[[120662,120662],"mapped",[945]],[[120663,120663],"mapped",[946]],[[120664,120664],"mapped",[947]],[[120665,120665],"mapped",[948]],[[120666,120666],"mapped",[949]],[[120667,120667],"mapped",[950]],[[120668,120668],"mapped",[951]],[[120669,120669],"mapped",[952]],[[120670,120670],"mapped",[953]],[[120671,120671],"mapped",[954]],[[120672,120672],"mapped",[955]],[[120673,120673],"mapped",[956]],[[120674,120674],"mapped",[957]],[[120675,120675],"mapped",[958]],[[120676,120676],"mapped",[959]],[[120677,120677],"mapped",[960]],[[120678,120678],"mapped",[961]],[[120679,120679],"mapped",[952]],[[120680,120680],"mapped",[963]],[[120681,120681],"mapped",[964]],[[120682,120682],"mapped",[965]],[[120683,120683],"mapped",[966]],[[120684,120684],"mapped",[967]],[[120685,120685],"mapped",[968]],[[120686,120686],"mapped",[969]],[[120687,120687],"mapped",[8711]],[[120688,120688],"mapped",[945]],[[120689,120689],"mapped",[946]],[[120690,120690],"mapped",[947]],[[120691,120691],"mapped",[948]],[[120692,120692],"mapped",[949]],[[120693,120693],"mapped",[950]],[[120694,120694],"mapped",[951]],[[120695,120695],"mapped",[952]],[[120696,120696],"mapped",[953]],[[120697,120697],"mapped",[954]],[[120698,120698],"mapped",[955]],[[120699,120699],"mapped",[956]],[[120700,120700],"mapped",[957]],[[120701,120701],"mapped",[958]],[[120702,120702],"mapped",[959]],[[120703,120703],"mapped",[960]],[[120704,120704],"mapped",[961]],[[120705,120706],"mapped",[963]],[[120707,120707],"mapped",[964]],[[120708,120708],"mapped",[965]],[[120709,120709],"mapped",[966]],[[120710,120710],"mapped",[967]],[[120711,120711],"mapped",[968]],[[120712,120712],"mapped",[969]],[[120713,120713],"mapped",[8706]],[[120714,120714],"mapped",[949]],[[120715,120715],"mapped",[952]],[[120716,120716],"mapped",[954]],[[120717,120717],"mapped",[966]],[[120718,120718],"mapped",[961]],[[120719,120719],"mapped",[960]],[[120720,120720],"mapped",[945]],[[120721,120721],"mapped",[946]],[[120722,120722],"mapped",[947]],[[120723,120723],"mapped",[948]],[[120724,120724],"mapped",[949]],[[120725,120725],"mapped",[950]],[[120726,120726],"mapped",[951]],[[120727,120727],"mapped",[952]],[[120728,120728],"mapped",[953]],[[120729,120729],"mapped",[954]],[[120730,120730],"mapped",[955]],[[120731,120731],"mapped",[956]],[[120732,120732],"mapped",[957]],[[120733,120733],"mapped",[958]],[[120734,120734],"mapped",[959]],[[120735,120735],"mapped",[960]],[[120736,120736],"mapped",[961]],[[120737,120737],"mapped",[952]],[[120738,120738],"mapped",[963]],[[120739,120739],"mapped",[964]],[[120740,120740],"mapped",[965]],[[120741,120741],"mapped",[966]],[[120742,120742],"mapped",[967]],[[120743,120743],"mapped",[968]],[[120744,120744],"mapped",[969]],[[120745,120745],"mapped",[8711]],[[120746,120746],"mapped",[945]],[[120747,120747],"mapped",[946]],[[120748,120748],"mapped",[947]],[[120749,120749],"mapped",[948]],[[120750,120750],"mapped",[949]],[[120751,120751],"mapped",[950]],[[120752,120752],"mapped",[951]],[[120753,120753],"mapped",[952]],[[120754,120754],"mapped",[953]],[[120755,120755],"mapped",[954]],[[120756,120756],"mapped",[955]],[[120757,120757],"mapped",[956]],[[120758,120758],"mapped",[957]],[[120759,120759],"mapped",[958]],[[120760,120760],"mapped",[959]],[[120761,120761],"mapped",[960]],[[120762,120762],"mapped",[961]],[[120763,120764],"mapped",[963]],[[120765,120765],"mapped",[964]],[[120766,120766],"mapped",[965]],[[120767,120767],"mapped",[966]],[[120768,120768],"mapped",[967]],[[120769,120769],"mapped",[968]],[[120770,120770],"mapped",[969]],[[120771,120771],"mapped",[8706]],[[120772,120772],"mapped",[949]],[[120773,120773],"mapped",[952]],[[120774,120774],"mapped",[954]],[[120775,120775],"mapped",[966]],[[120776,120776],"mapped",[961]],[[120777,120777],"mapped",[960]],[[120778,120779],"mapped",[989]],[[120780,120781],"disallowed"],[[120782,120782],"mapped",[48]],[[120783,120783],"mapped",[49]],[[120784,120784],"mapped",[50]],[[120785,120785],"mapped",[51]],[[120786,120786],"mapped",[52]],[[120787,120787],"mapped",[53]],[[120788,120788],"mapped",[54]],[[120789,120789],"mapped",[55]],[[120790,120790],"mapped",[56]],[[120791,120791],"mapped",[57]],[[120792,120792],"mapped",[48]],[[120793,120793],"mapped",[49]],[[120794,120794],"mapped",[50]],[[120795,120795],"mapped",[51]],[[120796,120796],"mapped",[52]],[[120797,120797],"mapped",[53]],[[120798,120798],"mapped",[54]],[[120799,120799],"mapped",[55]],[[120800,120800],"mapped",[56]],[[120801,120801],"mapped",[57]],[[120802,120802],"mapped",[48]],[[120803,120803],"mapped",[49]],[[120804,120804],"mapped",[50]],[[120805,120805],"mapped",[51]],[[120806,120806],"mapped",[52]],[[120807,120807],"mapped",[53]],[[120808,120808],"mapped",[54]],[[120809,120809],"mapped",[55]],[[120810,120810],"mapped",[56]],[[120811,120811],"mapped",[57]],[[120812,120812],"mapped",[48]],[[120813,120813],"mapped",[49]],[[120814,120814],"mapped",[50]],[[120815,120815],"mapped",[51]],[[120816,120816],"mapped",[52]],[[120817,120817],"mapped",[53]],[[120818,120818],"mapped",[54]],[[120819,120819],"mapped",[55]],[[120820,120820],"mapped",[56]],[[120821,120821],"mapped",[57]],[[120822,120822],"mapped",[48]],[[120823,120823],"mapped",[49]],[[120824,120824],"mapped",[50]],[[120825,120825],"mapped",[51]],[[120826,120826],"mapped",[52]],[[120827,120827],"mapped",[53]],[[120828,120828],"mapped",[54]],[[120829,120829],"mapped",[55]],[[120830,120830],"mapped",[56]],[[120831,120831],"mapped",[57]],[[120832,121343],"valid",[],"NV8"],[[121344,121398],"valid"],[[121399,121402],"valid",[],"NV8"],[[121403,121452],"valid"],[[121453,121460],"valid",[],"NV8"],[[121461,121461],"valid"],[[121462,121475],"valid",[],"NV8"],[[121476,121476],"valid"],[[121477,121483],"valid",[],"NV8"],[[121484,121498],"disallowed"],[[121499,121503],"valid"],[[121504,121504],"disallowed"],[[121505,121519],"valid"],[[121520,124927],"disallowed"],[[124928,125124],"valid"],[[125125,125126],"disallowed"],[[125127,125135],"valid",[],"NV8"],[[125136,125142],"valid"],[[125143,126463],"disallowed"],[[126464,126464],"mapped",[1575]],[[126465,126465],"mapped",[1576]],[[126466,126466],"mapped",[1580]],[[126467,126467],"mapped",[1583]],[[126468,126468],"disallowed"],[[126469,126469],"mapped",[1608]],[[126470,126470],"mapped",[1586]],[[126471,126471],"mapped",[1581]],[[126472,126472],"mapped",[1591]],[[126473,126473],"mapped",[1610]],[[126474,126474],"mapped",[1603]],[[126475,126475],"mapped",[1604]],[[126476,126476],"mapped",[1605]],[[126477,126477],"mapped",[1606]],[[126478,126478],"mapped",[1587]],[[126479,126479],"mapped",[1593]],[[126480,126480],"mapped",[1601]],[[126481,126481],"mapped",[1589]],[[126482,126482],"mapped",[1602]],[[126483,126483],"mapped",[1585]],[[126484,126484],"mapped",[1588]],[[126485,126485],"mapped",[1578]],[[126486,126486],"mapped",[1579]],[[126487,126487],"mapped",[1582]],[[126488,126488],"mapped",[1584]],[[126489,126489],"mapped",[1590]],[[126490,126490],"mapped",[1592]],[[126491,126491],"mapped",[1594]],[[126492,126492],"mapped",[1646]],[[126493,126493],"mapped",[1722]],[[126494,126494],"mapped",[1697]],[[126495,126495],"mapped",[1647]],[[126496,126496],"disallowed"],[[126497,126497],"mapped",[1576]],[[126498,126498],"mapped",[1580]],[[126499,126499],"disallowed"],[[126500,126500],"mapped",[1607]],[[126501,126502],"disallowed"],[[126503,126503],"mapped",[1581]],[[126504,126504],"disallowed"],[[126505,126505],"mapped",[1610]],[[126506,126506],"mapped",[1603]],[[126507,126507],"mapped",[1604]],[[126508,126508],"mapped",[1605]],[[126509,126509],"mapped",[1606]],[[126510,126510],"mapped",[1587]],[[126511,126511],"mapped",[1593]],[[126512,126512],"mapped",[1601]],[[126513,126513],"mapped",[1589]],[[126514,126514],"mapped",[1602]],[[126515,126515],"disallowed"],[[126516,126516],"mapped",[1588]],[[126517,126517],"mapped",[1578]],[[126518,126518],"mapped",[1579]],[[126519,126519],"mapped",[1582]],[[126520,126520],"disallowed"],[[126521,126521],"mapped",[1590]],[[126522,126522],"disallowed"],[[126523,126523],"mapped",[1594]],[[126524,126529],"disallowed"],[[126530,126530],"mapped",[1580]],[[126531,126534],"disallowed"],[[126535,126535],"mapped",[1581]],[[126536,126536],"disallowed"],[[126537,126537],"mapped",[1610]],[[126538,126538],"disallowed"],[[126539,126539],"mapped",[1604]],[[126540,126540],"disallowed"],[[126541,126541],"mapped",[1606]],[[126542,126542],"mapped",[1587]],[[126543,126543],"mapped",[1593]],[[126544,126544],"disallowed"],[[126545,126545],"mapped",[1589]],[[126546,126546],"mapped",[1602]],[[126547,126547],"disallowed"],[[126548,126548],"mapped",[1588]],[[126549,126550],"disallowed"],[[126551,126551],"mapped",[1582]],[[126552,126552],"disallowed"],[[126553,126553],"mapped",[1590]],[[126554,126554],"disallowed"],[[126555,126555],"mapped",[1594]],[[126556,126556],"disallowed"],[[126557,126557],"mapped",[1722]],[[126558,126558],"disallowed"],[[126559,126559],"mapped",[1647]],[[126560,126560],"disallowed"],[[126561,126561],"mapped",[1576]],[[126562,126562],"mapped",[1580]],[[126563,126563],"disallowed"],[[126564,126564],"mapped",[1607]],[[126565,126566],"disallowed"],[[126567,126567],"mapped",[1581]],[[126568,126568],"mapped",[1591]],[[126569,126569],"mapped",[1610]],[[126570,126570],"mapped",[1603]],[[126571,126571],"disallowed"],[[126572,126572],"mapped",[1605]],[[126573,126573],"mapped",[1606]],[[126574,126574],"mapped",[1587]],[[126575,126575],"mapped",[1593]],[[126576,126576],"mapped",[1601]],[[126577,126577],"mapped",[1589]],[[126578,126578],"mapped",[1602]],[[126579,126579],"disallowed"],[[126580,126580],"mapped",[1588]],[[126581,126581],"mapped",[1578]],[[126582,126582],"mapped",[1579]],[[126583,126583],"mapped",[1582]],[[126584,126584],"disallowed"],[[126585,126585],"mapped",[1590]],[[126586,126586],"mapped",[1592]],[[126587,126587],"mapped",[1594]],[[126588,126588],"mapped",[1646]],[[126589,126589],"disallowed"],[[126590,126590],"mapped",[1697]],[[126591,126591],"disallowed"],[[126592,126592],"mapped",[1575]],[[126593,126593],"mapped",[1576]],[[126594,126594],"mapped",[1580]],[[126595,126595],"mapped",[1583]],[[126596,126596],"mapped",[1607]],[[126597,126597],"mapped",[1608]],[[126598,126598],"mapped",[1586]],[[126599,126599],"mapped",[1581]],[[126600,126600],"mapped",[1591]],[[126601,126601],"mapped",[1610]],[[126602,126602],"disallowed"],[[126603,126603],"mapped",[1604]],[[126604,126604],"mapped",[1605]],[[126605,126605],"mapped",[1606]],[[126606,126606],"mapped",[1587]],[[126607,126607],"mapped",[1593]],[[126608,126608],"mapped",[1601]],[[126609,126609],"mapped",[1589]],[[126610,126610],"mapped",[1602]],[[126611,126611],"mapped",[1585]],[[126612,126612],"mapped",[1588]],[[126613,126613],"mapped",[1578]],[[126614,126614],"mapped",[1579]],[[126615,126615],"mapped",[1582]],[[126616,126616],"mapped",[1584]],[[126617,126617],"mapped",[1590]],[[126618,126618],"mapped",[1592]],[[126619,126619],"mapped",[1594]],[[126620,126624],"disallowed"],[[126625,126625],"mapped",[1576]],[[126626,126626],"mapped",[1580]],[[126627,126627],"mapped",[1583]],[[126628,126628],"disallowed"],[[126629,126629],"mapped",[1608]],[[126630,126630],"mapped",[1586]],[[126631,126631],"mapped",[1581]],[[126632,126632],"mapped",[1591]],[[126633,126633],"mapped",[1610]],[[126634,126634],"disallowed"],[[126635,126635],"mapped",[1604]],[[126636,126636],"mapped",[1605]],[[126637,126637],"mapped",[1606]],[[126638,126638],"mapped",[1587]],[[126639,126639],"mapped",[1593]],[[126640,126640],"mapped",[1601]],[[126641,126641],"mapped",[1589]],[[126642,126642],"mapped",[1602]],[[126643,126643],"mapped",[1585]],[[126644,126644],"mapped",[1588]],[[126645,126645],"mapped",[1578]],[[126646,126646],"mapped",[1579]],[[126647,126647],"mapped",[1582]],[[126648,126648],"mapped",[1584]],[[126649,126649],"mapped",[1590]],[[126650,126650],"mapped",[1592]],[[126651,126651],"mapped",[1594]],[[126652,126703],"disallowed"],[[126704,126705],"valid",[],"NV8"],[[126706,126975],"disallowed"],[[126976,127019],"valid",[],"NV8"],[[127020,127023],"disallowed"],[[127024,127123],"valid",[],"NV8"],[[127124,127135],"disallowed"],[[127136,127150],"valid",[],"NV8"],[[127151,127152],"disallowed"],[[127153,127166],"valid",[],"NV8"],[[127167,127167],"valid",[],"NV8"],[[127168,127168],"disallowed"],[[127169,127183],"valid",[],"NV8"],[[127184,127184],"disallowed"],[[127185,127199],"valid",[],"NV8"],[[127200,127221],"valid",[],"NV8"],[[127222,127231],"disallowed"],[[127232,127232],"disallowed"],[[127233,127233],"disallowed_STD3_mapped",[48,44]],[[127234,127234],"disallowed_STD3_mapped",[49,44]],[[127235,127235],"disallowed_STD3_mapped",[50,44]],[[127236,127236],"disallowed_STD3_mapped",[51,44]],[[127237,127237],"disallowed_STD3_mapped",[52,44]],[[127238,127238],"disallowed_STD3_mapped",[53,44]],[[127239,127239],"disallowed_STD3_mapped",[54,44]],[[127240,127240],"disallowed_STD3_mapped",[55,44]],[[127241,127241],"disallowed_STD3_mapped",[56,44]],[[127242,127242],"disallowed_STD3_mapped",[57,44]],[[127243,127244],"valid",[],"NV8"],[[127245,127247],"disallowed"],[[127248,127248],"disallowed_STD3_mapped",[40,97,41]],[[127249,127249],"disallowed_STD3_mapped",[40,98,41]],[[127250,127250],"disallowed_STD3_mapped",[40,99,41]],[[127251,127251],"disallowed_STD3_mapped",[40,100,41]],[[127252,127252],"disallowed_STD3_mapped",[40,101,41]],[[127253,127253],"disallowed_STD3_mapped",[40,102,41]],[[127254,127254],"disallowed_STD3_mapped",[40,103,41]],[[127255,127255],"disallowed_STD3_mapped",[40,104,41]],[[127256,127256],"disallowed_STD3_mapped",[40,105,41]],[[127257,127257],"disallowed_STD3_mapped",[40,106,41]],[[127258,127258],"disallowed_STD3_mapped",[40,107,41]],[[127259,127259],"disallowed_STD3_mapped",[40,108,41]],[[127260,127260],"disallowed_STD3_mapped",[40,109,41]],[[127261,127261],"disallowed_STD3_mapped",[40,110,41]],[[127262,127262],"disallowed_STD3_mapped",[40,111,41]],[[127263,127263],"disallowed_STD3_mapped",[40,112,41]],[[127264,127264],"disallowed_STD3_mapped",[40,113,41]],[[127265,127265],"disallowed_STD3_mapped",[40,114,41]],[[127266,127266],"disallowed_STD3_mapped",[40,115,41]],[[127267,127267],"disallowed_STD3_mapped",[40,116,41]],[[127268,127268],"disallowed_STD3_mapped",[40,117,41]],[[127269,127269],"disallowed_STD3_mapped",[40,118,41]],[[127270,127270],"disallowed_STD3_mapped",[40,119,41]],[[127271,127271],"disallowed_STD3_mapped",[40,120,41]],[[127272,127272],"disallowed_STD3_mapped",[40,121,41]],[[127273,127273],"disallowed_STD3_mapped",[40,122,41]],[[127274,127274],"mapped",[12308,115,12309]],[[127275,127275],"mapped",[99]],[[127276,127276],"mapped",[114]],[[127277,127277],"mapped",[99,100]],[[127278,127278],"mapped",[119,122]],[[127279,127279],"disallowed"],[[127280,127280],"mapped",[97]],[[127281,127281],"mapped",[98]],[[127282,127282],"mapped",[99]],[[127283,127283],"mapped",[100]],[[127284,127284],"mapped",[101]],[[127285,127285],"mapped",[102]],[[127286,127286],"mapped",[103]],[[127287,127287],"mapped",[104]],[[127288,127288],"mapped",[105]],[[127289,127289],"mapped",[106]],[[127290,127290],"mapped",[107]],[[127291,127291],"mapped",[108]],[[127292,127292],"mapped",[109]],[[127293,127293],"mapped",[110]],[[127294,127294],"mapped",[111]],[[127295,127295],"mapped",[112]],[[127296,127296],"mapped",[113]],[[127297,127297],"mapped",[114]],[[127298,127298],"mapped",[115]],[[127299,127299],"mapped",[116]],[[127300,127300],"mapped",[117]],[[127301,127301],"mapped",[118]],[[127302,127302],"mapped",[119]],[[127303,127303],"mapped",[120]],[[127304,127304],"mapped",[121]],[[127305,127305],"mapped",[122]],[[127306,127306],"mapped",[104,118]],[[127307,127307],"mapped",[109,118]],[[127308,127308],"mapped",[115,100]],[[127309,127309],"mapped",[115,115]],[[127310,127310],"mapped",[112,112,118]],[[127311,127311],"mapped",[119,99]],[[127312,127318],"valid",[],"NV8"],[[127319,127319],"valid",[],"NV8"],[[127320,127326],"valid",[],"NV8"],[[127327,127327],"valid",[],"NV8"],[[127328,127337],"valid",[],"NV8"],[[127338,127338],"mapped",[109,99]],[[127339,127339],"mapped",[109,100]],[[127340,127343],"disallowed"],[[127344,127352],"valid",[],"NV8"],[[127353,127353],"valid",[],"NV8"],[[127354,127354],"valid",[],"NV8"],[[127355,127356],"valid",[],"NV8"],[[127357,127358],"valid",[],"NV8"],[[127359,127359],"valid",[],"NV8"],[[127360,127369],"valid",[],"NV8"],[[127370,127373],"valid",[],"NV8"],[[127374,127375],"valid",[],"NV8"],[[127376,127376],"mapped",[100,106]],[[127377,127386],"valid",[],"NV8"],[[127387,127461],"disallowed"],[[127462,127487],"valid",[],"NV8"],[[127488,127488],"mapped",[12411,12363]],[[127489,127489],"mapped",[12467,12467]],[[127490,127490],"mapped",[12469]],[[127491,127503],"disallowed"],[[127504,127504],"mapped",[25163]],[[127505,127505],"mapped",[23383]],[[127506,127506],"mapped",[21452]],[[127507,127507],"mapped",[12487]],[[127508,127508],"mapped",[20108]],[[127509,127509],"mapped",[22810]],[[127510,127510],"mapped",[35299]],[[127511,127511],"mapped",[22825]],[[127512,127512],"mapped",[20132]],[[127513,127513],"mapped",[26144]],[[127514,127514],"mapped",[28961]],[[127515,127515],"mapped",[26009]],[[127516,127516],"mapped",[21069]],[[127517,127517],"mapped",[24460]],[[127518,127518],"mapped",[20877]],[[127519,127519],"mapped",[26032]],[[127520,127520],"mapped",[21021]],[[127521,127521],"mapped",[32066]],[[127522,127522],"mapped",[29983]],[[127523,127523],"mapped",[36009]],[[127524,127524],"mapped",[22768]],[[127525,127525],"mapped",[21561]],[[127526,127526],"mapped",[28436]],[[127527,127527],"mapped",[25237]],[[127528,127528],"mapped",[25429]],[[127529,127529],"mapped",[19968]],[[127530,127530],"mapped",[19977]],[[127531,127531],"mapped",[36938]],[[127532,127532],"mapped",[24038]],[[127533,127533],"mapped",[20013]],[[127534,127534],"mapped",[21491]],[[127535,127535],"mapped",[25351]],[[127536,127536],"mapped",[36208]],[[127537,127537],"mapped",[25171]],[[127538,127538],"mapped",[31105]],[[127539,127539],"mapped",[31354]],[[127540,127540],"mapped",[21512]],[[127541,127541],"mapped",[28288]],[[127542,127542],"mapped",[26377]],[[127543,127543],"mapped",[26376]],[[127544,127544],"mapped",[30003]],[[127545,127545],"mapped",[21106]],[[127546,127546],"mapped",[21942]],[[127547,127551],"disallowed"],[[127552,127552],"mapped",[12308,26412,12309]],[[127553,127553],"mapped",[12308,19977,12309]],[[127554,127554],"mapped",[12308,20108,12309]],[[127555,127555],"mapped",[12308,23433,12309]],[[127556,127556],"mapped",[12308,28857,12309]],[[127557,127557],"mapped",[12308,25171,12309]],[[127558,127558],"mapped",[12308,30423,12309]],[[127559,127559],"mapped",[12308,21213,12309]],[[127560,127560],"mapped",[12308,25943,12309]],[[127561,127567],"disallowed"],[[127568,127568],"mapped",[24471]],[[127569,127569],"mapped",[21487]],[[127570,127743],"disallowed"],[[127744,127776],"valid",[],"NV8"],[[127777,127788],"valid",[],"NV8"],[[127789,127791],"valid",[],"NV8"],[[127792,127797],"valid",[],"NV8"],[[127798,127798],"valid",[],"NV8"],[[127799,127868],"valid",[],"NV8"],[[127869,127869],"valid",[],"NV8"],[[127870,127871],"valid",[],"NV8"],[[127872,127891],"valid",[],"NV8"],[[127892,127903],"valid",[],"NV8"],[[127904,127940],"valid",[],"NV8"],[[127941,127941],"valid",[],"NV8"],[[127942,127946],"valid",[],"NV8"],[[127947,127950],"valid",[],"NV8"],[[127951,127955],"valid",[],"NV8"],[[127956,127967],"valid",[],"NV8"],[[127968,127984],"valid",[],"NV8"],[[127985,127991],"valid",[],"NV8"],[[127992,127999],"valid",[],"NV8"],[[128000,128062],"valid",[],"NV8"],[[128063,128063],"valid",[],"NV8"],[[128064,128064],"valid",[],"NV8"],[[128065,128065],"valid",[],"NV8"],[[128066,128247],"valid",[],"NV8"],[[128248,128248],"valid",[],"NV8"],[[128249,128252],"valid",[],"NV8"],[[128253,128254],"valid",[],"NV8"],[[128255,128255],"valid",[],"NV8"],[[128256,128317],"valid",[],"NV8"],[[128318,128319],"valid",[],"NV8"],[[128320,128323],"valid",[],"NV8"],[[128324,128330],"valid",[],"NV8"],[[128331,128335],"valid",[],"NV8"],[[128336,128359],"valid",[],"NV8"],[[128360,128377],"valid",[],"NV8"],[[128378,128378],"disallowed"],[[128379,128419],"valid",[],"NV8"],[[128420,128420],"disallowed"],[[128421,128506],"valid",[],"NV8"],[[128507,128511],"valid",[],"NV8"],[[128512,128512],"valid",[],"NV8"],[[128513,128528],"valid",[],"NV8"],[[128529,128529],"valid",[],"NV8"],[[128530,128532],"valid",[],"NV8"],[[128533,128533],"valid",[],"NV8"],[[128534,128534],"valid",[],"NV8"],[[128535,128535],"valid",[],"NV8"],[[128536,128536],"valid",[],"NV8"],[[128537,128537],"valid",[],"NV8"],[[128538,128538],"valid",[],"NV8"],[[128539,128539],"valid",[],"NV8"],[[128540,128542],"valid",[],"NV8"],[[128543,128543],"valid",[],"NV8"],[[128544,128549],"valid",[],"NV8"],[[128550,128551],"valid",[],"NV8"],[[128552,128555],"valid",[],"NV8"],[[128556,128556],"valid",[],"NV8"],[[128557,128557],"valid",[],"NV8"],[[128558,128559],"valid",[],"NV8"],[[128560,128563],"valid",[],"NV8"],[[128564,128564],"valid",[],"NV8"],[[128565,128576],"valid",[],"NV8"],[[128577,128578],"valid",[],"NV8"],[[128579,128580],"valid",[],"NV8"],[[128581,128591],"valid",[],"NV8"],[[128592,128639],"valid",[],"NV8"],[[128640,128709],"valid",[],"NV8"],[[128710,128719],"valid",[],"NV8"],[[128720,128720],"valid",[],"NV8"],[[128721,128735],"disallowed"],[[128736,128748],"valid",[],"NV8"],[[128749,128751],"disallowed"],[[128752,128755],"valid",[],"NV8"],[[128756,128767],"disallowed"],[[128768,128883],"valid",[],"NV8"],[[128884,128895],"disallowed"],[[128896,128980],"valid",[],"NV8"],[[128981,129023],"disallowed"],[[129024,129035],"valid",[],"NV8"],[[129036,129039],"disallowed"],[[129040,129095],"valid",[],"NV8"],[[129096,129103],"disallowed"],[[129104,129113],"valid",[],"NV8"],[[129114,129119],"disallowed"],[[129120,129159],"valid",[],"NV8"],[[129160,129167],"disallowed"],[[129168,129197],"valid",[],"NV8"],[[129198,129295],"disallowed"],[[129296,129304],"valid",[],"NV8"],[[129305,129407],"disallowed"],[[129408,129412],"valid",[],"NV8"],[[129413,129471],"disallowed"],[[129472,129472],"valid",[],"NV8"],[[129473,131069],"disallowed"],[[131070,131071],"disallowed"],[[131072,173782],"valid"],[[173783,173823],"disallowed"],[[173824,177972],"valid"],[[177973,177983],"disallowed"],[[177984,178205],"valid"],[[178206,178207],"disallowed"],[[178208,183969],"valid"],[[183970,194559],"disallowed"],[[194560,194560],"mapped",[20029]],[[194561,194561],"mapped",[20024]],[[194562,194562],"mapped",[20033]],[[194563,194563],"mapped",[131362]],[[194564,194564],"mapped",[20320]],[[194565,194565],"mapped",[20398]],[[194566,194566],"mapped",[20411]],[[194567,194567],"mapped",[20482]],[[194568,194568],"mapped",[20602]],[[194569,194569],"mapped",[20633]],[[194570,194570],"mapped",[20711]],[[194571,194571],"mapped",[20687]],[[194572,194572],"mapped",[13470]],[[194573,194573],"mapped",[132666]],[[194574,194574],"mapped",[20813]],[[194575,194575],"mapped",[20820]],[[194576,194576],"mapped",[20836]],[[194577,194577],"mapped",[20855]],[[194578,194578],"mapped",[132380]],[[194579,194579],"mapped",[13497]],[[194580,194580],"mapped",[20839]],[[194581,194581],"mapped",[20877]],[[194582,194582],"mapped",[132427]],[[194583,194583],"mapped",[20887]],[[194584,194584],"mapped",[20900]],[[194585,194585],"mapped",[20172]],[[194586,194586],"mapped",[20908]],[[194587,194587],"mapped",[20917]],[[194588,194588],"mapped",[168415]],[[194589,194589],"mapped",[20981]],[[194590,194590],"mapped",[20995]],[[194591,194591],"mapped",[13535]],[[194592,194592],"mapped",[21051]],[[194593,194593],"mapped",[21062]],[[194594,194594],"mapped",[21106]],[[194595,194595],"mapped",[21111]],[[194596,194596],"mapped",[13589]],[[194597,194597],"mapped",[21191]],[[194598,194598],"mapped",[21193]],[[194599,194599],"mapped",[21220]],[[194600,194600],"mapped",[21242]],[[194601,194601],"mapped",[21253]],[[194602,194602],"mapped",[21254]],[[194603,194603],"mapped",[21271]],[[194604,194604],"mapped",[21321]],[[194605,194605],"mapped",[21329]],[[194606,194606],"mapped",[21338]],[[194607,194607],"mapped",[21363]],[[194608,194608],"mapped",[21373]],[[194609,194611],"mapped",[21375]],[[194612,194612],"mapped",[133676]],[[194613,194613],"mapped",[28784]],[[194614,194614],"mapped",[21450]],[[194615,194615],"mapped",[21471]],[[194616,194616],"mapped",[133987]],[[194617,194617],"mapped",[21483]],[[194618,194618],"mapped",[21489]],[[194619,194619],"mapped",[21510]],[[194620,194620],"mapped",[21662]],[[194621,194621],"mapped",[21560]],[[194622,194622],"mapped",[21576]],[[194623,194623],"mapped",[21608]],[[194624,194624],"mapped",[21666]],[[194625,194625],"mapped",[21750]],[[194626,194626],"mapped",[21776]],[[194627,194627],"mapped",[21843]],[[194628,194628],"mapped",[21859]],[[194629,194630],"mapped",[21892]],[[194631,194631],"mapped",[21913]],[[194632,194632],"mapped",[21931]],[[194633,194633],"mapped",[21939]],[[194634,194634],"mapped",[21954]],[[194635,194635],"mapped",[22294]],[[194636,194636],"mapped",[22022]],[[194637,194637],"mapped",[22295]],[[194638,194638],"mapped",[22097]],[[194639,194639],"mapped",[22132]],[[194640,194640],"mapped",[20999]],[[194641,194641],"mapped",[22766]],[[194642,194642],"mapped",[22478]],[[194643,194643],"mapped",[22516]],[[194644,194644],"mapped",[22541]],[[194645,194645],"mapped",[22411]],[[194646,194646],"mapped",[22578]],[[194647,194647],"mapped",[22577]],[[194648,194648],"mapped",[22700]],[[194649,194649],"mapped",[136420]],[[194650,194650],"mapped",[22770]],[[194651,194651],"mapped",[22775]],[[194652,194652],"mapped",[22790]],[[194653,194653],"mapped",[22810]],[[194654,194654],"mapped",[22818]],[[194655,194655],"mapped",[22882]],[[194656,194656],"mapped",[136872]],[[194657,194657],"mapped",[136938]],[[194658,194658],"mapped",[23020]],[[194659,194659],"mapped",[23067]],[[194660,194660],"mapped",[23079]],[[194661,194661],"mapped",[23000]],[[194662,194662],"mapped",[23142]],[[194663,194663],"mapped",[14062]],[[194664,194664],"disallowed"],[[194665,194665],"mapped",[23304]],[[194666,194667],"mapped",[23358]],[[194668,194668],"mapped",[137672]],[[194669,194669],"mapped",[23491]],[[194670,194670],"mapped",[23512]],[[194671,194671],"mapped",[23527]],[[194672,194672],"mapped",[23539]],[[194673,194673],"mapped",[138008]],[[194674,194674],"mapped",[23551]],[[194675,194675],"mapped",[23558]],[[194676,194676],"disallowed"],[[194677,194677],"mapped",[23586]],[[194678,194678],"mapped",[14209]],[[194679,194679],"mapped",[23648]],[[194680,194680],"mapped",[23662]],[[194681,194681],"mapped",[23744]],[[194682,194682],"mapped",[23693]],[[194683,194683],"mapped",[138724]],[[194684,194684],"mapped",[23875]],[[194685,194685],"mapped",[138726]],[[194686,194686],"mapped",[23918]],[[194687,194687],"mapped",[23915]],[[194688,194688],"mapped",[23932]],[[194689,194689],"mapped",[24033]],[[194690,194690],"mapped",[24034]],[[194691,194691],"mapped",[14383]],[[194692,194692],"mapped",[24061]],[[194693,194693],"mapped",[24104]],[[194694,194694],"mapped",[24125]],[[194695,194695],"mapped",[24169]],[[194696,194696],"mapped",[14434]],[[194697,194697],"mapped",[139651]],[[194698,194698],"mapped",[14460]],[[194699,194699],"mapped",[24240]],[[194700,194700],"mapped",[24243]],[[194701,194701],"mapped",[24246]],[[194702,194702],"mapped",[24266]],[[194703,194703],"mapped",[172946]],[[194704,194704],"mapped",[24318]],[[194705,194706],"mapped",[140081]],[[194707,194707],"mapped",[33281]],[[194708,194709],"mapped",[24354]],[[194710,194710],"mapped",[14535]],[[194711,194711],"mapped",[144056]],[[194712,194712],"mapped",[156122]],[[194713,194713],"mapped",[24418]],[[194714,194714],"mapped",[24427]],[[194715,194715],"mapped",[14563]],[[194716,194716],"mapped",[24474]],[[194717,194717],"mapped",[24525]],[[194718,194718],"mapped",[24535]],[[194719,194719],"mapped",[24569]],[[194720,194720],"mapped",[24705]],[[194721,194721],"mapped",[14650]],[[194722,194722],"mapped",[14620]],[[194723,194723],"mapped",[24724]],[[194724,194724],"mapped",[141012]],[[194725,194725],"mapped",[24775]],[[194726,194726],"mapped",[24904]],[[194727,194727],"mapped",[24908]],[[194728,194728],"mapped",[24910]],[[194729,194729],"mapped",[24908]],[[194730,194730],"mapped",[24954]],[[194731,194731],"mapped",[24974]],[[194732,194732],"mapped",[25010]],[[194733,194733],"mapped",[24996]],[[194734,194734],"mapped",[25007]],[[194735,194735],"mapped",[25054]],[[194736,194736],"mapped",[25074]],[[194737,194737],"mapped",[25078]],[[194738,194738],"mapped",[25104]],[[194739,194739],"mapped",[25115]],[[194740,194740],"mapped",[25181]],[[194741,194741],"mapped",[25265]],[[194742,194742],"mapped",[25300]],[[194743,194743],"mapped",[25424]],[[194744,194744],"mapped",[142092]],[[194745,194745],"mapped",[25405]],[[194746,194746],"mapped",[25340]],[[194747,194747],"mapped",[25448]],[[194748,194748],"mapped",[25475]],[[194749,194749],"mapped",[25572]],[[194750,194750],"mapped",[142321]],[[194751,194751],"mapped",[25634]],[[194752,194752],"mapped",[25541]],[[194753,194753],"mapped",[25513]],[[194754,194754],"mapped",[14894]],[[194755,194755],"mapped",[25705]],[[194756,194756],"mapped",[25726]],[[194757,194757],"mapped",[25757]],[[194758,194758],"mapped",[25719]],[[194759,194759],"mapped",[14956]],[[194760,194760],"mapped",[25935]],[[194761,194761],"mapped",[25964]],[[194762,194762],"mapped",[143370]],[[194763,194763],"mapped",[26083]],[[194764,194764],"mapped",[26360]],[[194765,194765],"mapped",[26185]],[[194766,194766],"mapped",[15129]],[[194767,194767],"mapped",[26257]],[[194768,194768],"mapped",[15112]],[[194769,194769],"mapped",[15076]],[[194770,194770],"mapped",[20882]],[[194771,194771],"mapped",[20885]],[[194772,194772],"mapped",[26368]],[[194773,194773],"mapped",[26268]],[[194774,194774],"mapped",[32941]],[[194775,194775],"mapped",[17369]],[[194776,194776],"mapped",[26391]],[[194777,194777],"mapped",[26395]],[[194778,194778],"mapped",[26401]],[[194779,194779],"mapped",[26462]],[[194780,194780],"mapped",[26451]],[[194781,194781],"mapped",[144323]],[[194782,194782],"mapped",[15177]],[[194783,194783],"mapped",[26618]],[[194784,194784],"mapped",[26501]],[[194785,194785],"mapped",[26706]],[[194786,194786],"mapped",[26757]],[[194787,194787],"mapped",[144493]],[[194788,194788],"mapped",[26766]],[[194789,194789],"mapped",[26655]],[[194790,194790],"mapped",[26900]],[[194791,194791],"mapped",[15261]],[[194792,194792],"mapped",[26946]],[[194793,194793],"mapped",[27043]],[[194794,194794],"mapped",[27114]],[[194795,194795],"mapped",[27304]],[[194796,194796],"mapped",[145059]],[[194797,194797],"mapped",[27355]],[[194798,194798],"mapped",[15384]],[[194799,194799],"mapped",[27425]],[[194800,194800],"mapped",[145575]],[[194801,194801],"mapped",[27476]],[[194802,194802],"mapped",[15438]],[[194803,194803],"mapped",[27506]],[[194804,194804],"mapped",[27551]],[[194805,194805],"mapped",[27578]],[[194806,194806],"mapped",[27579]],[[194807,194807],"mapped",[146061]],[[194808,194808],"mapped",[138507]],[[194809,194809],"mapped",[146170]],[[194810,194810],"mapped",[27726]],[[194811,194811],"mapped",[146620]],[[194812,194812],"mapped",[27839]],[[194813,194813],"mapped",[27853]],[[194814,194814],"mapped",[27751]],[[194815,194815],"mapped",[27926]],[[194816,194816],"mapped",[27966]],[[194817,194817],"mapped",[28023]],[[194818,194818],"mapped",[27969]],[[194819,194819],"mapped",[28009]],[[194820,194820],"mapped",[28024]],[[194821,194821],"mapped",[28037]],[[194822,194822],"mapped",[146718]],[[194823,194823],"mapped",[27956]],[[194824,194824],"mapped",[28207]],[[194825,194825],"mapped",[28270]],[[194826,194826],"mapped",[15667]],[[194827,194827],"mapped",[28363]],[[194828,194828],"mapped",[28359]],[[194829,194829],"mapped",[147153]],[[194830,194830],"mapped",[28153]],[[194831,194831],"mapped",[28526]],[[194832,194832],"mapped",[147294]],[[194833,194833],"mapped",[147342]],[[194834,194834],"mapped",[28614]],[[194835,194835],"mapped",[28729]],[[194836,194836],"mapped",[28702]],[[194837,194837],"mapped",[28699]],[[194838,194838],"mapped",[15766]],[[194839,194839],"mapped",[28746]],[[194840,194840],"mapped",[28797]],[[194841,194841],"mapped",[28791]],[[194842,194842],"mapped",[28845]],[[194843,194843],"mapped",[132389]],[[194844,194844],"mapped",[28997]],[[194845,194845],"mapped",[148067]],[[194846,194846],"mapped",[29084]],[[194847,194847],"disallowed"],[[194848,194848],"mapped",[29224]],[[194849,194849],"mapped",[29237]],[[194850,194850],"mapped",[29264]],[[194851,194851],"mapped",[149000]],[[194852,194852],"mapped",[29312]],[[194853,194853],"mapped",[29333]],[[194854,194854],"mapped",[149301]],[[194855,194855],"mapped",[149524]],[[194856,194856],"mapped",[29562]],[[194857,194857],"mapped",[29579]],[[194858,194858],"mapped",[16044]],[[194859,194859],"mapped",[29605]],[[194860,194861],"mapped",[16056]],[[194862,194862],"mapped",[29767]],[[194863,194863],"mapped",[29788]],[[194864,194864],"mapped",[29809]],[[194865,194865],"mapped",[29829]],[[194866,194866],"mapped",[29898]],[[194867,194867],"mapped",[16155]],[[194868,194868],"mapped",[29988]],[[194869,194869],"mapped",[150582]],[[194870,194870],"mapped",[30014]],[[194871,194871],"mapped",[150674]],[[194872,194872],"mapped",[30064]],[[194873,194873],"mapped",[139679]],[[194874,194874],"mapped",[30224]],[[194875,194875],"mapped",[151457]],[[194876,194876],"mapped",[151480]],[[194877,194877],"mapped",[151620]],[[194878,194878],"mapped",[16380]],[[194879,194879],"mapped",[16392]],[[194880,194880],"mapped",[30452]],[[194881,194881],"mapped",[151795]],[[194882,194882],"mapped",[151794]],[[194883,194883],"mapped",[151833]],[[194884,194884],"mapped",[151859]],[[194885,194885],"mapped",[30494]],[[194886,194887],"mapped",[30495]],[[194888,194888],"mapped",[30538]],[[194889,194889],"mapped",[16441]],[[194890,194890],"mapped",[30603]],[[194891,194891],"mapped",[16454]],[[194892,194892],"mapped",[16534]],[[194893,194893],"mapped",[152605]],[[194894,194894],"mapped",[30798]],[[194895,194895],"mapped",[30860]],[[194896,194896],"mapped",[30924]],[[194897,194897],"mapped",[16611]],[[194898,194898],"mapped",[153126]],[[194899,194899],"mapped",[31062]],[[194900,194900],"mapped",[153242]],[[194901,194901],"mapped",[153285]],[[194902,194902],"mapped",[31119]],[[194903,194903],"mapped",[31211]],[[194904,194904],"mapped",[16687]],[[194905,194905],"mapped",[31296]],[[194906,194906],"mapped",[31306]],[[194907,194907],"mapped",[31311]],[[194908,194908],"mapped",[153980]],[[194909,194910],"mapped",[154279]],[[194911,194911],"disallowed"],[[194912,194912],"mapped",[16898]],[[194913,194913],"mapped",[154539]],[[194914,194914],"mapped",[31686]],[[194915,194915],"mapped",[31689]],[[194916,194916],"mapped",[16935]],[[194917,194917],"mapped",[154752]],[[194918,194918],"mapped",[31954]],[[194919,194919],"mapped",[17056]],[[194920,194920],"mapped",[31976]],[[194921,194921],"mapped",[31971]],[[194922,194922],"mapped",[32000]],[[194923,194923],"mapped",[155526]],[[194924,194924],"mapped",[32099]],[[194925,194925],"mapped",[17153]],[[194926,194926],"mapped",[32199]],[[194927,194927],"mapped",[32258]],[[194928,194928],"mapped",[32325]],[[194929,194929],"mapped",[17204]],[[194930,194930],"mapped",[156200]],[[194931,194931],"mapped",[156231]],[[194932,194932],"mapped",[17241]],[[194933,194933],"mapped",[156377]],[[194934,194934],"mapped",[32634]],[[194935,194935],"mapped",[156478]],[[194936,194936],"mapped",[32661]],[[194937,194937],"mapped",[32762]],[[194938,194938],"mapped",[32773]],[[194939,194939],"mapped",[156890]],[[194940,194940],"mapped",[156963]],[[194941,194941],"mapped",[32864]],[[194942,194942],"mapped",[157096]],[[194943,194943],"mapped",[32880]],[[194944,194944],"mapped",[144223]],[[194945,194945],"mapped",[17365]],[[194946,194946],"mapped",[32946]],[[194947,194947],"mapped",[33027]],[[194948,194948],"mapped",[17419]],[[194949,194949],"mapped",[33086]],[[194950,194950],"mapped",[23221]],[[194951,194951],"mapped",[157607]],[[194952,194952],"mapped",[157621]],[[194953,194953],"mapped",[144275]],[[194954,194954],"mapped",[144284]],[[194955,194955],"mapped",[33281]],[[194956,194956],"mapped",[33284]],[[194957,194957],"mapped",[36766]],[[194958,194958],"mapped",[17515]],[[194959,194959],"mapped",[33425]],[[194960,194960],"mapped",[33419]],[[194961,194961],"mapped",[33437]],[[194962,194962],"mapped",[21171]],[[194963,194963],"mapped",[33457]],[[194964,194964],"mapped",[33459]],[[194965,194965],"mapped",[33469]],[[194966,194966],"mapped",[33510]],[[194967,194967],"mapped",[158524]],[[194968,194968],"mapped",[33509]],[[194969,194969],"mapped",[33565]],[[194970,194970],"mapped",[33635]],[[194971,194971],"mapped",[33709]],[[194972,194972],"mapped",[33571]],[[194973,194973],"mapped",[33725]],[[194974,194974],"mapped",[33767]],[[194975,194975],"mapped",[33879]],[[194976,194976],"mapped",[33619]],[[194977,194977],"mapped",[33738]],[[194978,194978],"mapped",[33740]],[[194979,194979],"mapped",[33756]],[[194980,194980],"mapped",[158774]],[[194981,194981],"mapped",[159083]],[[194982,194982],"mapped",[158933]],[[194983,194983],"mapped",[17707]],[[194984,194984],"mapped",[34033]],[[194985,194985],"mapped",[34035]],[[194986,194986],"mapped",[34070]],[[194987,194987],"mapped",[160714]],[[194988,194988],"mapped",[34148]],[[194989,194989],"mapped",[159532]],[[194990,194990],"mapped",[17757]],[[194991,194991],"mapped",[17761]],[[194992,194992],"mapped",[159665]],[[194993,194993],"mapped",[159954]],[[194994,194994],"mapped",[17771]],[[194995,194995],"mapped",[34384]],[[194996,194996],"mapped",[34396]],[[194997,194997],"mapped",[34407]],[[194998,194998],"mapped",[34409]],[[194999,194999],"mapped",[34473]],[[195000,195000],"mapped",[34440]],[[195001,195001],"mapped",[34574]],[[195002,195002],"mapped",[34530]],[[195003,195003],"mapped",[34681]],[[195004,195004],"mapped",[34600]],[[195005,195005],"mapped",[34667]],[[195006,195006],"mapped",[34694]],[[195007,195007],"disallowed"],[[195008,195008],"mapped",[34785]],[[195009,195009],"mapped",[34817]],[[195010,195010],"mapped",[17913]],[[195011,195011],"mapped",[34912]],[[195012,195012],"mapped",[34915]],[[195013,195013],"mapped",[161383]],[[195014,195014],"mapped",[35031]],[[195015,195015],"mapped",[35038]],[[195016,195016],"mapped",[17973]],[[195017,195017],"mapped",[35066]],[[195018,195018],"mapped",[13499]],[[195019,195019],"mapped",[161966]],[[195020,195020],"mapped",[162150]],[[195021,195021],"mapped",[18110]],[[195022,195022],"mapped",[18119]],[[195023,195023],"mapped",[35488]],[[195024,195024],"mapped",[35565]],[[195025,195025],"mapped",[35722]],[[195026,195026],"mapped",[35925]],[[195027,195027],"mapped",[162984]],[[195028,195028],"mapped",[36011]],[[195029,195029],"mapped",[36033]],[[195030,195030],"mapped",[36123]],[[195031,195031],"mapped",[36215]],[[195032,195032],"mapped",[163631]],[[195033,195033],"mapped",[133124]],[[195034,195034],"mapped",[36299]],[[195035,195035],"mapped",[36284]],[[195036,195036],"mapped",[36336]],[[195037,195037],"mapped",[133342]],[[195038,195038],"mapped",[36564]],[[195039,195039],"mapped",[36664]],[[195040,195040],"mapped",[165330]],[[195041,195041],"mapped",[165357]],[[195042,195042],"mapped",[37012]],[[195043,195043],"mapped",[37105]],[[195044,195044],"mapped",[37137]],[[195045,195045],"mapped",[165678]],[[195046,195046],"mapped",[37147]],[[195047,195047],"mapped",[37432]],[[195048,195048],"mapped",[37591]],[[195049,195049],"mapped",[37592]],[[195050,195050],"mapped",[37500]],[[195051,195051],"mapped",[37881]],[[195052,195052],"mapped",[37909]],[[195053,195053],"mapped",[166906]],[[195054,195054],"mapped",[38283]],[[195055,195055],"mapped",[18837]],[[195056,195056],"mapped",[38327]],[[195057,195057],"mapped",[167287]],[[195058,195058],"mapped",[18918]],[[195059,195059],"mapped",[38595]],[[195060,195060],"mapped",[23986]],[[195061,195061],"mapped",[38691]],[[195062,195062],"mapped",[168261]],[[195063,195063],"mapped",[168474]],[[195064,195064],"mapped",[19054]],[[195065,195065],"mapped",[19062]],[[195066,195066],"mapped",[38880]],[[195067,195067],"mapped",[168970]],[[195068,195068],"mapped",[19122]],[[195069,195069],"mapped",[169110]],[[195070,195071],"mapped",[38923]],[[195072,195072],"mapped",[38953]],[[195073,195073],"mapped",[169398]],[[195074,195074],"mapped",[39138]],[[195075,195075],"mapped",[19251]],[[195076,195076],"mapped",[39209]],[[195077,195077],"mapped",[39335]],[[195078,195078],"mapped",[39362]],[[195079,195079],"mapped",[39422]],[[195080,195080],"mapped",[19406]],[[195081,195081],"mapped",[170800]],[[195082,195082],"mapped",[39698]],[[195083,195083],"mapped",[40000]],[[195084,195084],"mapped",[40189]],[[195085,195085],"mapped",[19662]],[[195086,195086],"mapped",[19693]],[[195087,195087],"mapped",[40295]],[[195088,195088],"mapped",[172238]],[[195089,195089],"mapped",[19704]],[[195090,195090],"mapped",[172293]],[[195091,195091],"mapped",[172558]],[[195092,195092],"mapped",[172689]],[[195093,195093],"mapped",[40635]],[[195094,195094],"mapped",[19798]],[[195095,195095],"mapped",[40697]],[[195096,195096],"mapped",[40702]],[[195097,195097],"mapped",[40709]],[[195098,195098],"mapped",[40719]],[[195099,195099],"mapped",[40726]],[[195100,195100],"mapped",[40763]],[[195101,195101],"mapped",[173568]],[[195102,196605],"disallowed"],[[196606,196607],"disallowed"],[[196608,262141],"disallowed"],[[262142,262143],"disallowed"],[[262144,327677],"disallowed"],[[327678,327679],"disallowed"],[[327680,393213],"disallowed"],[[393214,393215],"disallowed"],[[393216,458749],"disallowed"],[[458750,458751],"disallowed"],[[458752,524285],"disallowed"],[[524286,524287],"disallowed"],[[524288,589821],"disallowed"],[[589822,589823],"disallowed"],[[589824,655357],"disallowed"],[[655358,655359],"disallowed"],[[655360,720893],"disallowed"],[[720894,720895],"disallowed"],[[720896,786429],"disallowed"],[[786430,786431],"disallowed"],[[786432,851965],"disallowed"],[[851966,851967],"disallowed"],[[851968,917501],"disallowed"],[[917502,917503],"disallowed"],[[917504,917504],"disallowed"],[[917505,917505],"disallowed"],[[917506,917535],"disallowed"],[[917536,917631],"disallowed"],[[917632,917759],"disallowed"],[[917760,917999],"ignored"],[[918000,983037],"disallowed"],[[983038,983039],"disallowed"],[[983040,1048573],"disallowed"],[[1048574,1048575],"disallowed"],[[1048576,1114109],"disallowed"],[[1114110,1114111],"disallowed"]]'); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; +/******/ +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module is referenced by other modules so it can't be inlined +/******/ var __webpack_exports__ = __nccwpck_require__(2644); +/******/ module.exports = __webpack_exports__; +/******/ +/******/ })() +; diff --git a/.github/actions/javascript/proposalPoliceComment/proposalPoliceComment.ts b/.github/actions/javascript/proposalPoliceComment/proposalPoliceComment.ts new file mode 100644 index 000000000000..5a48bf06feee --- /dev/null +++ b/.github/actions/javascript/proposalPoliceComment/proposalPoliceComment.ts @@ -0,0 +1,107 @@ +import {setFailed} from '@actions/core'; +import {context} from '@actions/github'; +import type {IssueCommentCreatedEvent, IssueCommentEditedEvent, IssueCommentEvent} from '@octokit/webhooks-types'; +import CONST from '@github/libs/CONST'; +import GithubUtils from '@github/libs/GithubUtils'; +import OpenAIUtils from '@github/libs/OpenAIUtils'; + +function isCommentCreatedOrEditedEvent(payload: IssueCommentEvent): payload is IssueCommentCreatedEvent | IssueCommentEditedEvent { + return payload.action === CONST.ACTIONS.CREATED || payload.action === CONST.ACTIONS.EDIT; +} + +function isCommentCreatedEvent(payload: IssueCommentEvent): payload is IssueCommentCreatedEvent { + return payload.action === CONST.ACTIONS.CREATED; +} + +// Main function to process the workflow event +async function run() { + // Verify this is running for an expected webhook event + if (context.eventName !== CONST.EVENTS.ISSUE_COMMENT) { + throw new Error('ProposalPoliceā„¢ only supports the issue_comment webhook event'); + } + + const payload = context.payload as IssueCommentEvent; + + // check if the issue is open and the has labels + if (payload.issue?.state !== 'open' && !payload.issue?.labels.some((issueLabel: {name: string}) => issueLabel.name === CONST.LABELS.HELP_WANTED)) { + return; + } + + // Verify that the comment is not empty and contains the case sensitive `Proposal` keyword + if (!payload.comment?.body.trim() || !payload.comment?.body.includes(CONST.PROPOSAL_KEYWORD)) { + console.log('Comment body is either empty or doesn\'t contain the keyword "Proposal": ', payload.comment?.body); + return; + } + + console.log('ProposalPoliceā„¢ Action triggered for comment:', payload.comment?.body); + console.log('-> GitHub Action Type: ', payload.action?.toUpperCase()); + + if (!isCommentCreatedOrEditedEvent(payload)) { + console.error('Unsupported action type:', payload?.action); + setFailed(new Error(`Unsupported action type ${payload?.action}`)); + return; + } + + const prompt = isCommentCreatedEvent(payload) + ? `I NEED HELP WITH CASE (1.), CHECK IF COMMENT IS PROPOSAL AND IF TEMPLATE IS FOLLOWED AS PER INSTRUCTIONS. IT IS MANDATORY THAT YOU RESPOND ONLY WITH "${CONST.NO_ACTION}" IN CASE THE COMMENT IS NOT A PROPOSAL. Comment content: ${payload.comment?.body}` + : `I NEED HELP WITH CASE (2.) WHEN A USER THAT POSTED AN INITIAL PROPOSAL OR COMMENT (UNEDITED) THEN EDITS THE COMMENT - WE NEED TO CLASSIFY THE COMMENT BASED IN THE GIVEN INSTRUCTIONS AND IF TEMPLATE IS FOLLOWED AS PER INSTRUCTIONS. IT IS MANDATORY THAT YOU RESPOND ONLY WITH "${CONST.NO_ACTION}" IN CASE THE COMMENT IS NOT A PROPOSAL. \n\nPrevious comment content: ${payload.changes.body?.from}.\n\nEdited comment content: ${payload.comment?.body}`; + + const assistantResponse = await OpenAIUtils.prompt(prompt); + + // check if assistant response is either NO_ACTION or "NO_ACTION" strings + // as sometimes the assistant response varies + const isNoAction = assistantResponse.trim().replaceAll(' ', '_').replaceAll('"', '').toUpperCase() === CONST.NO_ACTION; + + // If assistant response is NO_ACTION, do nothing + if (isNoAction) { + console.log('Detected NO_ACTION for comment, returning early'); + return; + } + + // if the assistant responded with no action but there's some context in the response + if (assistantResponse.includes(`[${CONST.NO_ACTION}]`)) { + // extract the text after [NO_ACTION] from assistantResponse since this is a + // bot related action keyword + const noActionContext = assistantResponse.split(`[${CONST.NO_ACTION}] `)?.[1]?.replace('"', ''); + console.log('[NO_ACTION] w/ context: ', noActionContext); + return; + } + + if (isCommentCreatedEvent(payload)) { + const formattedResponse = assistantResponse + // replace {user} from response template with @username + .replaceAll('{user}', `@${payload.comment?.user.login}`) + + // replace {proposalLink} from response template with the link to the comment + .replaceAll('{proposalLink}', payload.comment?.html_url) + + // remove any double quotes from the final comment because sometimes the assistant's + // response contains double quotes / sometimes it doesn't + .replaceAll('"', ''); + + // Create a comment with the assistant's response + console.log('ProposalPoliceā„¢ commenting on issue...'); + await GithubUtils.createComment(CONST.APP_REPO, context.issue.number, formattedResponse); + // edit comment if assistant detected substantial changes and if the comment was not edited already by the bot + } else if (assistantResponse.includes('[EDIT_COMMENT]') && !payload.comment?.body.includes('Edited by **proposal-police**')) { + // extract the text after [EDIT_COMMENT] from assistantResponse since this is a + // bot related action keyword + let extractedNotice = assistantResponse.split('[EDIT_COMMENT] ')?.[1]?.replace('"', ''); + // format the github's updated_at like: 2024-01-24 13:15:24 UTC not 2024-01-28 18:18:28.000 UTC + const date = new Date(payload.comment?.updated_at ?? ''); + const formattedDate = `${date.toISOString()?.split('.')?.[0]?.replace('T', ' ')} UTC`; + extractedNotice = extractedNotice.replace('{updated_timestamp}', formattedDate); + console.log('ProposalPoliceā„¢ editing issue comment...', payload.comment.id); + await GithubUtils.octokit.issues.updateComment({ + ...context.repo, + /* eslint-disable @typescript-eslint/naming-convention */ + comment_id: payload.comment.id, + body: `${extractedNotice}\n\n${payload.comment?.body}`, + }); + } +} + +run().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/.github/actions/javascript/reopenIssueWithComment/index.js b/.github/actions/javascript/reopenIssueWithComment/index.js index 461f576e4691..75d40871926c 100644 --- a/.github/actions/javascript/reopenIssueWithComment/index.js +++ b/.github/actions/javascript/reopenIssueWithComment/index.js @@ -11511,7 +11511,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11519,6 +11533,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11895,12 +11912,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/reviewerChecklist/index.js b/.github/actions/javascript/reviewerChecklist/index.js index 5be97363a21c..0cec1bc183f0 100644 --- a/.github/actions/javascript/reviewerChecklist/index.js +++ b/.github/actions/javascript/reviewerChecklist/index.js @@ -11603,7 +11603,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11611,6 +11625,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11987,12 +12004,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/actions/javascript/verifySignedCommits/index.js b/.github/actions/javascript/verifySignedCommits/index.js index c932e0c4c618..0d441b9f52d3 100644 --- a/.github/actions/javascript/verifySignedCommits/index.js +++ b/.github/actions/javascript/verifySignedCommits/index.js @@ -11543,7 +11543,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -11551,6 +11565,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, }; exports["default"] = CONST; @@ -11927,12 +11944,6 @@ class GithubUtils { }) .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests) { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } /** * Generate the URL of an New Expensify pull request given the PR number. */ diff --git a/.github/libs/CONST.ts b/.github/libs/CONST.ts index 8d9aae9bff83..a46f4afc421c 100644 --- a/.github/libs/CONST.ts +++ b/.github/libs/CONST.ts @@ -13,7 +13,21 @@ const CONST = { STAGING_DEPLOY: 'StagingDeployCash', DEPLOY_BLOCKER: 'DeployBlockerCash', INTERNAL_QA: 'InternalQA', + HELP_WANTED: 'Help Wanted', }, + ACTIONS: { + CREATED: 'created', + EDIT: 'edited', + }, + EVENTS: { + ISSUE_COMMENT: 'issue_comment', + }, + OPENAI_ROLES: { + USER: 'user', + ASSISTANT: 'assistant', + }, + PROPOSAL_KEYWORD: 'Proposal', + OPENAI_THREAD_COMPLETED: 'completed', DATE_FORMAT_STRING: 'yyyy-MM-dd', PULL_REQUEST_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/pull/([0-9]+).*`), ISSUE_REGEX: new RegExp(`${GITHUB_BASE_URL_REGEX.source}/.*/.*/issues/([0-9]+).*`), @@ -21,6 +35,9 @@ const CONST = { POLL_RATE: 10000, APP_REPO_URL: `https://github.com/${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}`, APP_REPO_GIT_URL: `git@github.com:${GIT_CONST.GITHUB_OWNER}/${GIT_CONST.APP_REPO}.git`, + NO_ACTION: 'NO_ACTION', + OPENAI_POLL_RATE: 1500, + OPENAI_POLL_TIMEOUT: 90000, } as const; export default CONST; diff --git a/.github/libs/GithubUtils.ts b/.github/libs/GithubUtils.ts index 73553cb46bff..36363684a351 100644 --- a/.github/libs/GithubUtils.ts +++ b/.github/libs/GithubUtils.ts @@ -462,13 +462,6 @@ class GithubUtils { .then((response) => response.data.workflow_runs[0]?.id); } - /** - * Generate the well-formatted body of a production release. - */ - static getReleaseBody(pullRequests: number[]): string { - return pullRequests.map((number) => `- ${this.getPullRequestURLFromNumber(number)}`).join('\r\n'); - } - /** * Generate the URL of an New Expensify pull request given the PR number. */ @@ -559,7 +552,4 @@ class GithubUtils { } export default GithubUtils; -// This is a temporary solution to allow the use of the GithubUtils class in both TypeScript and JavaScript. -// Once all the files that import GithubUtils are migrated to TypeScript, this can be removed. - export type {ListForRepoMethod, InternalOctokit, CreateCommentResponse, StagingDeployCashData}; diff --git a/.github/libs/OpenAIUtils.ts b/.github/libs/OpenAIUtils.ts new file mode 100644 index 000000000000..a62fb509b7b5 --- /dev/null +++ b/.github/libs/OpenAIUtils.ts @@ -0,0 +1,74 @@ +import {getInput} from '@actions/core'; +import OpenAI from 'openai'; +import type {MessageContent, TextContentBlock} from 'openai/resources/beta/threads'; +import CONST from './CONST'; + +const MAX_POLL_COUNT = Math.floor(CONST.OPENAI_POLL_TIMEOUT / CONST.OPENAI_POLL_RATE); + +class OpenAIUtils { + private static ai: OpenAI; + + private static assistantID: string; + + static init(apiKey?: string, assistantID?: string) { + const key = apiKey ?? getInput('PROPOSAL_POLICE_API_KEY', {required: true}); + if (!key) { + throw new Error('Could not initialize OpenAI: No key provided.'); + } + this.ai = new OpenAI({apiKey: key}); + this.assistantID = assistantID ?? getInput('PROPOSAL_POLICE_ASSISTANT_ID', {required: true}); + } + + static get openAI() { + if (!this.ai) { + this.init(); + } + return this.ai; + } + + static async prompt(userMessage: string) { + // start a thread run + let threadRun = await this.openAI.beta.threads.createAndRun({ + /* eslint-disable @typescript-eslint/naming-convention */ + assistant_id: this.assistantID, + thread: {messages: [{role: CONST.OPENAI_ROLES.USER, content: userMessage}]}, + }); + + // poll for run completion + let response = ''; + let count = 0; + while (!response && count < MAX_POLL_COUNT) { + // await thread run completion + threadRun = await this.openAI.beta.threads.runs.retrieve(threadRun.thread_id, threadRun.id); + if (threadRun.status !== CONST.OPENAI_THREAD_COMPLETED) { + count++; + await new Promise((resolve) => { + setTimeout(resolve, CONST.OPENAI_POLL_RATE); + }); + continue; + } + + for await (const message of this.openAI.beta.threads.messages.list(threadRun.thread_id)) { + if (message.role !== CONST.OPENAI_ROLES.ASSISTANT) { + continue; + } + response += message.content + .map((contentBlock) => this.isTextContentBlock(contentBlock)) + .join('\n') + .trim(); + console.log('Parsed assistant response:', response); + } + + if (!response) { + throw new Error('Assistant response is empty or had no text content. This is unexpected.'); + } + } + return response; + } + + static isTextContentBlock(contentBlock: MessageContent): contentBlock is TextContentBlock { + return contentBlock?.type === 'text'; + } +} + +export default OpenAIUtils; diff --git a/.github/scripts/buildActions.sh b/.github/scripts/buildActions.sh index 27d65ca99c9b..4d54d75b0520 100755 --- a/.github/scripts/buildActions.sh +++ b/.github/scripts/buildActions.sh @@ -27,6 +27,7 @@ declare -r GITHUB_ACTIONS=( "$ACTIONS_DIR/validateReassureOutput/validateReassureOutput.ts" "$ACTIONS_DIR/getGraphiteString/getGraphiteString.ts" "$ACTIONS_DIR/getArtifactInfo/getArtifactInfo.ts" + "$ACTIONS_DIR/proposalPoliceComment/proposalPoliceComment.ts" ) # This will be inserted at the top of all compiled files as a warning to devs. diff --git a/.github/scripts/createDocsRoutes.ts b/.github/scripts/createDocsRoutes.ts index fc3f376a1774..a8ac3d511ff9 100644 --- a/.github/scripts/createDocsRoutes.ts +++ b/.github/scripts/createDocsRoutes.ts @@ -5,6 +5,7 @@ import type {ValueOf} from 'type-fest'; type Article = { href: string; title: string; + order?: number; }; type Section = { @@ -60,11 +61,12 @@ function toTitleCase(str: string): string { /** * @param filename - The name of the file */ -function getArticleObj(filename: string): Article { +function getArticleObj(filename: string, order?: number): Article { const href = filename.replace('.md', ''); return { href, title: toTitleCase(href.replaceAll('-', ' ')), + order, }; } @@ -90,6 +92,12 @@ function pushOrCreateEntry(hubs: Hub[], hub: string, } } +function getOrderFromArticleFrontMatter(path: string): number | undefined { + const frontmatter = fs.readFileSync(path, 'utf8').split('---')[1]; + const frontmatterObject = yaml.load(frontmatter) as Record; + return frontmatterObject.order as number | undefined; +} + /** * Add articles and sections to hubs * @param hubs - The hubs inside docs/articles/ for a platform @@ -113,7 +121,8 @@ function createHubsWithArticles(hubs: string[], platformName: ValueOf { - articles.push(getArticleObj(subArticle)); + const order = getOrderFromArticleFrontMatter(`${docsDir}/articles/${platformName}/${hub}/${section}/${subArticle}`); + articles.push(getArticleObj(subArticle, order)); }); pushOrCreateEntry(routeHubs, hub, 'sections', { diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5030ea1c2f2b..5aacf0ceea1d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -28,7 +28,7 @@ jobs: - name: šŸš€ Push tags to trigger staging deploy šŸš€ run: git push --tags - + - name: Warn deployers if staging deploy failed if: ${{ failure() }} uses: 8398a7/action-slack@v3 @@ -83,10 +83,10 @@ jobs: PR_LIST: ${{ steps.getReleasePRList.outputs.PR_LIST }} - name: šŸš€ Create release to trigger production deploy šŸš€ - run: gh release create ${{ env.PRODUCTION_VERSION }} --notes '${{ steps.getReleaseBody.outputs.RELEASE_BODY }}' + run: gh release create ${{ env.PRODUCTION_VERSION }} --title ${{ env.PRODUCTION_VERSION }} --notes '${{ steps.getReleaseBody.outputs.RELEASE_BODY }}' env: GITHUB_TOKEN: ${{ steps.setupGitForOSBotify.outputs.OS_BOTIFY_API_TOKEN }} - + - name: Warn deployers if production deploy failed if: ${{ failure() }} uses: 8398a7/action-slack@v3 diff --git a/.github/workflows/e2ePerformanceTests.yml b/.github/workflows/e2ePerformanceTests.yml index ffce73644263..add4879d8de1 100644 --- a/.github/workflows/e2ePerformanceTests.yml +++ b/.github/workflows/e2ePerformanceTests.yml @@ -156,7 +156,7 @@ jobs: run: mkdir zip - name: Download baseline APK - uses: actions/download-artifact@348754975ef0295bfa2c111cba996120cfdf8a5d + uses: actions/download-artifact@v4 id: downloadBaselineAPK with: name: baseline-apk-${{ needs.buildBaseline.outputs.VERSION }} @@ -170,7 +170,7 @@ jobs: run: mv "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2e-release.apk" "${{steps.downloadBaselineAPK.outputs.download-path}}/app-e2eRelease.apk" - name: Download delta APK - uses: actions/download-artifact@348754975ef0295bfa2c111cba996120cfdf8a5d + uses: actions/download-artifact@v4 id: downloadDeltaAPK with: name: delta-apk-${{ needs.buildDelta.outputs.DELTA_REF }} @@ -184,7 +184,7 @@ jobs: - name: Copy e2e code into zip folder run: cp tests/e2e/dist/index.js zip/testRunner.ts - + - name: Copy profiler binaries into zip folder run: cp -r node_modules/@perf-profiler/android/cpp-profiler/bin zip/bin @@ -257,12 +257,12 @@ jobs: - name: Check if test failed, if so post the results and add the DeployBlocker label id: checkIfRegressionDetected run: | - if grep -q 'šŸ”“' ./output.md; then + if grep -q 'šŸ”“' "./Host_Machine_Files/\$WORKING_DIRECTORY/output.md"; then # Create an output to the GH action that the test failed: echo "performanceRegressionDetected=true" >> "$GITHUB_OUTPUT" gh pr edit ${{ inputs.PR_NUMBER }} --add-label DeployBlockerCash - gh pr comment ${{ inputs.PR_NUMBER }} -F ./output.md + gh pr comment ${{ inputs.PR_NUMBER }} -F "./Host_Machine_Files/\$WORKING_DIRECTORY/output.md" gh pr comment ${{ inputs.PR_NUMBER }} -b "@Expensify/mobile-deployers šŸ“£ Please look into this performance regression as it's a deploy blocker." else echo "performanceRegressionDetected=false" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/platformDeploy.yml b/.github/workflows/platformDeploy.yml index 640d1eaa1172..4d204cab9d55 100644 --- a/.github/workflows/platformDeploy.yml +++ b/.github/workflows/platformDeploy.yml @@ -62,7 +62,7 @@ jobs: java-version: '17' - name: Setup Ruby - uses: ruby/setup-ruby@a05e47355e80e57b9a67566a813648fa67d92011 + uses: ruby/setup-ruby@v1.187.0 with: ruby-version: '2.7' bundler-cache: true @@ -80,38 +80,42 @@ jobs: - name: Set version in ENV run: echo "VERSION_CODE=$(grep -o 'versionCode\s\+[0-9]\+' android/app/build.gradle | awk '{ print $2 }')" >> "$GITHUB_ENV" - - name: Run Fastlane beta - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: bundle exec fastlane android beta + - name: Run Fastlane + run: bundle exec fastlane android ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} env: + RUBYOPT: '-rostruct' MYAPP_UPLOAD_STORE_PASSWORD: ${{ secrets.MYAPP_UPLOAD_STORE_PASSWORD }} MYAPP_UPLOAD_KEY_PASSWORD: ${{ secrets.MYAPP_UPLOAD_KEY_PASSWORD }} - - - name: Run Fastlane production - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: bundle exec fastlane android production - env: VERSION: ${{ env.VERSION_CODE }} - name: Archive Android sourcemaps - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: android-sourcemap-${{ github.ref_name }} path: android/app/build/generated/sourcemaps/react/productionRelease/index.android.bundle.map - - name: Upload Android version to GitHub artifacts + - name: Upload Android build to GitHub artifacts if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: app-production-release.aab path: android/app/build/outputs/bundle/productionRelease/app-production-release.aab - - name: Upload Android version to Browser Stack + - name: Upload Android build to Browser Stack if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} run: curl -u "$BROWSERSTACK" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@./android/app/build/outputs/bundle/productionRelease/app-production-release.aab" env: BROWSERSTACK: ${{ secrets.BROWSERSTACK }} + - name: Upload Android build to GitHub Release + if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: | + RUN_ID="$(gh run list --workflow platformDeploy.yml --event push --branch ${{ github.event.release.tag_name }} --json databaseId --jq '.[0].databaseId')" + gh run download "$RUN_ID" --name app-production-release.aab + gh release upload ${{ github.event.release.tag_name }} app-production-release.aab + env: + GITHUB_TOKEN: ${{ github.token }} + - name: Warn deployers if Android production deploy failed if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} uses: 8398a7/action-slack@v3 @@ -147,9 +151,13 @@ jobs: env: DEVELOPER_ID_SECRET_PASSPHRASE: ${{ secrets.DEVELOPER_ID_SECRET_PASSPHRASE }} - - name: Build production desktop app - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: npm run desktop-build + - name: Build desktop app + run: | + if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then + npm run desktop-build + else + npm run desktop-build-staging + fi env: CSC_LINK: ${{ secrets.CSC_LINK }} CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} @@ -159,18 +167,17 @@ jobs: AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} GCP_GEOLOCATION_API_KEY: $${{ secrets.GCP_GEOLOCATION_API_KEY_PRODUCTION }} + - name: Upload desktop build to GitHub Workflow + uses: actions/upload-artifact@v4 + with: + name: NewExpensify.dmg + path: desktop-build/NewExpensify.dmg - - name: Build staging desktop app - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: npm run desktop-build-staging + - name: Upload desktop build to GitHub Release + if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: gh release upload ${{ github.event.release.tag_name }} desktop-build/NewExpensify.dmg env: - CSC_LINK: ${{ secrets.CSC_LINK }} - CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - GCP_GEOLOCATION_API_KEY: $${{ secrets.GCP_GEOLOCATION_API_KEY_STAGING }} + GITHUB_TOKEN: ${{ github.token }} iOS: name: Build and deploy iOS @@ -191,7 +198,7 @@ jobs: uses: ./.github/actions/composite/setupNode - name: Setup Ruby - uses: ruby/setup-ruby@a05e47355e80e57b9a67566a813648fa67d92011 + uses: ruby/setup-ruby@v1.187.0 with: ruby-version: '2.7' bundler-cache: true @@ -236,43 +243,45 @@ jobs: env: LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} + - name: Set iOS version in ENV + run: echo "IOS_VERSION=$(echo '${{ github.event.release.tag_name }}' | tr '-' '.')" >> "$GITHUB_ENV" + - name: Run Fastlane - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: bundle exec fastlane ios beta + run: bundle exec fastlane ios ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) && 'production' || 'beta' }} env: APPLE_CONTACT_EMAIL: ${{ secrets.APPLE_CONTACT_EMAIL }} APPLE_CONTACT_PHONE: ${{ secrets.APPLE_CONTACT_PHONE }} APPLE_DEMO_EMAIL: ${{ secrets.APPLE_DEMO_EMAIL }} APPLE_DEMO_PASSWORD: ${{ secrets.APPLE_DEMO_PASSWORD }} + VERSION: ${{ env.IOS_VERSION }} - name: Archive iOS sourcemaps - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ios-sourcemap-${{ github.ref_name }} path: main.jsbundle.map - - name: Upload iOS version to GitHub artifacts + - name: Upload iOS build to GitHub artifacts if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: New Expensify.ipa path: /Users/runner/work/App/App/New Expensify.ipa - - name: Upload iOS version to Browser Stack + - name: Upload iOS build to Browser Stack if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} run: curl -u "$BROWSERSTACK" -X POST "https://api-cloud.browserstack.com/app-live/upload" -F "file=@/Users/runner/work/App/App/New Expensify.ipa" env: BROWSERSTACK: ${{ secrets.BROWSERSTACK }} - - name: Set iOS version in ENV - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: echo "IOS_VERSION=$(echo '${{ github.event.release.tag_name }}' | tr '-' '.')" >> "$GITHUB_ENV" - - - name: Run Fastlane for App Store release + - name: Upload iOS build to GitHub Release if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: bundle exec fastlane ios production + run: | + RUN_ID="$(gh run list --workflow platformDeploy.yml --event push --branch ${{ github.event.release.tag_name }} --json databaseId --jq '.[0].databaseId')" + gh run download "$RUN_ID" --name 'New Expensify.ipa' + gh release upload ${{ github.event.release.tag_name }} 'New Expensify.ipa' env: - VERSION: ${{ env.IOS_VERSION }} + GITHUB_TOKEN: ${{ github.token }} - name: Warn deployers if iOS production deploy failed if: ${{ failure() && fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} @@ -314,43 +323,68 @@ jobs: aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-east-1 - - name: Build web for production - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: npm run build - - - name: Build web for staging - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: npm run build-staging + - name: Build web + run: | + if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then + npm run build + else + npm run build-staging + fi - - name: Build storybook docs for production - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: npm run storybook-build + - name: Build storybook docs continue-on-error: true + run: | + if [[ ${{ env.SHOULD_DEPLOY_PRODUCTION }} == 'true' ]]; then + npm run storybook-build + else + npm run storybook-build-staging + fi - - name: Build storybook docs for staging - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: npm run storybook-build-staging - continue-on-error: true + - name: Deploy to S3 + run: | + aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist ${{ env.S3_URL }}/ + aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE ${{ env.S3_URL }}/.well-known/apple-app-site-association ${{ env.S3_URL }}/.well-known/apple-app-site-association + aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE ${{ env.S3_URL }}/.well-known/apple-app-site-association ${{env.S3_URL }}/apple-app-site-association + env: + S3_URL: s3://${{ env.SHOULD_DEPLOY_PRODUCTION != 'true' && 'staging-' || '' }}expensify-cash - - name: Deploy production to S3 - if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist s3://expensify-cash/ && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://expensify-cash/.well-known/apple-app-site-association s3://expensify-cash/.well-known/apple-app-site-association && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://expensify-cash/.well-known/apple-app-site-association s3://expensify-cash/apple-app-site-association + - name: Purge Cloudflare cache + run: /home/runner/.local/bin/cli4 --verbose --delete hosts=["${{ env.SHOULD_DEPLOY_PRODUCTION != 'true' && 'staging.' || '' }}new.expensify.com"] /zones/:9ee042e6cfc7fd45e74aa7d2f78d617b/purge_cache + env: + CF_API_KEY: ${{ secrets.CLOUDFLARE_TOKEN }} - - name: Deploy staging to S3 + - name: Verify staging deploy if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist s3://staging-expensify-cash/ && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://staging-expensify-cash/.well-known/apple-app-site-association s3://staging-expensify-cash/.well-known/apple-app-site-association && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://staging-expensify-cash/.well-known/apple-app-site-association s3://staging-expensify-cash/apple-app-site-association + run: | + DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://staging.new.expensify.com/version.json | jq -r '.version')" + if [[ '${{ github.ref_name }}' != "$DOWNLOADED_VERSION" ]]; then + echo "Error: deployed version does not match local version. Something went wrong..." + exit 1 + fi - - name: Purge production Cloudflare cache + - name: Verify production deploy if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: /home/runner/.local/bin/cli4 --verbose --delete hosts=["new.expensify.com"] /zones/:9ee042e6cfc7fd45e74aa7d2f78d617b/purge_cache - env: - CF_API_KEY: ${{ secrets.CLOUDFLARE_TOKEN }} + run: | + DOWNLOADED_VERSION="$(wget -q -O /dev/stdout https://new.expensify.com/version.json | jq -r '.version')" + if [[ '${{ github.event.release.tag_name }}' != "$DOWNLOADED_VERSION" ]]; then + echo "Error: deployed version does not match local version. Something went wrong..." + exit 1 + fi - - name: Purge staging Cloudflare cache - if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} - run: /home/runner/.local/bin/cli4 --verbose --delete hosts=["staging.new.expensify.com"] /zones/:9ee042e6cfc7fd45e74aa7d2f78d617b/purge_cache + - name: Upload web build to GitHub artifacts + uses: actions/upload-artifact@v4 + with: + name: web-build + path: dist + + - name: Upload web build to GitHub Release + if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }} + run: | + tar -czvf webBuild.tar.gz dist + zip -r webBuild.zip dist + gh release upload ${{ github.event.release.tag_name }} webBuild.tar.gz webBuild.zip env: - CF_API_KEY: ${{ secrets.CLOUDFLARE_TOKEN }} + GITHUB_TOKEN: ${{ github.token }} postSlackMessageOnFailure: name: Post a Slack message when any platform fails to build or deploy diff --git a/.github/workflows/preDeploy.yml b/.github/workflows/preDeploy.yml index f09865de0194..bb1cd71c9518 100644 --- a/.github/workflows/preDeploy.yml +++ b/.github/workflows/preDeploy.yml @@ -32,7 +32,9 @@ jobs: - name: Exit failed workflow if: ${{ needs.typecheck.result == 'failure' || needs.lint.result == 'failure' || needs.test.result == 'failure' }} - run: exit 1 + run: | + echo "Checks failed, exiting ~ typecheck: ${{ needs.typecheck.result }}, lint: ${{ needs.lint.result }}, test: ${{ needs.test.result }}" + exit 1 chooseDeployActions: runs-on: ubuntu-latest diff --git a/.github/workflows/proposalPolice.yml b/.github/workflows/proposalPolice.yml new file mode 100644 index 000000000000..aabf2fb4f6f1 --- /dev/null +++ b/.github/workflows/proposalPolice.yml @@ -0,0 +1,21 @@ +name: ProposalPoliceā„¢ - Issue Comment Workflow +on: + issue_comment: + types: [created, edited] + +jobs: + proposal-police-workflow: + runs-on: ubuntu-latest + if: "!contains(fromJSON('[\"OSBotify\", \"imgbot[bot]\", \"melvin-bot[bot]\"]'), github.actor)" + steps: + - uses: actions/checkout@v4 + + # Checks if the comment is created and follows the template OR + # if the comment is edited and if proposal template is followed. + # Action type logic can be found in the script files. + - name: Run ProposalPoliceā„¢ Comment Check Script + uses: ./.github/actions/javascript/proposalPoliceComment + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PROPOSAL_POLICE_API_KEY: ${{ secrets.PROPOSAL_POLICE_API_KEY }} + PROPOSAL_POLICE_ASSISTANT_ID: ${{ secrets.PROPOSAL_POLICE_ASSISTANT_ID }} diff --git a/.github/workflows/reassurePerformanceTests.yml b/.github/workflows/reassurePerformanceTests.yml index a2aadc331f19..a0489a52711b 100644 --- a/.github/workflows/reassurePerformanceTests.yml +++ b/.github/workflows/reassurePerformanceTests.yml @@ -47,12 +47,12 @@ jobs: BASELINE_BRANCH=${BASELINE_BRANCH:="main"} git fetch origin "$BASELINE_BRANCH" --no-tags --depth=1 git switch "$BASELINE_BRANCH" - npm install --force + npm install --force || (rm -rf node_modules && npm install --force) NODE_OPTIONS=--experimental-vm-modules npx reassure --baseline git switch --force --detach - git merge --no-commit --allow-unrelated-histories "$BASELINE_BRANCH" -X ours git checkout --ours . - npm install --force + npm install --force || (rm -rf node_modules && npm install --force) NODE_OPTIONS=--experimental-vm-modules npx reassure --branch - name: Validate output.json diff --git a/.github/workflows/sendReassurePerfData.yml b/.github/workflows/sendReassurePerfData.yml index 53b3d3374a9e..30a30918f4f6 100644 --- a/.github/workflows/sendReassurePerfData.yml +++ b/.github/workflows/sendReassurePerfData.yml @@ -25,7 +25,7 @@ jobs: shell: bash run: | set -e - npx reassure --baseline + NODE_OPTIONS=--experimental-vm-modules npx reassure --baseline - name: Get merged pull request id: getMergedPullRequest diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 10912aaeb436..1abe22dc395d 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -88,7 +88,7 @@ jobs: java-version: '17' - name: Setup Ruby - uses: ruby/setup-ruby@a05e47355e80e57b9a67566a813648fa67d92011 + uses: ruby/setup-ruby@v1.187.0 with: ruby-version: '2.7' bundler-cache: true @@ -117,6 +117,7 @@ jobs: id: runFastlaneBetaTest run: bundle exec fastlane android build_internal env: + RUBYOPT: '-rostruct' S3_ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY_ID }} S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} S3_BUCKET: ad-hoc-expensify-cash @@ -125,7 +126,7 @@ jobs: MYAPP_UPLOAD_KEY_PASSWORD: ${{ secrets.MYAPP_UPLOAD_KEY_PASSWORD }} - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: android path: ./android_paths.json @@ -161,7 +162,7 @@ jobs: run: sudo xcode-select -switch /Applications/Xcode_15.0.1.app - name: Setup Ruby - uses: ruby/setup-ruby@a05e47355e80e57b9a67566a813648fa67d92011 + uses: ruby/setup-ruby@v1.187.0 with: ruby-version: '2.7' bundler-cache: true @@ -184,7 +185,7 @@ jobs: with: timeout_minutes: 10 max_attempts: 5 - command: cd ios && bundle exec pod install + command: cd ios && bundle exec pod install --verbose - name: Decrypt AdHoc profile run: cd ios && gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output NewApp_AdHoc.mobileprovision NewApp_AdHoc.mobileprovision.gpg @@ -217,7 +218,7 @@ jobs: S3_REGION: us-east-1 - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: ios path: ./ios_paths.json @@ -321,7 +322,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha || needs.getBranchRef.outputs.REF }} - name: Download Artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 if: ${{ fromJSON(needs.validateActor.outputs.READY_TO_BUILD) }} - name: Read JSONs with android paths diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 476b01f87b07..3bfc0ed28d1a 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -34,7 +34,7 @@ jobs: # - git diff is used to see the files that were added on this branch # - gh pr view is used to list files touched by this PR. Git diff may give false positives if the branch isn't up-to-date with main # - wc counts the words in the result of the intersection - count_new_js=$(comm -1 -2 <(git diff --name-only --diff-filter=A origin/main HEAD -- 'src/*.js' '__mocks__/*.js' '.storybook/*.js' 'assets/*.js' 'config/*.js' 'desktop/*.js' 'jest/*.js' 'scripts/*.js' 'tests/*.js' 'workflow_tests/*.js' '.github/libs/*.js' '.github/scripts/*.js') <(gh pr view ${{ github.event.pull_request.number }} --json files | jq -r '.files | map(.path) | .[]') | wc -l) + count_new_js=$(comm -1 -2 <(git diff --name-only --diff-filter=A origin/main HEAD -- 'src/*.js' '__mocks__/*.js' '.storybook/*.js' 'assets/*.js' 'config/*.js' 'desktop/*.js' 'jest/*.js' 'scripts/*.js' 'tests/*.js' 'workflow_tests/*.js' '.github/libs/*.js' '.github/scripts/*.js' ':!src/libs/SearchParser/*.js') <(gh pr view ${{ github.event.pull_request.number }} --json files | jq -r '.files | map(.path) | .[]') | wc -l) if [ "$count_new_js" -gt "0" ]; then echo "ERROR: Found new JavaScript files in the project; use TypeScript instead." exit 1 diff --git a/.prettierignore b/.prettierignore index 09de20ba30b0..a9f7e1464529 100644 --- a/.prettierignore +++ b/.prettierignore @@ -19,3 +19,6 @@ package-lock.json src/libs/E2E/reactNativeLaunchingTest.ts # Temporary while we keep react-compiler in our repo lib/** + +# Automatically generated files +src/libs/SearchParser/searchParser.js diff --git a/.storybook/fonts.css b/.storybook/fonts.css index 906490c3a9d9..05002d893e61 100644 --- a/.storybook/fonts.css +++ b/.storybook/fonts.css @@ -1,52 +1,59 @@ @font-face { - font-family: ExpensifyNeue-Regular; + font-family: Expensify Neue; font-weight: 400; font-style: normal; src: url('../assets/fonts/web/ExpensifyNeue-Regular.woff2') format('woff2'), url('../assets/fonts/web/ExpensifyNeue-Regular.woff') format('woff'); } @font-face { - font-family: ExpensifyNeue-Regular; + font-family: Expensify Neue; font-weight: 700; font-style: normal; src: url('../assets/fonts/web/ExpensifyNeue-Bold.woff2') format('woff2'), url('../assets/fonts/web/ExpensifyNeue-Bold.woff') format('woff'); } @font-face { - font-family: ExpensifyNeue-Regular; + font-family: Expensify Neue; font-weight: 400; font-style: italic; src: url('../assets/fonts/web/ExpensifyNeue-Italic.woff2') format('woff2'), url('../assets/fonts/web/ExpensifyNeue-Italic.woff') format('woff'); } @font-face { - font-family: ExpensifyNeue-Regular; + font-family: Expensify Neue; font-weight: 700; font-style: italic; src: url('../assets/fonts/web/ExpensifyNeue-BoldItalic.woff2') format('woff2'), url('../assets/fonts/web/ExpensifyNeue-BoldItalic.woff') format('woff'); } @font-face { - font-family: ExpensifyMono-Regular; + font-family: Expensify Mono; font-weight: 400; font-style: normal; src: url('../assets/fonts/web/ExpensifyMono-Regular.woff2') format('woff2'), url('../assets/fonts/web/ExpensifyMono-Regular.woff') format('woff'); } @font-face { - font-family: ExpensifyMono-Bold; + font-family: Expensify Mono; font-weight: 700; font-style: normal; src: url('../assets/fonts/web/ExpensifyMono-Bold.woff2') format('woff2'), url('../assets/fonts/web/ExpensifyMono-Bold.woff') format('woff'); } @font-face { - font-family: ExpensifyNewKansas-Medium; - font-weight: 400; + font-family: Expensify New Kansas; + font-weight: 500; font-style: normal; src: url('../assets/fonts/web/ExpensifyNewKansas-Medium.woff2') format('woff2'), url('../assets/fonts/web/ExpensifyNewKansas-Medium.woff') format('woff'); } +@font-face { + font-family: Expensify New Kansas; + font-weight: 500; + font-style: italic; + src: url('../assets/fonts/web/ExpensifyNewKansas-MediumItalic.woff2') format('woff2'), url('../assets/fonts/web/ExpensifyNewKansas-MediumItalic.woff') format('woff'); +} + * { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; diff --git a/.storybook/theme.ts b/.storybook/theme.ts index 7fc55a549a4a..ace6208bdb3b 100644 --- a/.storybook/theme.ts +++ b/.storybook/theme.ts @@ -6,7 +6,7 @@ import colors from '../src/styles/theme/colors'; const theme: ThemeVars = create({ brandTitle: 'New Expensify UI Docs', brandImage: 'logomark.svg', - fontBase: 'ExpensifyNeue-Regular', + fontBase: 'Expensify Neue', fontCode: 'monospace', base: 'dark', appBg: colors.productDark200, diff --git a/.storybook/webpack.config.ts b/.storybook/webpack.config.ts index a7811a5a387d..0aa38f2e3b82 100644 --- a/.storybook/webpack.config.ts +++ b/.storybook/webpack.config.ts @@ -100,6 +100,11 @@ const webpackConfig = ({config}: {config: Configuration}) => { }), ); + config.module.rules?.push({ + test: /\.lottie$/, + type: 'asset/resource', + }); + return config; }; diff --git a/.well-known/apple-app-site-association b/.well-known/apple-app-site-association index 394e45f8d9ae..dce724440adf 100644 --- a/.well-known/apple-app-site-association +++ b/.well-known/apple-app-site-association @@ -91,6 +91,14 @@ { "/": "/money2020/*", "comment": "Money 2020" + }, + { + "/": "/track-expense/*", + "comment": "Track Expense" + }, + { + "/": "/submit-expense/*", + "comment": "Submit Expense" } ] } diff --git a/android/app/build.gradle b/android/app/build.gradle index d4cc7471a72b..df299757241a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,6 +15,7 @@ fullstory { org 'o-1WN56P-na1' enabledVariants 'all' logcatLevel 'debug' + recordOnStart false } react { @@ -107,8 +108,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009000600 - versionName "9.0.6-0" + versionCode 1009001401 + versionName "9.0.14-1" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 520602a28a02..142d919a7a18 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -73,6 +73,8 @@ + + @@ -94,6 +96,8 @@ + + diff --git a/android/app/src/main/java/com/expensify/chat/MainApplication.kt b/android/app/src/main/java/com/expensify/chat/MainApplication.kt index e660a871359d..dac9e68b705b 100644 --- a/android/app/src/main/java/com/expensify/chat/MainApplication.kt +++ b/android/app/src/main/java/com/expensify/chat/MainApplication.kt @@ -1,5 +1,7 @@ package com.expensify.chat +import com.facebook.react.common.assets.ReactFontManager + import android.app.ActivityManager import android.content.res.Configuration import android.database.CursorWindow @@ -42,6 +44,9 @@ class MainApplication : MultiDexApplication(), ReactApplication { override fun onCreate() { super.onCreate() + ReactFontManager.getInstance().addCustomFont(this, "Expensify New Kansas", R.font.expensify_new_kansas) + ReactFontManager.getInstance().addCustomFont(this, "Expensify Neue", R.font.expensify_neue) + ReactFontManager.getInstance().addCustomFont(this, "Expensify Mono", R.font.expensify_mono) RNPerformance.getInstance().mark("appCreationStart", false); diff --git a/android/app/src/main/res/font/expensify_mono.xml b/android/app/src/main/res/font/expensify_mono.xml new file mode 100644 index 000000000000..346a34ba22b6 --- /dev/null +++ b/android/app/src/main/res/font/expensify_mono.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/app/src/main/res/font/expensify_neue.xml b/android/app/src/main/res/font/expensify_neue.xml new file mode 100644 index 000000000000..74cd402c5535 --- /dev/null +++ b/android/app/src/main/res/font/expensify_neue.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/android/app/src/main/res/font/expensify_new_kansas.xml b/android/app/src/main/res/font/expensify_new_kansas.xml new file mode 100644 index 000000000000..18c2426cdad2 --- /dev/null +++ b/android/app/src/main/res/font/expensify_new_kansas.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/app/src/main/assets/fonts/ExpensifyMono-Bold.otf b/android/app/src/main/res/font/expensifymono_bold.otf similarity index 100% rename from android/app/src/main/assets/fonts/ExpensifyMono-Bold.otf rename to android/app/src/main/res/font/expensifymono_bold.otf diff --git a/android/app/src/main/assets/fonts/ExpensifyMono-Regular.otf b/android/app/src/main/res/font/expensifymono_regular.otf similarity index 100% rename from android/app/src/main/assets/fonts/ExpensifyMono-Regular.otf rename to android/app/src/main/res/font/expensifymono_regular.otf diff --git a/android/app/src/main/assets/fonts/ExpensifyNeue-Bold.otf b/android/app/src/main/res/font/expensifyneue_bold.otf similarity index 100% rename from android/app/src/main/assets/fonts/ExpensifyNeue-Bold.otf rename to android/app/src/main/res/font/expensifyneue_bold.otf diff --git a/android/app/src/main/assets/fonts/ExpensifyNeue-BoldItalic.otf b/android/app/src/main/res/font/expensifyneue_bolditalic.otf similarity index 100% rename from android/app/src/main/assets/fonts/ExpensifyNeue-BoldItalic.otf rename to android/app/src/main/res/font/expensifyneue_bolditalic.otf diff --git a/android/app/src/main/assets/fonts/ExpensifyNeue-Italic.otf b/android/app/src/main/res/font/expensifyneue_italic.otf similarity index 100% rename from android/app/src/main/assets/fonts/ExpensifyNeue-Italic.otf rename to android/app/src/main/res/font/expensifyneue_italic.otf diff --git a/android/app/src/main/assets/fonts/ExpensifyNeue-Regular.otf b/android/app/src/main/res/font/expensifyneue_regular.otf similarity index 100% rename from android/app/src/main/assets/fonts/ExpensifyNeue-Regular.otf rename to android/app/src/main/res/font/expensifyneue_regular.otf diff --git a/android/app/src/main/assets/fonts/ExpensifyNewKansas-Medium.otf b/android/app/src/main/res/font/expensifynewkansas_medium.otf similarity index 100% rename from android/app/src/main/assets/fonts/ExpensifyNewKansas-Medium.otf rename to android/app/src/main/res/font/expensifynewkansas_medium.otf diff --git a/android/app/src/main/assets/fonts/ExpensifyNewKansas-MediumItalic.otf b/android/app/src/main/res/font/expensifynewkansas_mediumitalic.otf similarity index 100% rename from android/app/src/main/assets/fonts/ExpensifyNewKansas-MediumItalic.otf rename to android/app/src/main/res/font/expensifynewkansas_mediumitalic.otf diff --git a/android/app/src/main/res/font/expneuebold.otf b/android/app/src/main/res/font/expneuebold.otf deleted file mode 100755 index 7534aecda322..000000000000 Binary files a/android/app/src/main/res/font/expneuebold.otf and /dev/null differ diff --git a/android/app/src/main/res/font/expneueregular.otf b/android/app/src/main/res/font/expneueregular.otf deleted file mode 100755 index d4d8cbe63b44..000000000000 Binary files a/android/app/src/main/res/font/expneueregular.otf and /dev/null differ diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index a040598e982d..75126afbd407 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -24,7 +24,7 @@ @@ -37,15 +37,15 @@ \ No newline at end of file diff --git a/assets/images/calendar-solid.svg b/assets/images/calendar-solid.svg new file mode 100644 index 000000000000..168aabaa4a49 --- /dev/null +++ b/assets/images/calendar-solid.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/assets/images/circular-arrow-backwards.svg b/assets/images/circular-arrow-backwards.svg index 209c0aea5fa7..7dab140cf78b 100644 --- a/assets/images/circular-arrow-backwards.svg +++ b/assets/images/circular-arrow-backwards.svg @@ -1,9 +1 @@ - - - - - + \ No newline at end of file diff --git a/assets/images/emptystate__expensifycard.svg b/assets/images/emptystate__expensifycard.svg new file mode 100644 index 000000000000..c5699c059e69 --- /dev/null +++ b/assets/images/emptystate__expensifycard.svg @@ -0,0 +1,909 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/product-illustrations/folder-with-papers.svg b/assets/images/product-illustrations/folder-with-papers.svg index 3d00fb147ccd..c0c35bc9b4ba 100644 --- a/assets/images/product-illustrations/folder-with-papers.svg +++ b/assets/images/product-illustrations/folder-with-papers.svg @@ -1,33 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/assets/images/simple-illustrations/simple-illustration__empty-state.svg b/assets/images/simple-illustrations/simple-illustration__empty-state.svg index 154b2269c285..2aeb9e8f4fb5 100644 --- a/assets/images/simple-illustrations/simple-illustration__empty-state.svg +++ b/assets/images/simple-illustrations/simple-illustration__empty-state.svg @@ -1,102 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/assets/images/simple-illustrations/simple-illustration__receipt-location-marker.svg b/assets/images/simple-illustrations/simple-illustration__receipt-location-marker.svg new file mode 100644 index 000000000000..1c2bb43a04ab --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__receipt-location-marker.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/simple-illustrations/simple-illustration__tire.svg b/assets/images/simple-illustrations/simple-illustration__tire.svg new file mode 100644 index 000000000000..db84f054568a --- /dev/null +++ b/assets/images/simple-illustrations/simple-illustration__tire.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/images/simple-illustrations/simple-illustration__virtualcard.svg b/assets/images/simple-illustrations/simple-illustration__virtualcard.svg index 2c1f538102a2..6a96a874b97e 100644 --- a/assets/images/simple-illustrations/simple-illustration__virtualcard.svg +++ b/assets/images/simple-illustrations/simple-illustration__virtualcard.svg @@ -1,48 +1 @@ - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/babel.config.js b/babel.config.js index 7010404f2a31..dcf12ba4d91e 100644 --- a/babel.config.js +++ b/babel.config.js @@ -4,6 +4,9 @@ const IS_E2E_TESTING = process.env.E2E_TESTING === 'true'; const ReactCompilerConfig = { runtimeModule: 'react-compiler-runtime', + environment: { + enableTreatRefLikeIdentifiersAsRefs: true, + }, }; const defaultPresets = ['@babel/preset-react', '@babel/preset-env', '@babel/preset-flow', '@babel/preset-typescript']; const defaultPlugins = [ diff --git a/contributingGuides/CONTRIBUTING.md b/contributingGuides/CONTRIBUTING.md index d6ab46c809ef..0ddaafda2d82 100644 --- a/contributingGuides/CONTRIBUTING.md +++ b/contributingGuides/CONTRIBUTING.md @@ -31,15 +31,6 @@ This project and everyone participating in it is governed by the Expensify [Code ## Restrictions At this time, we are not hiring contractors in Crimea, North Korea, Russia, Iran, Cuba, or Syria. -## Slack channels -All contributors should be a member of a shared Slack channel called [#expensify-open-source](https://expensify.slack.com/archives/C01GTK53T8Q) -- this channel is used to ask **general questions**, facilitate **discussions**, and make **feature requests**. - -Before requesting an invite to Slack, please ensure your Upwork account is active, since we only pay via Upwork (see [below](https://github.com/Expensify/App/blob/main/contributingGuides/CONTRIBUTING.md#payment-for-contributions)). To request an invite to Slack, email contributors@expensify.com with the subject `Slack Channel Invites`. We'll send you an invite! - -Note: Do not send direct messages to the Expensify team in Slack or Expensify Chat, they will not be able to respond. - -Note: if you are hired for an Upwork job and have any job-specific questions, please ask in the GitHub issue or pull request. This will ensure that the person addressing your question has as much context as possible. - ## Reporting Vulnerabilities If you've found a vulnerability, please email security@expensify.com with the subject `Vulnerability Report` instead of creating an issue. diff --git a/docs/Gemfile b/docs/Gemfile index 91971b594b4f..73ced17fea02 100644 --- a/docs/Gemfile +++ b/docs/Gemfile @@ -8,7 +8,8 @@ source "https://rubygems.org" # This will help ensure the proper Jekyll version is running. # Happy Jekylling! -gem "github-pages", group: :jekyll_plugins +gem 'jekyll', group: :jekyll_plugins +gem 'kramdown-parser-gfm' # If you have any plugins, put them here! group :jekyll_plugins do diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index de99bbcb48ef..4c492ae1e251 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -1,91 +1,16 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.5) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - zeitwerk (~> 2.2, >= 2.2.2) addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) - coffee-script (2.4.1) - coffee-script-source - execjs - coffee-script-source (1.11.1) colorator (1.1.0) - commonmarker (0.23.10) concurrent-ruby (1.1.10) - dnsruby (1.61.9) - simpleidn (~> 0.1) em-websocket (0.5.3) eventmachine (>= 0.12.9) http_parser.rb (~> 0) - ethon (0.15.0) - ffi (>= 1.15.0) eventmachine (1.2.7) - execjs (2.8.1) - faraday (2.3.0) - faraday-net_http (~> 2.0) - ruby2_keywords (>= 0.0.4) - faraday-net_http (2.0.3) ffi (1.15.5) forwardable-extended (2.6.0) - gemoji (3.0.1) - github-pages (228) - github-pages-health-check (= 1.17.9) - jekyll (= 3.9.3) - jekyll-avatar (= 0.7.0) - jekyll-coffeescript (= 1.1.1) - jekyll-commonmark-ghpages (= 0.4.0) - jekyll-default-layout (= 0.1.4) - jekyll-feed (= 0.15.1) - jekyll-gist (= 1.5.0) - jekyll-github-metadata (= 2.13.0) - jekyll-include-cache (= 0.2.1) - jekyll-mentions (= 1.6.0) - jekyll-optional-front-matter (= 0.3.2) - jekyll-paginate (= 1.1.0) - jekyll-readme-index (= 0.3.0) - jekyll-redirect-from (= 0.16.0) - jekyll-relative-links (= 0.6.1) - jekyll-remote-theme (= 0.4.3) - jekyll-sass-converter (= 1.5.2) - jekyll-seo-tag (= 2.8.0) - jekyll-sitemap (= 1.4.0) - jekyll-swiss (= 1.0.0) - jekyll-theme-architect (= 0.2.0) - jekyll-theme-cayman (= 0.2.0) - jekyll-theme-dinky (= 0.2.0) - jekyll-theme-hacker (= 0.2.0) - jekyll-theme-leap-day (= 0.2.0) - jekyll-theme-merlot (= 0.2.0) - jekyll-theme-midnight (= 0.2.0) - jekyll-theme-minimal (= 0.2.0) - jekyll-theme-modernist (= 0.2.0) - jekyll-theme-primer (= 0.6.0) - jekyll-theme-slate (= 0.2.0) - jekyll-theme-tactile (= 0.2.0) - jekyll-theme-time-machine (= 0.2.0) - jekyll-titles-from-headings (= 0.5.3) - jemoji (= 0.12.0) - kramdown (= 2.3.2) - kramdown-parser-gfm (= 1.1.0) - liquid (= 4.0.4) - mercenary (~> 0.3) - minima (= 2.5.1) - nokogiri (>= 1.13.6, < 2.0) - rouge (= 3.26.0) - terminal-table (~> 1.4) - github-pages-health-check (1.17.9) - addressable (~> 2.3) - dnsruby (~> 1.60) - octokit (~> 4.0) - public_suffix (>= 3.0, < 5.0) - typhoeus (~> 1.3) - html-pipeline (2.14.2) - activesupport (>= 2) - nokogiri (>= 1.4) http_parser.rb (0.8.0) i18n (0.9.5) concurrent-ruby (~> 1.0) @@ -102,101 +27,16 @@ GEM pathutil (~> 0.9) rouge (>= 1.7, < 4) safe_yaml (~> 1.0) - jekyll-avatar (0.7.0) - jekyll (>= 3.0, < 5.0) - jekyll-coffeescript (1.1.1) - coffee-script (~> 2.2) - coffee-script-source (~> 1.11.1) - jekyll-commonmark (1.4.0) - commonmarker (~> 0.22) - jekyll-commonmark-ghpages (0.4.0) - commonmarker (~> 0.23.7) - jekyll (~> 3.9.0) - jekyll-commonmark (~> 1.4.0) - rouge (>= 2.0, < 5.0) - jekyll-default-layout (0.1.4) - jekyll (~> 3.0) jekyll-feed (0.15.1) jekyll (>= 3.7, < 5.0) - jekyll-gist (1.5.0) - octokit (~> 4.2) - jekyll-github-metadata (2.13.0) - jekyll (>= 3.4, < 5.0) - octokit (~> 4.0, != 4.4.0) - jekyll-include-cache (0.2.1) - jekyll (>= 3.7, < 5.0) - jekyll-mentions (1.6.0) - html-pipeline (~> 2.3) - jekyll (>= 3.7, < 5.0) - jekyll-optional-front-matter (0.3.2) - jekyll (>= 3.0, < 5.0) - jekyll-paginate (1.1.0) - jekyll-readme-index (0.3.0) - jekyll (>= 3.0, < 5.0) jekyll-redirect-from (0.16.0) jekyll (>= 3.3, < 5.0) - jekyll-relative-links (0.6.1) - jekyll (>= 3.3, < 5.0) - jekyll-remote-theme (0.4.3) - addressable (~> 2.0) - jekyll (>= 3.5, < 5.0) - jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) - rubyzip (>= 1.3.0, < 3.0) jekyll-sass-converter (1.5.2) sass (~> 3.4) jekyll-seo-tag (2.8.0) jekyll (>= 3.8, < 5.0) - jekyll-sitemap (1.4.0) - jekyll (>= 3.7, < 5.0) - jekyll-swiss (1.0.0) - jekyll-theme-architect (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-cayman (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-dinky (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-hacker (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-leap-day (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-merlot (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-midnight (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-minimal (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-modernist (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-primer (0.6.0) - jekyll (> 3.5, < 5.0) - jekyll-github-metadata (~> 2.9) - jekyll-seo-tag (~> 2.0) - jekyll-theme-slate (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-tactile (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-theme-time-machine (0.2.0) - jekyll (> 3.5, < 5.0) - jekyll-seo-tag (~> 2.0) - jekyll-titles-from-headings (0.5.3) - jekyll (>= 3.3, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - jemoji (0.12.0) - gemoji (~> 3.0) - html-pipeline (~> 2.2) - jekyll (>= 3.0, < 5.0) kramdown (2.3.2) rexml kramdown-parser-gfm (1.1.0) @@ -206,53 +46,21 @@ GEM rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) mercenary (0.3.6) - minima (2.5.1) - jekyll (>= 3.5, < 5.0) - jekyll-feed (~> 0.9) - jekyll-seo-tag (~> 2.1) - minitest (5.16.2) - nokogiri (1.15.4-arm64-darwin) - racc (~> 1.4) - nokogiri (1.15.4-x86_64-darwin) - racc (~> 1.4) - octokit (4.25.1) - faraday (>= 1, < 3) - sawyer (~> 0.9) pathutil (0.16.2) forwardable-extended (~> 2.6) public_suffix (4.0.7) - racc (1.6.0) rb-fsevent (0.11.1) rb-inotify (0.10.1) ffi (~> 1.0) rexml (3.2.5) rouge (3.26.0) - ruby2_keywords (0.0.5) - rubyzip (2.3.2) safe_yaml (1.0.5) sass (3.7.4) sass-listen (~> 4.0.0) sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sawyer (0.9.2) - addressable (>= 2.3.5) - faraday (>= 0.17.3, < 3) - simpleidn (0.2.1) - unf (~> 0.1.4) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - thread_safe (0.3.6) - typhoeus (1.4.0) - ethon (>= 0.9.0) - tzinfo (1.2.9) - thread_safe (~> 0.1) - unf (0.1.4) - unf_ext - unf_ext (0.0.8.2) - unicode-display_width (1.8.0) webrick (1.7.0) - zeitwerk (2.6.0) PLATFORMS arm64-darwin-22 @@ -261,11 +69,12 @@ PLATFORMS x86_64-darwin-21 DEPENDENCIES - github-pages http_parser.rb (~> 0.6.0) + jekyll jekyll-feed (~> 0.12) jekyll-redirect-from jekyll-seo-tag + kramdown-parser-gfm liquid (~> 4.0.4) tzinfo (~> 1.2) tzinfo-data diff --git a/docs/_config.yml b/docs/_config.yml index 888f0b24a91e..36eea67ad2de 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -6,6 +6,7 @@ author: Expensify logo: /assets/images/expensify-help.svg repository: Expensify/App open_url: true +main_style: /assets/css/styles.css defaults: - scope: @@ -22,3 +23,4 @@ plugins: whitelist: - jekyll-redirect-from + - jekyll-seo-tag diff --git a/docs/_data/_routes.yml b/docs/_data/_routes.yml index 7f416951b58c..85ffbb30c360 100644 --- a/docs/_data/_routes.yml +++ b/docs/_data/_routes.yml @@ -69,8 +69,8 @@ platforms: icon: /assets/images/handshake.svg description: Discover the benefits of becoming an Expensify Partner. - - href: integrations - title: Integrations + - href: connections + title: Connections icon: /assets/images/simple-illustration__monitor-remotesync.svg description: Integrate with accounting or HR software to streamline expense approvals. diff --git a/docs/_includes/hub.html b/docs/_includes/hub.html index 7f1e25243c09..32d81d88e981 100644 --- a/docs/_includes/hub.html +++ b/docs/_includes/hub.html @@ -4,21 +4,24 @@ {% assign activeHub = page.url | remove: activePlatform | remove: "/hubs/" | remove: "/" | remove: ".html" %} {% assign hub = platform.hubs | where: "href", activeHub | first %} -

- {{ hub.title }} -

+

{{ hub.title }}

-

- {{ hub.description }} -

+

{{ hub.description }}

+ +{% if hub.articles %} + {% assign sortedSectionsAndArticles = hub.sections | concat: hub.articles | sort: 'title' %} +{% else %} + {% assign sortedSectionsAndArticles = hub.sections | sort: 'title' %} +{% endif%}
- {% for section in hub.sections %} - {% include section-card.html platform=activePlatform hub=hub.href section=section.href title=section.title %} - {% endfor %} - {% for article in hub.articles %} - {% include article-card.html hub=hub.href href=article.href title=article.title platform=activePlatform %} + {% for item in sortedSectionsAndArticles %} + {% if item.articles %} + {% include section-card.html platform=activePlatform hub=hub.href section=item.href title=item.title %} + {% else %} + {% include article-card.html hub=hub.href href=item.href title=item.title platform=activePlatform %} + {% endif %} {% endfor %}
diff --git a/docs/_includes/lhn-template.html b/docs/_includes/lhn-template.html index 32078c1a8de6..294094214c8e 100644 --- a/docs/_includes/lhn-template.html +++ b/docs/_includes/lhn-template.html @@ -33,31 +33,35 @@ {{ hub.title }}
    - {% for section in hub.sections %} -
  • - {% if section.href == activeSection %} - -
      - {% for article in section.articles %} - {% assign article_href = section.href | append: '/' | append: article.href %} - {% include lhn-article-link.html platform=activePlatform hub=hub.href href=article_href title=article.title %} - {% endfor %} -
    - {% else %} - - - {{ section.title }} - - {% endif %} - -
  • - {% endfor %} - - {% for article in hub.articles %} - {% include lhn-article-link.html platform=activePlatform hub=hub.href href=article.href title=article.title %} + {% if hub.articles %} + {% assign sortedSectionsAndArticles = hub.sections | concat: hub.articles | sort: 'title' %} + {% else %} + {% assign sortedSectionsAndArticles = hub.sections | sort: 'title' %} + {% endif%} + {% for item in sortedSectionsAndArticles %} + {% if item.articles %} +
  • + {% if item.href == activeSection %} + +
      + {% for article in item.articles %} + {% assign article_href = item.href | append: '/' | append: article.href %} + {% include lhn-article-link.html platform=activePlatform hub=hub.href href=article_href title=article.title %} + {% endfor %} +
    + {% else %} + + + {{ item.title }} + + {% endif %} +
  • + {% else %} + {% include lhn-article-link.html platform=activePlatform hub=hub.href href=item.href title=item.title %} + {% endif %} {% endfor %}
{% else %} diff --git a/docs/_includes/section.html b/docs/_includes/section.html index 786e7d997462..cd48a40585be 100644 --- a/docs/_includes/section.html +++ b/docs/_includes/section.html @@ -15,9 +15,12 @@

- {% for article in section.articles %} - {% assign article_href = section.href | append: '/' | append: article.href %} - {% include article-card.html hub=hub.href href=article_href title=article.title platform=activePlatform %} - {% endfor %} + {% if section.articles %} + {% assign sortedArticles = section.articles | sort: 'order', 'last' | default: 999 %} + {% for article in sortedArticles %} + {% assign article_href = section.href | append: '/' | append: article.href %} + {% include article-card.html hub=hub.href href=article_href title=article.title platform=activePlatform %} + {% endfor %} + {% endif %}
diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index cc45e83efa59..472887177e74 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -5,15 +5,15 @@ Expensify Help - - + + - - - + + + diff --git a/docs/_plugins/cache_bust_filter.rb b/docs/_plugins/cache_bust_filter.rb new file mode 100644 index 000000000000..abb1545fdd28 --- /dev/null +++ b/docs/_plugins/cache_bust_filter.rb @@ -0,0 +1,64 @@ +require 'digest' + +module Jekyll + module CacheBustFilter + def cache_bust(input) + puts "Processing asset: #{input}" + + # Get the file extension + ext = File.extname(input) + puts "File extension: #{ext}" + + # Define a list of supported asset types + supported_assets = %w[.css .js .png .jpg .jpeg .gif .svg .woff .woff2 .ttf .eot] + + # Check if the asset type is supported + if supported_assets.include?(ext) + puts "Asset type supported: #{ext}" + + # Compute the file hash + site_source = @context.registers[:site].source + puts "Site destination directory: #{site_source}" + + file_path = File.join(site_source, input) + puts "Constructed file path: #{file_path}" + + if File.exist?(file_path) + puts "File exists: #{file_path}" + + file_content = File.read(file_path) + file_hash = Digest::MD5.hexdigest(file_content) + puts "File hash: #{file_hash}" + "#{input}?v=#{file_hash}" + else + if input == @context.registers[:site].config['main_style'] + puts "Digesting contents of _sass folder" + sass_folder_path = File.join(site_source, '_sass') + directory_hash = digest_directory_contents(sass_folder_path) + puts "Directory hash: #{directory_hash}" + "#{input}?v=#{directory_hash}" + else + puts "File does not exist: #{file_path}" + # Return the input unchanged if the file does not exist + input + end + end + else + puts "Asset type not supported: #{ext}" + # Return the input unchanged if the asset type is not supported + input + end + end + + private + + def digest_directory_contents(directory) + target_path = File.join(directory, '**', '*') + content = Dir[target_path].map { |f| File.read(f) unless File.directory?(f) }.join + Digest::MD5.hexdigest(content) + end + + end +end + +Liquid::Template.register_filter(Jekyll::CacheBustFilter) \ No newline at end of file diff --git a/docs/_sass/_fonts.scss b/docs/_sass/_fonts.scss index cf905805ddd2..c62d15720197 100644 --- a/docs/_sass/_fonts.scss +++ b/docs/_sass/_fonts.scss @@ -1,26 +1,26 @@ @font-face { - font-family: ExpensifyNeue; + font-family: Expensify Neue; font-weight: 400; font-style: normal; src: url('/assets/fonts/ExpensifyNeue-Regular.woff2') format('woff2'), url('/assets/fonts/ExpensifyNeue-Regular.woff') format('woff'); } @font-face { - font-family: ExpensifyNeue; + font-family: Expensify Neue; font-weight: 700; font-style: bold; src: url('/assets/fonts/ExpensifyNeue-Bold.woff2') format('woff2'), url('/assets/fonts/ExpensifyNeue-Bold.woff') format('woff'); } @font-face { - font-family: ExpensifyNewKansas; + font-family: Expensify New Kansas; font-weight: 500; font-style: normal; src: url('/assets/fonts/ExpensifyNewKansas-Medium.woff2') format('woff2'), url('/assets/fonts/ExpensifyNewKansas-Medium.woff') format('woff'); } @font-face { - font-family: ExpensifyNewKansas; + font-family: Expensify New Kansas; font-weight: 500; font-style: italic; src: url('/assets/fonts/ExpensifyNewKansas-MediumItalic.woff2') format('woff2'), url('/assets/fonts/ExpensifyNewKansas-MediumItalic.woff') format('woff'); diff --git a/docs/_sass/_main.scss b/docs/_sass/_main.scss index f3bf1035ed56..82446fe08b3a 100644 --- a/docs/_sass/_main.scss +++ b/docs/_sass/_main.scss @@ -131,7 +131,7 @@ details[open] > summary { h1, summary { - font-family: 'ExpensifyNewKansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; + font-family: 'Expensify New Kansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; font-weight: 500; font-size: larger; } @@ -151,7 +151,7 @@ select, textarea { line-height: 1.4; font-weight: 400; - font-family: 'ExpensifyNeue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; + font-family: 'Expensify Neue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; font-size: 16px; color: var(--color-text-supporting); } @@ -159,7 +159,7 @@ textarea { button { border-radius: 12px; padding: 12px; - font-family: 'ExpensifyNeue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; + font-family: 'Expensify Neue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; font-size: 15px; font-weight: bold; @@ -426,12 +426,12 @@ button { h2 { font-size: 1.125em; font-weight: 500; - font-family: 'ExpensifyNewKansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; + font-family: 'Expensify New Kansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; } h3 { font-size: 1em; - font-family: 'ExpensifyNeue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; + font-family: 'Expensify Neue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; } h2, @@ -457,7 +457,7 @@ button { p:first-child { font-size: large; - font-family: 'ExpensifyNewKansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; + font-family: 'Expensify New Kansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; opacity: 0.8; } } @@ -621,7 +621,7 @@ button { } h3.title { - font-family: 'ExpensifyNewKansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; + font-family: 'Expensify New Kansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; } h3.title, @@ -820,7 +820,7 @@ button { h3 { color: var(--color-success); - font-family: 'ExpensifyNewKansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; + font-family: 'Expensify New Kansas', 'Helvetica Neue', 'Helvetica', Arial, sans-serif; font-size: 17px; font-weight: 500; padding: 0; diff --git a/docs/_sass/_search-bar.scss b/docs/_sass/_search-bar.scss index c9b66d1e4b4a..2a546d3a5be4 100644 --- a/docs/_sass/_search-bar.scss +++ b/docs/_sass/_search-bar.scss @@ -87,7 +87,7 @@ input#gsc-i-id1.gsc-input { padding: 15px 0px 0px !important; pointer-events: auto; color: var(--color-text) !important; - font-family: 'ExpensifyNeue', 'Segoe UI Emoji', 'Noto Color Emoji' !important; + font-family: 'Expensify Neue', 'Segoe UI Emoji', 'Noto Color Emoji' !important; } /* These below #gsc-iw-id1, .gsc-input-box & .gsib_a are inner wrapper of search bar input */ @@ -144,7 +144,7 @@ label.search-label { position: absolute; margin-top: -20px; font-size: 15px; - font-family: 'ExpensifyNeue', 'Segoe UI Emoji', 'Noto Color Emoji'; + font-family: 'Expensify Neue', 'Segoe UI Emoji', 'Noto Color Emoji'; transform: translateY(-50%); left: 20px; pointer-events: none; @@ -166,7 +166,7 @@ label.search-label { .gsc-control-cse { background-color: var(--color-appBG) !important; border: var(--color-appBG) !important; - font-family: 'ExpensifyNeue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif !important; + font-family: 'Expensify Neue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif !important; } .gsc-webResult.gsc-result { @@ -219,7 +219,7 @@ label.search-label { /* Change Font the Google Search result */ .gsc-control-cse .gsc-table-result { - font-family: 'ExpensifyNeue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif !important; + font-family: 'Expensify Neue', 'Helvetica Neue', 'Helvetica', Arial, sans-serif !important; } /* Change Font result Paragraph color */ diff --git a/docs/articles/expensify-classic/bank-accounts-and-payments/Pay-Bills.md b/docs/articles/expensify-classic/bank-accounts-and-payments/Pay-Bills.md deleted file mode 100644 index 81dcf3488462..000000000000 --- a/docs/articles/expensify-classic/bank-accounts-and-payments/Pay-Bills.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Pay Bills -description: How to receive and pay company bills in Expensify ---- - - -# Overview -Simplify your back office by receiving bills from vendors and suppliers in Expensify. Anyone with or without an Expensify account can send you a bill, and Expensify will file it as a Bill and help you issue the payment. - -# How to Receive Vendor or Supplier Bills in Expensify - -There are three ways to get a vendor or supplier bill into Expensify: - -**Option 1:** Have vendors send bills to Expensify directly: Ask your vendors to email all bills to your Expensify billing intake email. - -**Option 2:** Forward bills to Expensify: If your bills are emailed to you, you can forward those bills to your Expensify billing intake email yourself. - -**Option 3:** Manually upload bills to Expensify: If you receive physical bills, you can manually create a Bill in Expensify on the web from the Reports page: -1. Click **New Report** and choose **Bill** -2. Add the expense details and vendor's email address to the pop-up window -3. Upload a pdf/image of the bill -4. Click **Submit** - -# How to Pay Bills - -There are multiple ways to pay Bills in Expensify. Letā€™s go over each method below: - -## ACH bank-to-bank transfer - -To use this payment method, you must have a business bank account connected to your Expensify account. - -To pay with an ACH bank-to-bank transfer: - -1. Sign in to your Expensify account on the web at www.expensify.com. -2. Go to the Inbox or Reports page and locate the Bill that needs to be paid. -3. Click the **Pay** button to be redirected to the Bill. -4. Choose the ACH option from the drop-down list. -5. Follow the prompts to connect your business bank account to Expensify. - -**Fees:** None - -## Pay using a credit or debit card - -This option is available to all US and International customers receiving an bill from a US vendor with a US business bank account. - -To pay with a credit or debit card: -1. Sign-in to your Expensify account on the web app at www.expensify.com. -2, Click on the Bill youā€™d like to pay to see the details. -3, Click the **Pay** button. -4. Youā€™ll be prompted to enter your credit card or debit card details. - -**Fees:** Includes 2.9% credit card payment fee - -## Venmo - -If both you and the vendor have Venmo setup in their Expensify account, you can opt to pay the bill through Venmo. - -**Fees:** Venmo charges a 3% senderā€™s fee - -## Pay Outside of Expensify - -If you are not able to pay using one of the above methods, then you can mark the Bill as paid manually in Expensify to update its status and indicate that you have made payment outside Expensify. - -To mark a Bill as paid outside of Expensify: - -1. Sign-in to your Expensify account on the web app at www.expensify.com. -2. Click on the Bill youā€™d like to pay to see the details. -3. Click on the **Reimburse** button. -4. Choose **Iā€™ll do it manually** - -**Fees:** None - -# Deep Dive: How company bills and vendor invoices are processed in Expensify - -Here is how a vendor or supplier bill goes from received to paid in Expensify: - -1. When a vendor or supplier bill is received in Expensify via, the document is SmartScanned automatically and a Bill is created. The Bill is owned by the primary domain contact, who will see the Bill on the Reports page on their default group policy. -2. When the Bill is ready for processing, it is submitted and follows the primary domain contactā€™s approval workflow. Each time the Bill is approved, it is visible in the next approver's Inbox. -3. The final approver pays the Bill from their Expensify account on the web via one of the methods. -4. The Bill is coded with the relevant imported GL codes from a connected accounting software. After it has finished going through the approval workflow the Bill can be exported back to the accounting package connected to the policy. - - -{% include faq-begin.md %} - -## What is my company's billing intake email? -Your billing intake email is [yourdomain.com]@expensify.cash. Example, if your domain is `company.io` your billing email is `company.io@expensify.cash`. - -## When a vendor or supplier bill is sent to Expensify, who receives it? - -Bills are received by the Primary Contact for the domain. This is the email address listed at **Settings > Domains > Domain Admins**. - -## Who can view a Bill in Expensify? - -Only the primary contact of the domain can view a Bill. - -## Who can pay a Bill? - -Only the primary domain contact (owner of the bill) will be able to pay the Mill. - -## How can you share access to Bills? - -To give others the ability to view a Bill, the primary contact can manually ā€œshareā€ the Bill under the Details section of the report via the Sharing Options button. -To give someone else the ability to pay Bills, the primary domain contact will need to grant those individuals Copilot access to the primary domain contact's account. - -## Is Bill Pay supported internationally? - -Payments are currently only supported for users paying in United States Dollars (USD). - -## Whatā€™s the difference between a Bill and an Invoice in Expensify? - -A Bill is a payable which represents an amount owed to a payee (usually a vendor or supplier), and is usually created from a vendor invoice. An Invoice is a receivable, and indicates an amount owed to you by someone else. - -{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/bank-accounts-and-payments/Reimbursements.md b/docs/articles/expensify-classic/bank-accounts-and-payments/Reimbursements.md deleted file mode 100644 index a31c0a582fd7..000000000000 --- a/docs/articles/expensify-classic/bank-accounts-and-payments/Reimbursements.md +++ /dev/null @@ -1,42 +0,0 @@ -# Overview - -If you want to know more about how and when youā€™ll be reimbursed through Expensify, weā€™ve answered your questions below. - -# How to Get Reimbursed - -To get paid back after submitting a report for reimbursement, youā€™ll want to be sure to connect your bank account. You can do that under **Settings** > **Account** > **Payments** > **Add a Deposit Account**. Once your employer has approved your report, the reimbursement will be paid into the account you added. - -# Deep Dive - -## Reimbursement Timing - -### US Bank Accounts - -If your company uses Expensify's ACH reimbursement we'll first check to see if the report is eligible for Rapid Reimbursement (next business day). For a report to be eligible for Rapid Reimbursement it must fall under two limits: - - - $100 per deposit bank account per day or less for the individuals being reimbursed or businesses receiving payments for bills. - - Less than $10,000 being disbursed in a 24-hour time period from the verified bank account being used to pay the reimbursement. - -If the request passes both checks, then you can expect to see funds deposited into your bank account on the next business day. - -If either limit has been reached, then you can expect to see funds deposited within your bank account within the typical ACH timeframe of 3-5 business days. - -### International Bank Accounts - -If receiving reimbursement to an international deposit account via Global Reimbursement, you should expect to see funds deposited in your bank account within 4 business days. - -## Bank Processing Timeframes - -Banks only process transactions and ACH activity on weekdays that are not bank holidays. These are considered business days. Additionally, the business day on which a transaction will be processed depends upon whether or not a request is created before or after the cutoff time, which is typically 3 pm PST. -For example, if your reimbursement is initiated at 4 pm on Wednesday, this is past the bank's cutoff time, and it will not begin processing until the next business day. -If that same reimbursement starts processing on Thursday, and it's estimated to take 3-5 business days, this will cover a weekend, and both days are not considered business days. So, assuming there are no bank holidays added into this mix, here is how that reimbursement timeline would play out: - -**Wednesday**: Reimbursement initiated after 3 pm PST; will be processed the next business day by your companyā€™s bank. -**Thursday**: Your company's bank will begin processing the withdrawal request -**Friday**: Business day 1 -**Saturday**: Weekend -**Sunday**: Weekend -**Monday**: Business day 2 -**Tuesday**: Business day 3 -**Wednesday**: Business day 4 -**Thursday**: Business day 5 diff --git a/docs/articles/expensify-classic/bank-accounts-and-payments/Reimbursing-Reports.md b/docs/articles/expensify-classic/bank-accounts-and-payments/Reimbursing-Reports.md deleted file mode 100644 index 69b39bae2874..000000000000 --- a/docs/articles/expensify-classic/bank-accounts-and-payments/Reimbursing-Reports.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Reimbursing Reports -description: How to reimburse employee expense reports ---- -# Overview - -One essential aspect of the Expensify workflow is the ability to reimburse reports. This process allows for the reimbursement of expenses that have been submitted for review to the person who made the request. Detailed explanations of the various methods for reimbursing reports within Expensify are provided below. - -# How to reimburse reports - -Reports can be reimbursed directly within Expensify by clicking the **Reimburse** button at the top of the report to reveal the available reimbursement options. - -## Direct Deposit - -To reimburse directly in Expensify, the following needs to be already configured: -- The employee that's receiving reimbursement needs to add a deposit bank account to their Expensify account (under **Settings > Account > Payments > Add a Deposit-only Bank Account**) -- The reimburser needs to add a business bank account to Expensify (under **Settings > Account > Payments > Add a Verified Business Bank Account**) -- The reimburser needs to ensure Expensify is whitelisted to withdraw funds from the bank account - -If all of those settings are in place, to reimburse a report, you will click **Reimburse** on the report and then select **Via Direct Deposit (ACH)**. - -![Reimbursing Reports Dropdown]({{site.url}}/assets/images/Reimbursing Reports Dropdown.png){:width="100%"} - -## Indirect or Manual Reimbursement - -If you don't have the option to utilize direct reimbursement, you can choose to mark a report as reimbursed by clicking the **Reimburse** button at the top of the report and then selecting **Iā€™ll do it manually ā€“ just mark as reimbursed**. - -This will effectively mark the report as reimbursed within Expensify, but you'll handle the payment elsewhere, outside of the platform. - -# Best Practices -- Plan ahead! Consider sharing a business bank account with multiple workspace admins so they can reimburse employee reports if you're unavailable. We recommend having at least two workspace admins with reimbursement permissions. - -- Understand there is a verification process when sharing a business bank account. The new reimburser will need access to the business bank accountā€™s transaction history (or access to someone who has access to it) to verify the set of test transactions sent from Expensify. - -- Get into the routine of having every new employee connect a deposit-only bank account to their Expensify account. This will ensure reimbursements happen in a timely manner. - -- Employees can see the expected date of their reimbursement at the top of and in the comments section of their report. - -# How to cancel a reimbursement - -Reimbursed a report by mistake? No worries! Any workspace admin with access to the same Verified Bank Account can cancel the reimbursement from within the report until it is withdrawn from the payment account. - -**Steps to Cancel an ACH Reimbursement:** -1. On your web account, navigate to the Reports page -2. Open the report -3. Click **Cancel Reimbursement** -4. After the prompt, "Are you sure you want to cancel the reimbursement?" click **Cancel Reimbursement**. - -It's important to note that there is a small window of time (roughly less than 24 hours) when a reimbursement can be canceled. If you don't see the **Cancel Reimbursement** button on a report, this means your bank has already begun withdrawing the funds from the reimbursement account and the withdrawal cannot be canceled. - -In that case, youā€™ll want to contact your bank directly to see if they can cancel the reimbursement on their end - or manage the return of funds directly with your employee, outside of Expensify. - -If you cancel a reimbursement after the withdrawal has started, it will be automatically returned to your Verified Bank Account within 3-5 business days. - -# Deep Dive - -## Rapid Reimbursement -If your company uses Expensify's ACH reimbursement, we'll first check to see if the report is eligible for Rapid Reimbursement (next business day). For a report to be eligible for Rapid Reimbursement, it must fall under two limits: -- $100 per deposit only bank account per day for the individuals being reimbursed or businesses receiving payments for bills -- $10,000 per verified bank account for the company paying bills and reimbursing - -If neither limit is met, you can expect to see funds deposited into your bank account on the next business day. - -If either limit has been reached, you can expect funds deposited within your bank account within the typical ACH time frame of four to five business days. - -Rapid Reimbursement is not available for non-US-based reimbursement. If you are receiving a reimbursement to a non-US-based deposit account, you should expect to see the funds deposited in your bank account within four business days. - -{% include faq-begin.md %} - -## Who can reimburse reports? -Only a workspace admin who has added a verified business bank account to their Expensify account can reimburse employees. - -## Why canā€™t I trigger direct ACH reimbursements in bulk? - -Instead of a bulk reimbursement option, you can set up automatic reimbursement. With this configured, reports below a certain threshold (defined by you) will be automatically reimbursed via ACH as soon as they're "final approved." - -To set your manual reimbursement threshold, head to **Settings > Workspace > Group > _[Workspace Name]_ > Reimbursement > Manual Reimbursement**. - -![Manual Reimbursement]({{site.url}}/assets/images/Reimbursing Manual.png){:width="100%"} - -{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Cancel-an-ACH-Reimbursement.md b/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Cancel-an-ACH-Reimbursement.md new file mode 100644 index 000000000000..ab75067b1a7f --- /dev/null +++ b/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Cancel-an-ACH-Reimbursement.md @@ -0,0 +1,17 @@ +--- +title: Cancel an ACH reimbursement +description: Cancel an ACH payment after it has been sent +--- +
+ +If a report was reimbursed with an ACH payment by mistake or otherwise needs to be canceled, a Workspace Admin with access to the verified bank account can cancel the reimbursement up until it is withdrawn from the payment account. + +To cancel an ACH reimbursement, + +1. Click the **Reports** tab. +2. Open the report. +3. Click **Cancel Reimbursement**. + - If you donā€™t see the Cancel Reimbursement button, this means your bank has already begun transferring the funds and it cannot be canceled. In this case, youā€™ll need to contact your bank for cancellation. +4. Click **Cancel Reimbursement** to confirm cancellation. + +
diff --git a/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Receive-Payments.md b/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Receive-Payments.md new file mode 100644 index 000000000000..00fb236e1763 --- /dev/null +++ b/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Receive-Payments.md @@ -0,0 +1,36 @@ +--- +title: Receive payments +description: Receive reimbursements from an employer +--- +
+ +To get paid after submitting a report for reimbursement, you must first connect a personal U.S. bank account or a personal Australian bank account. Then once your employer approves your report or invoice, the reimbursement will be paid directly to your bank account. +Funds for U.S. and global payments are generally deposited within a maximum of four to five business days: 2 days for the funds to be debited from the business bank account, and 2-3 business days for the ACH or wire to deposit into the employee account. + +However, banks only process ACH transactions before the daily cutoff (generally 3 p.m. PST) and only on business weekdays that are not bank holidays. This may affect when the payment is disbursed. If the payment qualifies for Rapid Reimbursement, you may receive the payment sooner. + +{% include info.html %} +Companies also have the option to submit payments outside of Expensify via check, cash, or a third-party payment processor. Check with your Workspace Admin to know how you will be reimbursed. +{% include end-info.html %} + +# Rapid Reimbursement (U.S. only) + +With Expensifyā€™s ACH reimbursement, payments may be eligible for reimbursement by the next business day with Rapid Reimbursement if they meet the following qualifications: +- **Deposit-only accounts**: Payment must not exceed $100 +- **Verified business bank accounts**: The account does not disburse more than $10,000 within a 24-hour time period. + +If the payment amount exceeds the limit, funds will be deposited within the typical ACH time frame of four to five business days. + +{% include faq-begin.md %} + +**Is there a way I can track my payment?** + +For U.S. ACH payments and global reimbursements, the expected date of reimbursement is provided at the top of the report and in the comments section of the report. Funds will be deposited within the typical ACH time frame of four to five business days unless the payment is eligible for Rapid Reimbursement. + +**For global payments, what currency is the payment provided in?** + +Global payments are reimbursed in the recipient's currency. + +{% include faq-end.md %} + +
diff --git a/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Reimburse-Australian-Reports.md b/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Reimburse-Australian-Reports.md new file mode 100644 index 000000000000..90a89ff3c75e --- /dev/null +++ b/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Reimburse-Australian-Reports.md @@ -0,0 +1,63 @@ +--- +title: Reimburse Australian reports +description: Send payment for Australian expense reports +--- +
+ +Workspace Admins can reimburse AUD expense reports by downloading an .aba file containing the accounts needing payment and uploading the file to the bank. This can be done for a single report or for a batch of payments at once. + +{% include info.html %} +Your financial institution may require .aba files to include a self-balancing transaction. If you are unsure, check with your bank. Otherwise, the .aba file may not work with your bankā€™s internet banking platform. +{% include end-info.html %} + +# Reimburse a single report + +1. Open the report, invoice, or bill from the email or Concierge notification, or from the **Reports** tab. +2. Click the **Reimburse** dropdown and select **Via ABA File**. +3. Click **Generate ABA and Mark as Reimbursed**. +4. Click **Download**. +5. Upload the .aba file to your bank. For additional guidance, use any of the following bank guides: + - [ANZ Bank](https://www.anz.com.au/support/internet-banking/pay-transfer-business/payroll/import-file/) + - [CommBank](https://www.commbank.com.au/business/pds/003-279-importing-a-de-file.pdf) + - [Westpac](https://www.westpac.com.au/business-banking/online-banking/support-faqs/import-files/) + - [NAB](https://www.nab.com.au/business/online-banking/nab-connect/help) + - [Bendigo Bank](https://www.bendigobank.com.au/globalassets/documents/business/bulk-payments-user-guide.pdf) + - [Bank of Queensland](https://www.boq.com.au/help-and-support/online-banking/ob-faqs-and-support/faq-pfuf) + +# Send batch payments + +Once employees submit their expense reports, a Workspace Admin exports the reports (which contains the employeesā€™ bank account information) and uploads the .aba file to the bank. + +## Step 1: Verify currency & reimbursement settings + +1. Hover over **Settings**, then click **Workspaces**. +2. Select the desired workspace. +3. Click the **Reports** tab on the left. +4. Click the Report Currency dropdown and select **AUD A$**. +5. Click the **Reimbursement** tab on the left. +6. Verify that **Indirect** is selected as the Reimbursement type or select it if not. + +## Step 2: Download and upload the ABA file + +1. Click the **Reports** tab. +2. Use the checkbox on the left to select all the reports needing payment. +3. Click **Bulk Actions** and select **Reimburse via ABA**. +5. Click **Generate ABA and Mark as Reimbursed**. +6. Click **Download Report**. +7. Upload the .aba file to your bank. For additional guidance, use any of the following bank guides: + - [ANZ Bank](https://www.anz.com.au/support/internet-banking/pay-transfer-business/payroll/import-file/) + - [CommBank](https://www.commbank.com.au/business/pds/003-279-importing-a-de-file.pdf) + - [Westpac](https://www.westpac.com.au/business-banking/online-banking/support-faqs/import-files/) + - [NAB](https://www.nab.com.au/business/online-banking/nab-connect/help) + - [Bendigo Bank](https://www.bendigobank.com.au/globalassets/documents/business/bulk-payments-user-guide.pdf) + - [Bank of Queensland](https://www.boq.com.au/help-and-support/online-banking/ob-faqs-and-support/faq-pfuf) + +{% include faq-begin.md %} + +**Can I use direct deposit for an AUD bank account?** + +No, AUD bank accounts do not rely on direct deposit or ACH. + +{% include faq-end.md %} + +
diff --git a/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Reimburse-Reports-Invoices-and-Bills.md b/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Reimburse-Reports-Invoices-and-Bills.md new file mode 100644 index 000000000000..b2cfbf833e13 --- /dev/null +++ b/docs/articles/expensify-classic/bank-accounts-and-payments/payments/Reimburse-Reports-Invoices-and-Bills.md @@ -0,0 +1,108 @@ +--- +title: Reimburse reports, invoices, and bills +description: Use direct deposit or indirect reimbursement to pay reports, invoices, and bills +--- +
+ +Once a report, invoice, or bill has been submitted and approved for reimbursement, you can reimburse the expenses using direct deposit or an indirect reimbursement option outside of Expensify (like cash, a check, or a third-party payment processor). + +# Pay with direct deposit + +{% include info.html %} +Before a report can be reimbursed with direct deposit, the employee or vendor receiving the reimbursement must connect their personal U.S. bank account, and the reimburser must connect a verified business bank account. + +Direct deposit is available for U.S. and global reimbursements. It is not available for Australian bank accounts. For Australian accounts, review the process for reimbursing Australian expenses. +{% include end-info.html %} + +1. Open the report, invoice, or bill from the email or Concierge notification, or from the **Reports** tab. +2. Click the **Reimburse** (for reports) or **Pay** (for bills and invoices) dropdown and select **Via Direct Deposit (ACH)**. +3. Confirm that the correct VBA is selected or use the dropdown menu to select a different one. +4. Click **Accept Terms & Pay**. + +The reimbursement is now queued in the daily batch. + +# Pay with indirect reimbursement + +When payments are submitted through Expensify, the report is automatically labeled as Reimbursed after it has been paid. However, if you are reimbursing reports via paper check, payroll, or any other method that takes place outside of Expensify, youā€™ll want to manually mark the bill as paid in Expensify to track the payment history. + +To label a report as Reimbursed after sending a payment outside of Expensify, + +1. Pay the report, invoice, or bill outside of Expensify. +2. Open the report, invoice, or bill from the email or Concierge notification, or from the **Reports** tab. +3. Click **Reimburse**. +4. Select **Iā€™ll do it manually - just mark it as reimbursed**. This changes the report status to Reimbursed. + +Once the recipient has received the payment, the submitter can return to the report and click **Confirm** at the top of the report. This will change the report status to Reimbursed: CONFIRMED. + +{% include faq-begin.md %} + +**Is there a maximum total report total?** + +Expensify cannot process a reimbursement for any single report over $20,000. If you have a report with expenses exceeding $20,000 we recommend splitting the expenses into multiple reports. + +**Why is my account locked?** + +When you reimburse a report, you authorize Expensify to withdraw the funds from your account and send them to the person requesting reimbursement. If your bank rejects Expensifyā€™s withdrawal request, your verified bank account is locked until the issue is resolved. + +Withdrawal requests can be rejected if the bank account has not been enabled for direct debit or due to insufficient funds. If you need to enable direct debits from your verified bank account, your bank will require the following details: +- The ACH CompanyIDs: 1270239450 and 4270239450 +- The ACH Originator Name: Expensify + +Once resolved, you can request to unlock the bank account by completing the following steps: + +1. Hover over **Settings**, then click **Account**. +2. Click the **Payments** tab. +3. Click **Bank Accounts**. +4. Next to the bank account, click **Fix**. + +Our support team will review and process the request within 4-5 business days. + +**How are bills and invoices processed in Expensify?** + +Here is the process a vendor or supplier bill goes through from receipt to payment: + +1. A vendor or supplier bill is received in Expensify. +2. Automatically, the document is SmartScanned and a bill is created for the primary domain contact. The bill will appear under the Reports tab on their default group policy. +3. When the bill is ready for processing, it is submitted and follows the primary domain contactā€™s approval workflow until the bill has been fully approved. +4. The final approver pays the bill from their Expensify account using one of the methods outlined in the article above. +5. If the workspace is connected to an accounting integration, the bill is automatically coded with the relevant imported GL codes and can be exported back to the accounting software. + +**When a vendor or supplier bill is sent to Expensify, who receives it?** + +Bills are sent to the primary contact for the domain. Theyā€™ll see a notification from Concierge on their Home page, and theyā€™ll also receive an email. + +**How can I share access to bills?** + +By default, only the primary contact for the domain can view and pay the bill. However, you can allow someone else to view or pay bills. + +- **To allow someone to view a bill**: The primary contact can manually share the bill with others to allow them to view it. + 1. Click the **Reports** tab. + 2. Click the report. + 3. Click **Details** in the top right. + 4. Click the **Add Person** icon. + 5. Enter the email address or phone number of the person you will share the report with. + 6. Enter a message, if desired. + 7. Click **Share Report**. + +- **To allow someone to pay bills**: The primary domain contact can allow others to pay bills on their behalf by [assigning those individuals as Copilots](https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Assign-or-remove-a-Copilot). + +**Is Bill Pay supported internationally?** + +Payments are currently only supported for users paying in United States Dollars (USD). + +**Whatā€™s the difference between a bill and an invoice?** + +- A **bill** is a payable that represents an amount owed to a payee (usually a vendor or supplier), and it is usually created from a vendor invoice. +- An **invoice** is a receivable that indicates an amount owed to you by someone else. + +**Who can reimburse reports?** + +Only a Workspace Admin who has added a verified business bank account to their Expensify account can reimburse employee reports. + +**Why canā€™t I trigger direct ACH reimbursements in bulk?** + +Expensify does not offer bulk reimbursement, but you can set up automatic reimbursement to automatically reimburse approved reports via ACH that do not exceed the threshold that you define. + +{% include faq-end.md %} + +
diff --git a/docs/articles/expensify-classic/connect-credit-cards/company-cards/Troubleshooting.md b/docs/articles/expensify-classic/connect-credit-cards/company-cards/Troubleshooting.md index 05366a91d9fa..f94e692f5e56 100644 --- a/docs/articles/expensify-classic/connect-credit-cards/company-cards/Troubleshooting.md +++ b/docs/articles/expensify-classic/connect-credit-cards/company-cards/Troubleshooting.md @@ -8,6 +8,15 @@ Whether you're encountering issues related to company cards, require assistance ## How to add company cards to Expensify You can add company credit cards under the Domain settings in your Expensify account by navigating to *Settings* > *Domain* > _Domain Name_ > *Company Cards* and clicking *Import Card/Bank* and following the prompts. +## To Locate Missing Card Transactions in Expensify +1. **Wait for Posting**: Bank transactions may take up to 24 hours to import into Expensify after they have "posted" at your bank. Ensure sufficient time has passed for transactions to appear. +2. **Update Company Cards**: Go to Settings > Domains > Company Cards. Click on the card in question and click "Update" to refresh the card feed. +3. **Reconcile Cards**: Navigate to the Reconciliation section under Settings > Domains > Company Cards. Refer to the detailed guide on how to use the [Reconciliation Dashboard](https://help.expensify.com/articles/expensify-classic/connect-credit-cards/company-cards/Reconciliation#identifying-outstanding-unapproved-expenses-using-the-reconciliation-dashboard). +4. **Review Transactions**: Use the Reconciliation Dashboard to view all transactions within a specific timeframe. Transactions will display on the Expenses page based on their "Posted Date". If needed, uncheck the "use posted date" checkbox near the filters to view transactions based on their "Transaction Date" instead. +5. **Address Gaps**: If there is a significant gap in transactions or if transactions are still missing, contact Expensify's Concierge or your Account Manager. They can initiate a historical data update on your card feed to ensure all transactions are properly imported. + +Following these steps should help you identify and resolve any issues with missing card transactions in Expensify. + ## Known issues importing transactions The first step should always be to "Update" your card, either from Settings > Your Account > Credit Card Import or Settings > Domain > [Domain Name] > Company Cards for centrally managed cards. If a "Fix" or "Fix card" option appears, follow the steps to fix the connection. If this fails to import your missing transactions, there is a known issue whereby some transactions will not import for certain API-based company card connections. So far this has been reported on American Express, Chase and Wells Fargo. This can be temporarily resolved by creating the expenses manually instead: @@ -63,6 +72,24 @@ If you've answered "yes" to any of these questions, a Domain Admins need to upda Make sure you're importing your card in the correct spot in Expensify and selecting the right bank connection. For company cards, use the master administrative credentials to import your set of cards at *Settings* > *Domains* > _Domain Name_ > *Company Cards* > *Import Card*. Please note there are some things that cannot be bypassed within Expensify, including two-factor authentication being enabled within your bank account. This will prevent the connection from remaining stable and will need to be turned off on the bank side. +## Why Canā€™t I See the Transactions Before a Certain Date? +When importing a card into Expensify, the platform typically retrieves 30-90 days of historical transactions, depending on the card or account type. For commercial feeds, transactions cannot be imported before the bank starts sending data. If needed, banks can send backdated files, and Expensify can run a historical update upon request. + +Additionally, Expensify does not import transactions dated before the "start date" you specify when assigning the card. Unless transitioning from an old card to a new one to avoid duplicates, it's advisable to set the start date to "earliest possible" or leave it blank. + +For historical expenses that cannot be imported automatically, consider using Expensify's [company card](https://help.expensify.com/articles/expensify-classic/connect-credit-cards/company-cards/CSV-Import) or [personal card](https://help.expensify.com/articles/expensify-classic/connect-credit-cards/Personal-Credit-Cards#importing-expenses-via-a-spreadsheet) spreadsheet import method. This allows you to manually input missing transactions into the system. + +## Why Am I / Why Is My Employee Seeing Duplicates? +If an employee is seeing duplicate expenses, they may have accidentally imported the card as a personal credit card as well as having the Domain Admin assign them a company card. + +To troubleshoot: +- Have the employee navigate to their Settings > Your Account > Credit Card Import and confirm that their card is only listed once. +- If the card is listed twice, delete the entry without the "padlock" icon. + +**Important:** Deleting a duplicate card will delete all unapproved expenses from that transaction feed. Transactions associated with the remaining card will not be affected. If receipts were attached to those transactions, they will still be on the Expenses page, and the employee can click to SmartScan them again. + +Duplicate expenses might also occur if you recently unassigned and reassigned a company card with an overlapping start date. If this is the case and expenses on the ā€œnewā€ copy have not been submitted, you can unassign the card again and reassign it with a more appropriate start date. This action will delete all unsubmitted expenses from the new card feed. + ## What are the most reliable bank connections in Expensify?* All bank connections listed below are extremely reliable, but we recommend transacting with the Expensify VisaĀ® Commercial Card. It also offers daily and monthly settlement, unapproved expense limits, realtime compliance for secure and efficient spending, and cash back on all US purchases. [Click here to learn more about the Expensify Card](https://use.expensify.com/company-credit-card). diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/ADP.md b/docs/articles/expensify-classic/connections/ADP.md similarity index 100% rename from docs/articles/expensify-classic/integrations/HR-integrations/ADP.md rename to docs/articles/expensify-classic/connections/ADP.md diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Additional-Travel-Integrations.md b/docs/articles/expensify-classic/connections/Additional-Travel-Integrations.md similarity index 100% rename from docs/articles/expensify-classic/integrations/travel-integrations/Additional-Travel-Integrations.md rename to docs/articles/expensify-classic/connections/Additional-Travel-Integrations.md diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Egencia.md b/docs/articles/expensify-classic/connections/Egencia.md similarity index 75% rename from docs/articles/expensify-classic/integrations/travel-integrations/Egencia.md rename to docs/articles/expensify-classic/connections/Egencia.md index 178621a62d90..35d232d2df67 100644 --- a/docs/articles/expensify-classic/integrations/travel-integrations/Egencia.md +++ b/docs/articles/expensify-classic/connections/Egencia.md @@ -24,7 +24,7 @@ Egencia controls the feed, so to connect Expensify you will need to: # How to Connect to a Central Purchasing Account Once your Egencia account manager has established the feed, you can automatically forward all Egencia booking receipts to a single Expensify account. To do this: 1. Open a chat with Concierge. -2. Tell Concierge ā€œPlease enable Central Purchasing Account for our Egencia feed. The account email is: xxx@yourdomain.comā€. +2. Tell Concierge the address of your central purchasing account, ā€œPlease enable Central Purchasing Account for our Egencia feed. The account email is: xxx@yourdomain.comā€. -The receipt the traveler receives is a "reservation expense." Reservation expenses are non-reimbursable and wonā€™t be included in any integrated accounting system exports. The reservation sent to the traveler's account is added to their mobile app Trips feature so that the traveler can easily keep tabs on upcoming travel and receive trip notifications. +A receipt will be sent to both the traveler and the central account. The receipt sent to the traveler is a "reservation expense." Reservation expenses are non-reimbursable and wonā€™t be included in any integrated accounting system exports. diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Global-VaTax.md b/docs/articles/expensify-classic/connections/Global-VaTax.md similarity index 100% rename from docs/articles/expensify-classic/integrations/travel-integrations/Global-VaTax.md rename to docs/articles/expensify-classic/connections/Global-VaTax.md diff --git a/docs/articles/expensify-classic/integrations/other-integrations/Google-Apps-SSO.md b/docs/articles/expensify-classic/connections/Google-Apps-SSO.md similarity index 100% rename from docs/articles/expensify-classic/integrations/other-integrations/Google-Apps-SSO.md rename to docs/articles/expensify-classic/connections/Google-Apps-SSO.md diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/Greenhouse.md b/docs/articles/expensify-classic/connections/Greenhouse.md similarity index 100% rename from docs/articles/expensify-classic/integrations/HR-integrations/Greenhouse.md rename to docs/articles/expensify-classic/connections/Greenhouse.md diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/Gusto.md b/docs/articles/expensify-classic/connections/Gusto.md similarity index 100% rename from docs/articles/expensify-classic/integrations/HR-integrations/Gusto.md rename to docs/articles/expensify-classic/connections/Gusto.md diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/Indirect-Accounting-Integrations.md b/docs/articles/expensify-classic/connections/Indirect-Accounting-Integrations.md similarity index 100% rename from docs/articles/expensify-classic/integrations/accounting-integrations/Indirect-Accounting-Integrations.md rename to docs/articles/expensify-classic/connections/Indirect-Accounting-Integrations.md diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Lyft.md b/docs/articles/expensify-classic/connections/Lyft.md similarity index 100% rename from docs/articles/expensify-classic/integrations/travel-integrations/Lyft.md rename to docs/articles/expensify-classic/connections/Lyft.md diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Navan.md b/docs/articles/expensify-classic/connections/Navan.md similarity index 100% rename from docs/articles/expensify-classic/integrations/travel-integrations/Navan.md rename to docs/articles/expensify-classic/connections/Navan.md diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/QuickBooks-Time.md b/docs/articles/expensify-classic/connections/QuickBooks-Time.md similarity index 100% rename from docs/articles/expensify-classic/integrations/HR-integrations/QuickBooks-Time.md rename to docs/articles/expensify-classic/connections/QuickBooks-Time.md diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/Rippling.md b/docs/articles/expensify-classic/connections/Rippling.md similarity index 100% rename from docs/articles/expensify-classic/integrations/HR-integrations/Rippling.md rename to docs/articles/expensify-classic/connections/Rippling.md diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/TravelPerk.md b/docs/articles/expensify-classic/connections/TravelPerk.md similarity index 100% rename from docs/articles/expensify-classic/integrations/travel-integrations/TravelPerk.md rename to docs/articles/expensify-classic/connections/TravelPerk.md diff --git a/docs/articles/expensify-classic/integrations/travel-integrations/Uber.md b/docs/articles/expensify-classic/connections/Uber.md similarity index 90% rename from docs/articles/expensify-classic/integrations/travel-integrations/Uber.md rename to docs/articles/expensify-classic/connections/Uber.md index 16da0c0caa5b..213a90b6d288 100644 --- a/docs/articles/expensify-classic/integrations/travel-integrations/Uber.md +++ b/docs/articles/expensify-classic/connections/Uber.md @@ -22,3 +22,5 @@ Now, every time you use Uber for Business ā€“ be it for rides or meals ā€“ the r ![Uber integration set up steps: Connecting your account](https://help.expensify.com/assets/images/Uber1.png){:width="100%"} ![Uber integration set up steps: Selecting Expensify](https://help.expensify.com/assets/images/Uber2.png){:width="100%"} + +To disconnect Uber and Expensify, simply follow the above path and select Disconnect on the Expensify option. diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/Workday.md b/docs/articles/expensify-classic/connections/Workday.md similarity index 100% rename from docs/articles/expensify-classic/integrations/HR-integrations/Workday.md rename to docs/articles/expensify-classic/connections/Workday.md diff --git a/docs/articles/expensify-classic/integrations/HR-integrations/Zenefits.md b/docs/articles/expensify-classic/connections/Zenefits.md similarity index 100% rename from docs/articles/expensify-classic/integrations/HR-integrations/Zenefits.md rename to docs/articles/expensify-classic/connections/Zenefits.md diff --git a/docs/articles/expensify-classic/connections/accelo/Accelo-Troubleshooting.md b/docs/articles/expensify-classic/connections/accelo/Accelo-Troubleshooting.md new file mode 100644 index 000000000000..fd0a6ca59069 --- /dev/null +++ b/docs/articles/expensify-classic/connections/accelo/Accelo-Troubleshooting.md @@ -0,0 +1,7 @@ +--- +title: Accelo Troubleshooting +description: Accelo Troubleshooting +order: 3 +--- + +# Coming soon diff --git a/docs/articles/expensify-classic/connections/accelo/Configure-Accelo.md b/docs/articles/expensify-classic/connections/accelo/Configure-Accelo.md new file mode 100644 index 000000000000..a71671ad8da0 --- /dev/null +++ b/docs/articles/expensify-classic/connections/accelo/Configure-Accelo.md @@ -0,0 +1,55 @@ +--- +title: Configure Accelo +description: Configure Accelo's export and coding settings. +order: 2 +--- + +# Configure Accelo +1. Log into Accelo +2. Navigate to the Integrations page +3. Select the **Expensify** tab +4. Enter Expensify Integration Server Credentials +5. Provide your Expensify Integration Serverā€™s Partner User ID and Partner User Secret +6. Click ā€œSaveā€ to complete the setup + +## Upload Accelo Project Codes as Tags in Expensify +Once you have connected Accelo to Expensify, the next step is to upload your Accelo Project Codes as Tags in Expensify: +1. Head to to **Settings** > **Workspaces** > **Group** > _[Workspace Name]_ > **Tags** +2. Choose to upload a CSV +3. If you also integrate with Xero or QuickBooks Online, you must upload your Project Codes by appending your tags + - Go to **Settings** > **Workspaces** > **Group** > _[Workspace Name]_ > **Tags** + - Click on **Append a custom tag list from a CSV** to upload your Project Codes via a CSV + +## Information sync between Expensify and Accelo +The Accelo integration does a one-way sync, which means it brings expenses from Expensify into Accelo. When this happens, it transfers specific information from Expensify expenses to Accelo: + +| Expensify | Accelo | +|---------------------|-----------------------| +| Comment | Title | +| Date | Date Incurred | +| Category | Type | +| Tags | Against (relevant Project, Ticket or Retainer) | +| Distance (mileage) | Quantity | +| Hours (time expenses) | Quantity | +| Amount | Purchase Price and Sale Price | +| Reimbursable? | Reimbursable? | +| Billable? | Billable? | +| Receipt | Attachment | +| Tax Rate | Tax Code | +| Attendees | Submitted By | + +## Expense Status +The status of your expense report in Expensify is also synced in Accelo. + +| Expensify Report Status | Accelo Expense Status | +|-------------------------|-----------------------| +| Open | Submitted | +| Submitted | Submitted | +| Approved | Approved | +| Reimbursed | Approved | +| Rejected | Declined | +| Archived | Approved | +| Closed | Approved | + +## Importing expenses from Expensify to Accelo +Accelo checks Expensify for new expenses once every hour. It automatically adds expenses that have been created or changed since the connection's last sync. diff --git a/docs/articles/expensify-classic/connections/accelo/Connect-To-Accelo.md b/docs/articles/expensify-classic/connections/accelo/Connect-To-Accelo.md new file mode 100644 index 000000000000..bdb21ceab9c0 --- /dev/null +++ b/docs/articles/expensify-classic/connections/accelo/Connect-To-Accelo.md @@ -0,0 +1,26 @@ +--- +title: Accelo +description: Help doc for Accelo integration +order: 1 +--- + + +# Overview +Accelo is a cloud-based business management platform tailored to professional service companies. It enables seamless integration with Expensify, allowing users to effortlessly import expense details from Expensify into Accelo, associating them with the corresponding project, ticket, or retainer within the system. + +**A couple of notes before connecting Accelo to Expensify:** +- You must have administrator access to Accelo +- You need to be a workspace admin in Expensify + +# Connect to Accelo +To connect Expensify to Accelo, follow these steps: +1. Open the [Expensify Integration Server](https://www.expensify.com/tools/integrations/) +2. Copy your **Partner User ID** and **Partner User Secret** + - If you havenā€™t previously set up the integration server, follow the prompt on the screen and select **click here**. + - If the integration server is already set up, select **Click here to regenerate your Partner User Secret to generate a new code**. +3. Copy the Partner User ID and Partner User Secret and store them in a secure location. +4. In Accelo, go to the Integrations page and select the **Expensify** tab. +5. Enter the Expensify Partner User ID and Partner User Secret. + - (Optional) If you currently use the Integration Server for another integration, open that platform and update the secret to the newly generated Partner User Secret +6. Click **Save**. +7. Connection Established: Expensify is now successfully connected to Accelo! diff --git a/docs/articles/expensify-classic/connections/certinia/Certinia-Troubleshooting.md b/docs/articles/expensify-classic/connections/certinia/Certinia-Troubleshooting.md new file mode 100644 index 000000000000..82a2762ee99a --- /dev/null +++ b/docs/articles/expensify-classic/connections/certinia/Certinia-Troubleshooting.md @@ -0,0 +1,6 @@ +--- +title: Certinia Troubleshooting +description: Certinia Troubleshooting +--- + +# Coming soon diff --git a/docs/articles/expensify-classic/connections/certinia/Configure-Certinia.md b/docs/articles/expensify-classic/connections/certinia/Configure-Certinia.md new file mode 100644 index 000000000000..3f9172baaf9e --- /dev/null +++ b/docs/articles/expensify-classic/connections/certinia/Configure-Certinia.md @@ -0,0 +1,91 @@ +--- +title: Configure Certinia +description: Configure Certinia's export, coding, and advanced settings. +order: 2 +--- +After Certinia and Expensify are connected, head to **Settings > Workspaces > [Workspace Name] > Connections > Certinia > Configure** to configure the export, coding, and advanced settings for the connection. + +# Step 1: Configure Export Settings +## Preferred Exporter +The preferred exporter is the user who will be the main exporter of reports. This person will receive the notifications for errors. + +## Payable Invoice Status and Date +Reports can be exported as Complete or In Progress, using the date of last expense, submitted date, or exported date. + +## Reimbursable and non-reimbursable exports +Both reimbursable and non-reimbursable reports are exported as payable invoices (FFA) or expense reports (PSA/SRP). If you have both Reimbursable and Non-Reimbursable expenses on a single report, Expensify will create a separate payable invoice/expense report for each type. + +## Default Vendor (FFA) +Choose from the full list of vendors from your Certinia FFA account. The amount will be applied to the non-reimbursable payable invoices. + +# Step 2: Configure Coding Settings +## Company +Select which FinancialForce company to import from/export to. + +## Chart of Accounts (FFA) +Prepaid Expense Type and Profit & Loss accounts are imported to be used as categories on each expense. + +## Expense Type GLA Mappings (PSA/SRP) +Your Expense Type GLA Mappings are enabled in Expensify to use as categories on each expense when using both PSA and SRP; however, PSA will not import or export categories, while SRP will. + +## Dimensions (FFA) +We import four dimension levels and each has three options to select from: + +* Do not map: FinancialForce defaults will apply to the payable invoice, without importing it into Expensify +* Tags: These are shown in the Tag section of your workspace, and employees can select them on each expense created +* Report fields: These will show in the Reports section of your workspace. Employees can select one to be applied at the header level, i.e., the entire report. + +## Projects, Assignments, or Projects & Assignments (PSA/SRP) +These can be imported as tags with **Milestones** being optional. When selecting to import only projects, we will derive the account from the project. If an assignment is selected, we will derive both the account and project from the assignment. + +**Note:** If you are using a project without an assignment, the box **Allow Expenses Without Assignment** must be checked on the project in FinancialForce. + +## Tax +Import tax rates from Certinia to apply to expenses. + +# Step 3: Configure Advanced Settings +## Auto Sync +Auto Sync in Certinia performs daily updates to your coding. Additionally, it automatically exports reports after they receive final approval. For Non-Reimbursable expenses, syncing happens immediately upon final approval of the report. In the case of Reimbursable expenses, syncing occurs as soon as the report is reimbursed or marked as reimbursed. + +## Export tax as non-billable +When exporting Billable expenses, this dictates whether you will also bill the tax component to your clients/customers. + +## Multi-Currency in Certinia PSA/SRP +When exporting to Certinia PSA/SRP, if employees are submitting expenses in more than one original currency, you may see up to three different currencies on the expense report in Certinia. +* Summary Total Reimbursement Amount: this currency is derived from the currency of the project selected on the expense. +* Amount field on the Expense line: this currency is derived from the Expensify workspace default report currency. +* Reimbursable Amount on the Expense line: this currency is derived from the currency of the resource with an email matching the report submitter. + +{% include faq-begin.md %} + +## What happens if the report canā€™t be exported to Certinia? + +The following happens if a report isn't exported: +- The preferred exporter will receive an email outlining the issue and any specific error messages +- Any error messages preventing the export from taking place will be recorded in the reportā€™s history +- The report will be listed in the exporterā€™s Expensify Inbox as awaiting export. + +## If I enable Auto Sync, what happens to existing approved and reimbursed reports? + +Enabling Auto-Sync afterward won't affect existing approved or reimbursed reports. For any approved reports that haven't been exported to Certinia, you'll need to either manually export them or mark them as manually entered. + +## How do I export tax? + +Tax rates are created in Expensify through the tax tracking feature under **Settings** > **Workspaces** > **Groups** > _[Workspace Name]_ > **Tax**. We export the tax amount calculated on the expenses. + +## How do reports map to Payable Invoices in Certinia FFA? + +Reports map to FFA as follows: +- Account Name - Account associated with Expensify submitterā€™s email address +- Reference 1 - Report URL +- Invoice Description - Report title + +## How do reports map to Expense Reports in Certinia PSA/SRP? + +Reports map to PSA/SRP as follows: +- Expense report name - Report title +- Resource - User associated with Expensify submitterā€™s email address +- Description - Report URL +- Approver - Expensify report approver + +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/connections/certinia/Connect-To-Certinia.md b/docs/articles/expensify-classic/connections/certinia/Connect-To-Certinia.md new file mode 100644 index 000000000000..3d9c13449934 --- /dev/null +++ b/docs/articles/expensify-classic/connections/certinia/Connect-To-Certinia.md @@ -0,0 +1,40 @@ +--- +title: Certinia +description: Connect Expensify to Certinia +order: 1 +--- +[Certinia](https://use.expensify.com/financialforce) (formerly known as FinancialForce) is a cloud-based software solution that provides a range of financial management and accounting applications built on the Salesforce platform. There are two versions: PSA/SRP and FFA -- Expensify supports connections to both. + +**Before connecting to Certinia:** +Install the Expensify bundle in Certinia using the relevant installer: +- [PSA/SRP](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t2M000002J0BHD%252Fpackaging%252FinstallPackage.apexp%253Fp0%253D04t2M000002J0BH) +- [FFA](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t4p000001UQVj) +- **Check the contact details in Certinia:** + - Confirm there's a user and contact in Certinia that matches your main email in Expensify + - Then, create contacts for all employees who will be sending expense reports + - Be sure that each contact's email matches the email address associated with their Expensify account + +# Connect to Certinia +1. Go to **Settings > Workspaces > Groups > [Workspace Name] > Connections** in Expensify +2. Click **Create a New Certinia (FinancialForce) Connection** +3. Log into your Certinia account +4. Follow the prompts until the connection between Certinia and Expensify is established + +### If you use PSA/SRP +- Each report approver needs both a User and a Contact +- The user does not need a SalesForce license + +Then, run through the following steps before connecting to Expensify: +1. Set permission controls in Certinia for your user for each contact/resource + - Go to Permission Controls + - Create a new permission control + - Set yourself (exporter) as the user + - Select the resource (report submitter) + - Grant all available permissions +2. Set permissions on any project you are exporting to + - Go to **Projects** > _select a project_ > **Project Attributes** > **Allow Expenses Without Assignment** + - Select the project > **Edit** + - Under the Project Attributes section, check **Allow Expenses Without Assignment** +3. Set up Expense Types (categories in Expensify - _SRP only_) + - Go to **Main Menu** > _+ symbol_ > **Expense Type GLA Mappings** + - Click **New** to add new mappings diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/NetSuite.md b/docs/articles/expensify-classic/connections/netsuite/Configure-Netsuite.md similarity index 73% rename from docs/articles/expensify-classic/integrations/accounting-integrations/NetSuite.md rename to docs/articles/expensify-classic/connections/netsuite/Configure-Netsuite.md index ee116f65a398..f926792ffd1f 100644 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/NetSuite.md +++ b/docs/articles/expensify-classic/connections/netsuite/Configure-Netsuite.md @@ -1,136 +1,13 @@ --- -title: NetSuite -description: Connect and configure NetSuite directly to Expensify. +title: Configure Netsuite +description: Configure NetSuite's export, coding, and advanced settings. --- -# Overview -Expensify's seamless integration with NetSuite enables you to streamline your expense reporting process. This integration allows you to automate the export of reports, tailor your coding preferences, and tap into NetSuite's array of advanced features. By correctly configuring your NetSuite settings in Expensify, you can leverage the connection's settings to automate most of the tasks, making your workflow more efficient. +By correctly configuring your NetSuite settings in Expensify, you can leverage the connection's settings to automate most of the tasks, making your workflow more efficient. -Before getting started with connecting NetSuite to Expensify, there are a few things to note: -- Token-based authentication works by ensuring that each request to NetSuite is accompanied by a signed token which is verified for authenticity -- You must be able to login to NetSuite as an administrator to initiate the connection -- You must have a Control Plan in Expensify to integrate with NetSuite -- Employees donā€™t need NetSuite access or a NetSuite license to submit expense reports since the connection is managed by the Workspace Admin -- Each NetSuite subsidiary will need its own Expensify Group Workspace -- Ensure that your workspace's report output currency setting matches the NetSuite Subsidiary default currency -- Make sure your page size is set to 1000 for importing your customers and vendors. Go to Setup > Integration > Web Services Preferences > 'Search Page Size' - -# How to Connect to NetSuite - -## Step 1: Install the Expensify Bundle in NetSuite - -1. While logged into NetSuite as an administrator, go to Customization > SuiteBundler > Search & Install Bundles, then search for "Expensify" -2. Click on the Expensify Connect bundle (Bundle ID 283395) -3. Click Install -4. If you already have the Expensify Connect bundle installed, head to _Customization > SuiteBundler > Search & Install Bundles > List_ and update it to the latest version -5. Select **Show on Existing Custom Forms** for all available fields - -## Step 2: Enable Token-Based Authentication - -1. Head to _Setup > Company > Enable Features > SuiteCloud > Manage Authentication_ -2. Make sure ā€œToken Based Authenticationā€ is enabled -3. Click **Save** - -## Step 3: Add Expensify Integration Role to a User - -The user you select must have access to at least the permissions included in the Expensify Integration Role, but they're not required to be an Admin. -1. In NetSuite, head to Lists > Employees, and find the user you want to add the Expensify Integration role to -2. Click _Edit > Access_, then find the Expensify Integration role in the dropdown and add it to the user -3. Click **Save** - -Remember that Tokens are linked to a User and a Role, not solely to a User. It's important to note that you cannot establish a connection with tokens using one role and then switch to another role afterward. Once you've initiated a connection with tokens, you must continue using the same token/user/role combination for all subsequent sync or export actions. - -## Step 4: Create Access Tokens - -1. Using Global Search in NetSuite, enter ā€œpage: tokensā€ -2. Click **New Access Token** -3. Select Expensify as the application (this must be the original Expensify integration from the bundle) -4. Select the role Expensify Integration -5. Press **Save** -6. Copy and Paste the token and token ID to a saved location on your computer (this is the only time you will see these details) - -## Step 5: Confirm Expense Reports are Enabled in NetSuite. - -Enabling Expense Reports is required as part of Expensify's integration with NetSuite: -1. Logged into NetSuite as an administrator, go to Setup > Company > Enable Features > Employees -2. Confirm the checkbox next to Expense Reports is checked -3. If not, click the checkbox and then Save to enable Expense Reports - -## Step 6: Confirm Expense Categories are set up in NetSuite. - -Once Expense Reports are enabled, Expense Categories can be set up in NetSuite. Expense Categories are an alias for General Ledger accounts for coding expenses. - -1. Logged into NetSuite as an administrator, go to Setup > Accounting > Expense Categories (a list of Expense Categories should show) -2. If no Expense Categories are visible, click **New** to create new ones - -## Step 7: Confirm Journal Entry Transaction Forms are Configured Properly - -1. Logged into NetSuite as an administrator, go to _Customization > Forms > Transaction Forms_ -2. Click **Customize** or **Edit** next to the Standard Journal Entry form -3. Then, click Screen Fields > Main. Please verify the "Created From" label has "Show" checked and the Display Type is set to Normal -4. Click the sub-header Lines and verify that the "Show" column for "Receipt URL" is checked -5. Go to _Customization > Forms > Transaction Forms_ and ensure all other transaction forms with the journal type have this same configuration - -## Step 8: Confirm Expense Report Transaction Forms are Configured Properly - -1. Logged into NetSuite as an administrator, go to _Customization > Forms > Transaction Forms_ -2. Click **Customize** or **Edit** next to the Standard Expense Report form, then click **Screen Fields > Main** -3. Verify the "Created From" label has "Show" checked and the Display Type is set to Normal -4. Click the second sub-header, Expenses, and verify that the 'Show' column for 'Receipt URL' is checked -5. Go to _Customization > Forms > Transaction Forms_ and ensure all other transaction forms with the expense report type have this same configuration - -## Step 9: Confirm Vendor Bill Transactions Forms are Configured Properly - -1. Logged into NetSuite as an administrator, go to _Customization > Forms > Transaction Forms_ -2. Click **Customize** or **Edit** next to your preferred Vendor Bill form -3. Then, click _Screen Fields > Main_ and verify that the "Created From" label has "Show" checked and that Departments, Classes, and Locations have the "Show" label unchecked -4. Under the Expenses sub-header (make sure to click the "Expenses" sub-header at the very bottom and not "Expenses & Items"), ensure "Show" is checked for Receipt URL, Department, Location, and Class -5. Go to _Customization > Forms > Transaction Forms_ and provide all other transaction forms with the vendor bill type have this same configuration - -## Step 10: Confirm Vendor Credit Transactions Forms are Configured Properly - -1. While logged in as an administrator, go to _Customization > Forms > Transaction Forms_ -2. Click **Customize** or **Edit** next to your preferred Vendor Credit form, then click _Screen Fields > Main_ and verify that the "Created From" label has "Show" checked and that Departments, Classes, and Locations have the "Show" label unchecked -3. Under the Expenses sub-header (make sure to click the "Expenses" sub-header at the very bottom and not "Expenses & Items"), ensure "Show" is checked for Receipt URL, Department, Location, and Class -4. Go to _Customization > Forms > Transaction Forms_ and ensure all other transaction forms with the vendor credit type have this same configuration - -## Step 11: Set up Tax Groups (only applicable if tracking taxes) - -Expensify imports NetSuite Tax Groups (not Tax Codes), which you can find in NetSuite under _Setup > Accounting > Tax Groups_. - -Tax Groups are an alias for Tax Codes in NetSuite and can contain one or more Tax Codes (Please note: for UK and Ireland subsidiaries, please ensure your Tax Groups do not have more than one Tax Code). We recommend naming Tax Groups so your employees can easily understand them, as the name and rate will be displayed in Expensify. - -Before importing NetSuite Tax Groups into Expensify: -1. Create your Tax Groups in NetSuite by going to _Setup > Accounting > Tax Groups_ -2. Click **New** -3. Select the country for your Tax Group -4. Enter the Tax Name (this is what employees will see in Expensify) -5. Select the subsidiary for this Tax Group -6. Select the Tax Code from the table you wish to include in this Tax Group -7. Click **Add** -8. Click **Save** -9. Create one NetSuite Tax Group for each tax rate you want to show in Expensify - -Ensure Tax Groups can be applied to expenses by going to _Setup > Accounting > Set Up Taxes_ and setting the Tax Code Lists Include preference to "Tax Groups And Tax Codes" or "Tax Groups Only." - -If this field does not display, itā€™s not needed for that specific country. - -## Step 12: Connect Expensify and NetSuite - -1. Log into Expensify as a Policy Admin and go to **Settings > Workspaces > _[Workspace Name]_ > Connections > NetSuite** -2. Click **Connect to NetSuite** -3. Enter your Account ID (Account ID can be found in NetSuite by going to _Setup > Integration > Web Services Preferences_) -4. Then, enter the token and token secret -5. Click **Connect to NetSuite** - -From there, the NetSuite connection will sync, and the configuration dialogue box will appear. - -Please note that you must create the connection using a NetSuite account with the Expensify Integration role - -Once connected, all reports exported from Expensify will be generated in NetSuite using SOAP Web Services (the term NetSuite employs when records are created through the integration). - -# How to Configure Export Settings +# Step 1: Configure Export Settings There are numerous options for exporting Expensify reports to NetSuite. Let's explore how to configure these settings to align with your business needs. + To access these settings, head to **Settings > Workspace > Group > Connections** and select the **Configure** button. ## Export Options @@ -206,9 +83,9 @@ Select the Accounts Receivable account you want your Invoice Reports to export. ### Default Vendor Bills -The list of vendors will be available in the dropdown when selecting the option to export non-reimbursable expenses as vendor bills. +When selecting the option to export non-reimbursable expenses as vendor bills, the list of vendors will be available in the dropdown menu. -# How to Configure Coding Settings +# Step 2: Configure Coding Settings The Coding tab is where NetSuite information is configured in Expensify, which allows employees to code expenses and reports accurately. There are several coding options in NetSuite. Letā€™s go over each of those below. @@ -313,7 +190,7 @@ If configuring Custom Segments as Report Fields, use the Field ID on the Transac If configuring Custom Segments as Tags, use the Field ID on the Transaction Columns tab (under _Custom Segments > Transaction Columns_). Lastly, head over to Expensify and do the following: -1. Navigate to **Settings > Workspace > Group > [Workspace Name]_ > Connections > Configure > Coding tab** +1. Navigate to **Settings > Workspace > Group > [Workspace Name] > Connections > Configure > Coding tab** 2. Choose how to import Custom Records (Report Fields or Tags) 3. Fill out the three fields (the name or label of the record, Internal ID, Transaction Column ID) 4. Click **Submit** @@ -328,7 +205,7 @@ To add Custom Lists to your workspace, youā€™ll need to locate two fields in Net **To find the record:** 1. Log into Expensify -2. Head to **Settings > Workspace > Group > _[Workspace Name]_ > Connections > Configure > Coding tab** +2. Head to **Settings > Workspace > Group > [Workspace Name] > Connections > Configure > Coding tab** 3. The name of the record will be populated in a dropdown list The name of the record will populate in a dropdown list. If you don't see the one you are looking for, click **Refresh Custom List Options**. @@ -339,14 +216,14 @@ The name of the record will populate in a dropdown list. If you don't see the on 3. Open the option that is holding the record to get the ID Lastly, head over to Expensify, and do the following: -1. Navigate to **Settings > Workspaces > Group > _[Workspace Name]_ > Connections > Configure > Coding tab** +1. Navigate to **Settings > Workspaces > Group > [Workspace Name] > Connections > Configure > Coding tab** 2. Choose how to import Custom Lists (Report Fields or Tags) 3. Enter the ID in Expensify in the configuration screen 4. Click **Submit** From there, you should see the values for the Custom Lists under the Tag or Report Field settings in Expensify. -# How to Configure Advanced Settings +# Step 3: Configure Advanced Settings The NetSuite integrationā€™s advanced configuration settings are accessed under **Settings > Workspaces > Group > _[Workspace Name]_ > Connections > NetSuite > Configure > Advanced tab**. @@ -384,13 +261,13 @@ Besides inviting employees, you can also establish an approval process in NetSui By doing this, the Approval Workflow in Expensify will automatically follow the same rules as NetSuite, typically starting with Manager Approval. -- **Basic Approval:** A single level of approval, where all users submit directly to a Final Approver. The Final Approver defaults to the workspace owner but can be edited on the people page. +- **Basic Approval:** This is a single level of approval, where all users submit directly to a Final Approver. The Final Approver defaults to the workspace owner but can be edited on the people page. - **Manager Approval (default):** Two levels of approval route reports first to an employee's NetSuite expense approver or supervisor, and second to a workspace-wide Final Approver. By NetSuite convention, Expensify will map to the supervisor if no expense approver exists. The Final Approver defaults to the workspace owner but can be edited on the people page. - **Configure Manually:** Employees will be imported, but all levels of approval must be manually configured on the workspace's People settings page. If you enable this setting, itā€™s recommended you review the newly imported employees and managers on the **Settings > Workspaces > Group > _[Workspace Name]_ > People page**. You can set a user role for each new employee and enforce an approval workflow. ## Automatically Create Employees/Vendors -With this feature enabled, Expensify will automatically create a new employee or vendor (if one doesnā€™t already exist) from the email of the report submitter in NetSuite. +With this feature enabled, Expensify will automatically create a new employee or vendor (if one doesnā€™t already exist) from the report submitter's email in NetSuite. ## Export Foreign Currency Amount @@ -430,13 +307,12 @@ If you do not wish to use Approval Routing in NetSuite, go to _Setup > Accountin When exporting invoices, once marked as Paid, the payment is marked against the account selected after enabling the Collection Account setting. -# Deep Dive - +# Additional Settings ## Categories You can use the Auto-Categorization feature so that expenses are automatically categorized. -To set Category Rules (e.g., receipt requirements or comments), go to the categories page in the workspace under **Settings > Workspaces > _[Workspace Name]_ > Categories**. +To set Category Rules (e.g., receipt requirements or comments), go to the categories page in the workspace under **Settings > Workspaces > [Workspace Name] > Categories**. With this setting enabled, when an Expense Category updates in NetSuite, it will update in Expensify automatically. @@ -448,7 +324,7 @@ NetSuite's company card feature simplifies exporting reimbursable and non-reimbu 2. **Default Accounts Payable (A/P) Account:** Expense reports enable you to set a default A/P account for export on your subsidiary record. Unlike vendor bills, where the A/P account defaults to the last selected account, the expense report export option allows you to establish a default A/P account. 3. **Mix Reimbursable and Non-Reimbursable Expenses:** You can freely mix reimbursable and non-reimbursable expenses without categorizing them in NetSuite after export. NetSuite's corporate card feature automatically categorizes expenses into the correct GL accounts, ensuring a neat and organized GL impact. -#### Letā€™s go over an example! +**Letā€™s go over an example!** Consider an expense report with one reimbursable and one non-reimbursable expense. Each needs to be exported to different accounts and expense categories. @@ -456,7 +332,7 @@ In NetSuite, you can quickly identify the non-reimbursable expense marked as a c Furthermore, each expense is categorized according to your selected expense category. -You'll need to set up default corporate cards in NetSuite to use the expense report option for your corporate card expenses. +To use the expense report option for your corporate card expenses, you'll need to set up default corporate cards in NetSuite. For non-reimbursable expenses, choose the appropriate card on the subsidiary record. You can find the default in your accounting preferences if you're not using a OneWorld account. @@ -545,7 +421,7 @@ When exporting to NetSuite, we match the recipient's email address on the invoic Once exported, the invoice will appear in the Accounts Receivable account you selected during your NetSuite Export configuration. -### Updating an Invoice to paid +### Updating the status of an invoice to "paid" When you mark an invoice as "Paid" in Expensify, this status will automatically update in NetSuite. Similarly, if the invoice is marked as "Paid" in NetSuite, it will sync with Expensify. The payment will be reflected in the Collection account specified in your Advanced Settings Configuration. @@ -562,10 +438,6 @@ Send these two files to your Account Manager or Concierge so we can continue tro {% include faq-begin.md %} -## What type of Expensify plan is required for connecting to NetSuite? - -You need a group workspace on a Control Plan to integrate with NetSuite. - ## How does Auto Sync work with reimbursed reports? If a report is reimbursed via ACH or marked as reimbursed in Expensify and then exported to NetSuite, the report is automatically marked as paid in NetSuite during the next sync. @@ -574,6 +446,24 @@ If a report is exported to NetSuite and then marked as paid in NetSuite, the rep ## If I enable Auto Sync, what happens to existing approved and reimbursed reports? -If you previously had Auto Sync disabled but want to allow that feature to be used going forward, you can safely turn on Auto Sync without affecting existing reports. Auto Sync will only take effect for reports created after enabling that feature. +If you previously had Auto Sync disabled but want to allow that feature to be used going forward, you can safely turn it on without affecting existing reports. Auto Sync will only take effect for reports created after enabling that feature. + +## Why are some of my customers not importing from NetSuite? + +If only part of your customer list is importing from NetSuite to Expensify, ensure your page size is set to 1000 for importing customers and vendors: +1. Navigate to **Setup > Integration > Web Services Preferences > Search Page Size** +2. Adjust this setting to 1000 +3. Sync your connection again under **Settings > Workspaces > Group > Workspace Name > Connections** + +Additionally, ensure the "Company Name" field is completed for each customer profile; otherwise, they won't import into the Group Workspace. + +## Why aren't all my Categories pulling into Expensify from NetSuite? + +If you're having trouble importing your Categories, you'll want to start by checking that they are set up in NetSuite as actual Expense Categories, not General Ledger accounts: +- Log into NetSuite as an administrator and go to **Setup > Accounting > Expense Categories** +- A list of Expense Categories should be available +- If no Expense Categories are visible click on "New" to create new Expense Categories + +If you have confirmed that your categories are set as Expense Categories in NetSuite and they still aren't importing to Expensify, make sure that the subsidiary of the Expense Category matches the subsidiary selected in your connection settings. {% include faq-end.md %} diff --git a/docs/articles/expensify-classic/connections/netsuite/Connect-To-NetSuite.md b/docs/articles/expensify-classic/connections/netsuite/Connect-To-NetSuite.md new file mode 100644 index 000000000000..1f96d9b8a633 --- /dev/null +++ b/docs/articles/expensify-classic/connections/netsuite/Connect-To-NetSuite.md @@ -0,0 +1,164 @@ +--- +title: NetSuite +description: Set up the direct connection from Expensify to NetSuite. +order: 1 +--- +# Overview +Expensify's integration with NetSuite allows you to automate report exports, tailor your coding preferences, and tap into NetSuite's array of advanced features. By correctly configuring your NetSuite settings in Expensify, you can leverage the connection's settings to automate most of the tasks, making your workflow more efficient. + +**Before connecting NetSuite to Expensify, a few things to note:** +- Token-based authentication works by ensuring that each request to NetSuite is accompanied by a signed token which is verified for authenticity +- You must be able to login to NetSuite as an administrator to initiate the connection +- You must have a Control Plan in Expensify to integrate with NetSuite +- Employees donā€™t need NetSuite access or a NetSuite license to submit expense reports since the connection is managed by the Workspace Admin +- Each NetSuite subsidiary will need its own Expensify Group Workspace +- Ensure that your workspace's report output currency setting matches the NetSuite Subsidiary default currency +- Make sure your page size is set to 1000 for importing your customers and vendors. You can check this in NetSuite under **Setup > Integration > Web Services Preferences > 'Search Page Size'** + +# Connect to NetSuite + +## Step 1: Install the Expensify Bundle in NetSuite + +1. While logged into NetSuite as an administrator, go to Customization > SuiteBundler > Search & Install Bundles, then search for "Expensify" +2. Click on the Expensify Connect bundle (Bundle ID 283395) +3. Click Install +4. If you already have the Expensify Connect bundle installed, head to _Customization > SuiteBundler > Search & Install Bundles > List_ and update it to the latest version +5. Select **Show on Existing Custom Forms** for all available fields + +## Step 2: Enable Token-Based Authentication + +1. Head to _Setup > Company > Enable Features > SuiteCloud > Manage Authentication_ +2. Make sure ā€œToken Based Authenticationā€ is enabled +3. Click **Save** + +## Step 3: Add Expensify Integration Role to a User + +The user you select must have access to at least the permissions included in the Expensify Integration Role, but they're not required to be an Admin. +1. In NetSuite, head to Lists > Employees, and find the user you want to add the Expensify Integration role to +2. Click _Edit > Access_, then find the Expensify Integration role in the dropdown and add it to the user +3. Click **Save** + +Remember that Tokens are linked to a User and a Role, not solely to a User. It's important to note that you cannot establish a connection with tokens using one role and then switch to another role afterward. Once you've initiated a connection with tokens, you must continue using the same token/user/role combination for all subsequent sync or export actions. + +## Step 4: Create Access Tokens + +1. Using Global Search in NetSuite, enter ā€œpage: tokensā€ +2. Click **New Access Token** +3. Select Expensify as the application (this must be the original Expensify integration from the bundle) +4. Select the role Expensify Integration +5. Press **Save** +6. Copy and Paste the token and token ID to a saved location on your computer (this is the only time you will see these details) + +## Step 5: Confirm Expense Reports are Enabled in NetSuite. + +Enabling Expense Reports is required as part of Expensify's integration with NetSuite: +1. Logged into NetSuite as an administrator, go to Setup > Company > Enable Features > Employees +2. Confirm the checkbox next to Expense Reports is checked +3. If not, click the checkbox and then Save to enable Expense Reports + +## Step 6: Confirm Expense Categories are set up in NetSuite. + +Once Expense Reports are enabled, Expense Categories can be set up in NetSuite. Expense Categories are an alias for General Ledger accounts used to code expenses. + +1. Logged into NetSuite as an administrator, go to Setup > Accounting > Expense Categories (a list of Expense Categories should show) +2. If no Expense Categories are visible, click **New** to create new ones + +## Step 7: Confirm Journal Entry Transaction Forms are Configured Properly + +1. Logged into NetSuite as an administrator, go to _Customization > Forms > Transaction Forms_ +2. Click **Customize** or **Edit** next to the Standard Journal Entry form +3. Then, click Screen Fields > Main. Please verify the "Created From" label has "Show" checked and the Display Type is set to Normal +4. Click the sub-header Lines and verify that the "Show" column for "Receipt URL" is checked +5. Go to _Customization > Forms > Transaction Forms_ and ensure all other transaction forms with the journal type have this same configuration + +## Step 8: Confirm Expense Report Transaction Forms are Configured Properly + +1. Logged into NetSuite as an administrator, go to _Customization > Forms > Transaction Forms_ +2. Click **Customize** or **Edit** next to the Standard Expense Report form, then click **Screen Fields > Main** +3. Verify the "Created From" label has "Show" checked and the Display Type is set to Normal +4. Click the second sub-header, Expenses, and verify that the 'Show' column for 'Receipt URL' is checked +5. Go to _Customization > Forms > Transaction Forms_ and ensure all other transaction forms with the expense report type have this same configuration + +## Step 9: Confirm Vendor Bill Transactions Forms are Configured Properly + +1. Logged into NetSuite as an administrator, go to _Customization > Forms > Transaction Forms_ +2. Click **Customize** or **Edit** next to your preferred Vendor Bill form +3. Then, click _Screen Fields > Main_ and verify that the "Created From" label has "Show" checked and that Departments, Classes, and Locations have the "Show" label unchecked +4. Under the Expenses sub-header (make sure to click the "Expenses" sub-header at the very bottom and not "Expenses & Items"), ensure "Show" is checked for Receipt URL, Department, Location, and Class +5. Go to _Customization > Forms > Transaction Forms_ and provide all other transaction forms with the vendor bill type have this same configuration + +## Step 10: Confirm Vendor Credit Transactions Forms are Configured Properly + +1. While logged in as an administrator, go to _Customization > Forms > Transaction Forms_ +2. Click **Customize** or **Edit** next to your preferred Vendor Credit form, then click _Screen Fields > Main_ and verify that the "Created From" label has "Show" checked and that Departments, Classes, and Locations have the "Show" label unchecked +3. Under the Expenses sub-header (make sure to click the "Expenses" sub-header at the very bottom and not "Expenses & Items"), ensure "Show" is checked for Receipt URL, Department, Location, and Class +4. Go to _Customization > Forms > Transaction Forms_ and ensure all other transaction forms with the vendor credit type have this same configuration + +## Step 11: Set up Tax Groups (only applicable if tracking taxes) + +Expensify imports NetSuite Tax Groups (not Tax Codes), which you can find in NetSuite under _Setup > Accounting > Tax Groups_. + +Tax Groups are an alias for Tax Codes in NetSuite and can contain one or more Tax Codes (Please note: for UK and Ireland subsidiaries, please ensure your Tax Groups do not have more than one Tax Code). We recommend naming Tax Groups so your employees can easily understand them, as the name and rate will be displayed in Expensify. + +Before importing NetSuite Tax Groups into Expensify: +1. Create your Tax Groups in NetSuite by going to _Setup > Accounting > Tax Groups_ +2. Click **New** +3. Select the country for your Tax Group +4. Enter the Tax Name (this is what employees will see in Expensify) +5. Select the subsidiary for this Tax Group +6. Select the Tax Code from the table you wish to include in this Tax Group +7. Click **Add** +8. Click **Save** +9. Create one NetSuite Tax Group for each tax rate you want to show in Expensify + +Ensure Tax Groups can be applied to expenses by going to _Setup > Accounting > Set Up Taxes_ and setting the Tax Code Lists Include preference to "Tax Groups And Tax Codes" or "Tax Groups Only." + +If this field does not display, itā€™s not needed for that specific country. + +## Step 12: Connect Expensify and NetSuite + +1. Log into Expensify as a Policy Admin and go to **Settings > Workspaces > _[Workspace Name]_ > Connections > NetSuite** +2. Click **Connect to NetSuite** +3. Enter your Account ID (Account ID can be found in NetSuite by going to _Setup > Integration > Web Services Preferences_) +4. Then, enter the token and token secret +5. Click **Connect to NetSuite** + +From there, the NetSuite connection will sync, and the configuration dialogue box will appear. + +Please note that you must create the connection using a NetSuite account with the Expensify Integration role + +Once connected, all reports exported from Expensify will be generated in NetSuite using SOAP Web Services (the term NetSuite employs when records are created through the integration). + +{% include faq-begin.md %} + +## Can negative expenses be exported to NetSuite? +You can export reports with a negative total to NetSuite by selecting ā€œVendor Billā€ as your export option. When a report total is negative, weā€™ll create a Vendor Credit in NetSuite instead of a bill. + +**Important**: Only enable this if you pay your employees/vendors outside of Expensify. A Vendor Credit reduces the total amount payable in NetSuite, but not in Expensify. + +To use this feature, make sure you have configured your Vendor Credit transaction form in NetSuite and are using the latest version of the Expensify bundle (version 1.4). If you need to update, go to **Customization > SuiteBundler > Search & Install Bundles > List** and click **Update** next to **Expensify Connect**. + +## How do you switch the owner of the connection between NetSuite and Expensify? + +Follow the steps below to transfer ownership of the NetSuite connection to someone else: +1. Head to **Settings > Workspaces > Workspace Name > Connections > NetSuite** +2. Click **Configure** to review and save the settings for future reference +3. Select **Do not connect to NetSuite** +4. Select **Connect to NetSuite** +5. Enter the email address of the new admin who will take over as the NetSuite User ID +6. Enter the NetSuite Account ID (found in NetSuite under **Setup > Integration > Web Services Preferences**) +7. Click **Create a new NetSuite Connection** +8. Confirm completion of prerequisites and proceed by clicking Continue +9. You will be redirected to the NetSuite SSO page, where you will enter the email address of the new connection owner and the NetSuite password for that account +10. Once redirected to the NetSuite page, click **View all roles** and ensure you are logged in under the Administrator role +11. After confirmation, sign out +12. Return to Expensify to reconfigure the sync and export settings on the updated connection +13. Click **Save** + +**If you run into any issues updating the connection, follow these additional troubleshooting steps:** +- In NetSuite, access the role of the current connection owner +- Click Edit > Access > Choose any role other than Administrator > Save +- Click Edit > Access > Select Administrator role > Save +- Repeat the steps outlined above + +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/connections/netsuite/Netsuite-Troubleshooting.md b/docs/articles/expensify-classic/connections/netsuite/Netsuite-Troubleshooting.md new file mode 100644 index 000000000000..01aa21a28b80 --- /dev/null +++ b/docs/articles/expensify-classic/connections/netsuite/Netsuite-Troubleshooting.md @@ -0,0 +1,464 @@ +--- +title: Netsuite Troubleshooting +description: Troubleshoot common NetSuite sync and export errors. +--- + +# Overview of NetSuite Troubleshooting +Synchronizing and exporting data between Expensify and NetSuite can streamline your financial processes, but occasionally, users may encounter errors that prevent a smooth integration. These errors often arise from discrepancies in settings, missing data, or configuration issues within NetSuite or Expensify. + +This troubleshooting guide aims to help you identify and resolve common sync and export errors, ensuring a seamless connection between your financial management systems. By following the step-by-step solutions provided for each specific error, you can quickly address issues and maintain accurate and efficient expense reporting and data management. + +# ExpensiError NS0005: Please enter value(s) for Department, Location or Class + +This error occurs when the classification (like Location) is required at the header level of your transaction form in NetSuite. + +For expense reports and journal entries, NetSuite uses classifications from the employee record default. Expensify only exports this information at the line item level. + +For vendor bills, these classifications can't be mandatory because we use the vendor record instead of the employee record, and vendor records donā€™t have default classifications. + +**Vendor Bills:** +When exporting as a Vendor Bill, we pull from the vendor record, not the employee. Therefore, employee defaults donā€™t apply at the header ("main") level. This error appears if your NetSuite transaction form requires those fields. + +## How to Fix ExpensiError NS0005 +1. Go to **Customization > Forms > Transaction Forms**. +2. Click **"Edit"** on your preferred vendor bill form. +3. Go to **Screen Fields > Main**. +4. Uncheck both **"Show"** and **"Mandatory"** for the listed fields in your error message. +5. Sync the workspace connection in Expensify (**Settings > Workspaces > Workspace Name > Connections > Sync**). +6. Attempt the export again. + +**Journal Entries and Expense Reports:** +If you see this error when exporting a Journal Entry or Expense Report, it might be because the report submitter doesnā€™t have default settings for Departments, Classes, or Locations. + +**To fix this:** +1. Go to **Lists > Employees** in NetSuite. +2. Click **"Edit"** next to the employee's name who submitted the report. +3. Scroll down to the **Classification** section. +4. Select a default **Department**, **Class**, and **Location** for the employee. +5. Click **Save**. +6. Sync your NetSuite connection in Expensify. + + +# ExpensiError NS0012: Currency Does Not Exist In NetSuite + +**Scenario One:** When dealing with foreign transactions, Expensify sends the conversion rate and currency of the original expense to NetSuite. If the currency isn't listed in your NetSuite subsidiary, you'll see an error message saying the currency does not exist in NetSuite. + +**To fix this:** +1. Ensure the currency in Expensify matches what's in your NetSuite subsidiary. +2. If you see an error saying 'The currency X does not exist in NetSuite', re-sync your connection to NetSuite through the workspace admin section in Expensify. +3. Try exporting again. + +**Scenario Two:** This error can happen if youā€™re using a non-OneWorld NetSuite instance and exporting a currency other than EUR, GBP, USD, or CAD. + +**To fix this:** +1. Head to NetSuite. +2. Go to **Setup > Enable Features**. +3. Check the **Multiple Currencies** box. + +Once you've done this, you can add the offending currency by searching **New Currencies** in the NetSuite global search. + + +# ExpensiError NS0021: Invalid tax code reference key + +This error usually indicates an issue with the Tax Group settings in NetSuite, which can arise from several sources. + +#### Tax Group to Tax Code Mapping +If a Tax Code on Sales Transactions is mapped to a Tax Group, an error will occur. To fix this, the Tax Code must be mapped to a Tax Code on Purchase Transactions instead. + +To verify if a Tax Code is for Sales or Purchase transactions, view the relevant Tax Code(s). + +**For Australian Taxes:** +Ensure your Tax Groups are mapped correctly: +- **GST 10%** to **NCT-AU** (not the Sales Transaction Tax Code TS-AU) +- **No GST 0%** to **NCF-AU** (not the Sales Transaction Tax Code TFS-AU) + +#### Tax Group Type +Tax Groups can represent different types of taxes. For compatibility with Expensify, ensure the tax type is set to GST/VAT. + +#### Enable Tax Groups +Some subsidiaries require you to enable Tax Groups. Go to **Set Up Taxes** for the subsidiary's country and ensure the Tax Code lists include both Tax Codes and Tax Groups. + + +# ExpensiError NS0023: Employee Does Not Exist in NetSuite (Invalid Employee) + +This can happen if the employeeā€™s subsidiary in NetSuite doesnā€™t match whatā€™s listed in Expensify. + +## How to Fix ExpensiError NS0023 +1. **Check the Employee's Subsidiary** + - Go to the employee record in NetSuite. + - Confirm the employee's subsidiary matches whatā€™s listed as the subsidiary at the workspace level. + - To find this in Expensify navigate to **Settings > Workspaces > Workspace Name > Connections > Configure**. + - If the subsidiaries donā€™t match, update the subsidiary in Expensify to match whatā€™s listed in NetSuite. + - Sync the NetSuite connection in Expensify. +2. **Verify Access Restrictions:** + - Go to **Lists > Employees > Employees > [Select Employee] > Edit > Access**. + - Uncheck **Restrict Access to Expensify**. +3. **Additional Checks:** + - Ensure the email on the employee record in NetSuite matches the email address of the report submitter in Expensify. + - In NetSuite, make sure the employee's hire date is in the past and/or the termination date is in the future. +4. **Currency Match for Journal Entries:** + - If exporting as Journal Entries, ensure the currency for the NetSuite employee record, NetSuite subsidiary, and Expensify policy all match. + - In NetSuite, go to the **Human Resources** tab > **Expense Report Currencies**, and add the subsidiary/policy currency if necessary. + + +# ExpensiError NS0024: Invalid Customer or Project Tag + +Employees must be listed as a resource on the customer/project in NetSuite to be able to apply it to an expense. If that isnā€™t set up in NetSuite, you can run into this error. + +## How to Fix ExpensiError NS0024 + +1. **Ensure Employee Access:** + - In NetSuite, go to **Lists > Relationships > Customer/Projects**. + - Click **Edit** next to the desired Customer/Project. + - Click **Resources**, select the Employee from the drop-down menu, click **Add**, then **Save** your changes. +2. **Sync with Expensify:** + - In Expensify, go to **Settings > Workspaces > [Workspace Name] > NetSuite > Sync Now**. + - Attempt to export again. +3. **Remove Restriction for a Specific Customer/Project (Optional):** + - In NetSuite, edit the customer/project. + - Go to **Preferences**, then uncheck **Limit time and expenses to resources**. +4. **Remove Restrictions for All Projects:** + - In NetSuite, go to **Setup > Accounting > Accounting Preferences > Time & Expenses**. + - Uncheck **Show Projects Only For Time And Expense Entry**. +5. **Enable Cross-Subsidiary Customers/Projects in Expensify (Optional):** + - Go to **Settings > Workspaces > Group > [Workspace Name] > Connections > NetSuite > Configure > Advanced**. + - Enable **Cross-Subsidiary Customers/Projects** to remove the requirement for the employee's subsidiary and the customer's subsidiary to match. + + +# ExpensiError NS0034: This record already exists + +This error occurs when the report in question was already exported to NetSuite. + +## How to fix ExpensiError NS0034 +1. **Check for the existing Report in NetSuite:** + - If the report already exists in NetSuite but has been edited in Expensify, you need to delete the report in NetSuite. +2. **Find the Report ID in Expensify:** + - Locate the Report ID in Expensify under the Details section in the top right corner of the report. +3. **Search for the Report ID in NetSuite:** + - Use the Global Search Box in NetSuite to find the report using the Report ID. +4. **Delete the Report in NetSuite:** + - In NetSuite, click _**Edit > Actions > Delete**_ to remove the report. +5. **Re-export the Report from Expensify to NetSuite:** + - After deleting the report in NetSuite, re-export it from Expensify to NetSuite. + + +# ExpensiError NS0046: Billable Expenses Not Coded with a NetSuite Customer or Billable Project + +NetSuite requires billable expenses to be assigned to a Customer or a Project that is configured as billable to a Customer. If this is not set up correctly in NetSuite, this error can occur. + +## How to Fix ExpensiError NS0046 +1. **Access the Report in Expensify:** + - Go to the Expensify website and open the report. +2. Click the **Details** icon in the upper-left corner of the report. +3. Select the following options (this allows you to easily see which expenses are flagged as billable but don't have a valid customer tagged): + - **View:** Details + - **Group by:** Tag + - **Split report by:** Billable +4. **Check Billable Expenses:** + - Click on each expense in the Billable section of the report. + - Ensure that the Customer or Project tag field is present. + - Verify that there are no violations and that a value has been applied to the field. +5. Make any necessary adjustments to the billable expenses and try the export again. + + +# ExpensiError NS0059: A credit card account has not been selected for corporate card expenses. + +**To resolve this error:** +1. Log into NetSuite as an admin. +2. Type "Page: Subsidiaries" in the global search box and select the subsidiary you will export to. +3. Under the Preferences tab of the subsidiary, locate the field: Default Account for Corporate Card Expenses. + +**If you want to assign different cards to different employees:** +1. Go to each employee record in NetSuite. +2. Under the Human Resources > Expense and Purchasing section, find the field: Default Account for Corporate Card Expenses. + +**For reports containing cash expenses that are not marked as Reimbursable:** +1. Have the approver reject the report. +2. Mark the expenses as Reimbursable. +3. Re-submit the report, approve it, and try to export again. + +For accounts without subsidiaries (non-OneWorld accounts), the default field is in your accounting preferences. + + +# ExpensiError NS0085: Expense Does Not Have Appropriate Permissions for Settings an Exchange Rate in NetSuite + +This error occurs when the exchange rate settings in NetSuite aren't updated correctly. + +## How to Fix ExpensiError NS0085 +1. In NetSuite, go to Customization > Forms > Transaction Forms. +2. Search for the form type that the report is being exported as (Expense Report, Journal Entry, or Vendor Bill) and click Edit next to the form that has the Preferred checkbox checked. + - **For Expense Reports:** + - Go to Screen Fields > Expenses (the Expenses tab farthest to the right). + - Ensure the Exchange Rate field under the Description column has the Show checkbox checked. + - **For Vendor Bills:** + - Go to Screen Fields > Main. + - Ensure the Exchange Rate field under the Description column has the Show checkbox checked. + - **For Journal Entries:** + - Go to Screen Fields > Lines. + - Ensure the Exchange Rate field under the Description column has the Show checkbox checked. + - Go to Screen Fields > Main and ensure the Show checkbox is checked in the Exchange Rate field under the Description column. +3. Go to **Settings > Workspaces > Group > [Workspace Name] > Connections**. +4. Click Sync Now to sync the NetSuite connection. +5. Export the report(s) again. + + +# ExpensiError NS0079: The Transaction Date is Not Within the Date Range of Your Accounting Period + +The transaction date you specified is not within the date range of your accounting period. When the posting period settings in NetSuite are not configured to allow a transaction date outside the posting period, you can't export a report to the next open period, which is why youā€™ll run into this error. + +## How to Fix ExpensiError NS0079 +1. In NetSuite, navigate to Setup > Accounting > Accounting Preferences. +2. Under the General Ledger section, ensure the field Allow Transaction Date Outside of the Posting Period is set to Warn. +3. Then, choose whether to export your reports to the First Open Period or the Current Period. + +Additionally, ensure the Export to Next Open Period feature is enabled within Expensify: +1. Navigate to **Settings > Workspaces > Group > [Workspace Name] > Connections > Configure**. +2. Open the **Advanced tab**. +3. Confirm that the setting for **Export to Next Open Period** is enabled. + +If any configuration settings are updated on the NetSuite connection, be sure to sync the connection before trying the export again. + + +# ExpensiError NS0055: The Vendor You are Trying to Export to Does Not Have Access to the Currency X + +This error occurs when a vendor tied to a report in Expensify does not have access to a currency on the report in NetSuite. The vendor used in NetSuite depends on the type of expenses on the report you're exporting. +- For **reimbursable** (out-of-pocket) expenses, this is the report's submitter (the employee who submitted the report). +- For **non-reimbursable** (e.g., company card) expenses, this is the default vendor set via Settings > Workspaces > Group > [Workspace Name] > Connections > NetSuite > Configure. + +## How to Fix ExpensiError NS0055 +To fix this, the vendor needs to be given access to the applicable currency: +1. In NetSuite, navigate to Lists > Relationships > Vendors to access the list of Vendors. +2. Click Edit next to the Vendor tied to the report: + - For reimbursable (out-of-pocket) expenses, this is the report's submitter. + - For non-reimbursable (e.g., company card) expenses, this is the default vendor set via **Settings > Workspaces > Group > [Workspace Name] > Connections > NetSuite > Configure**. +3. Navigate to the Financial tab. +4. Scroll down to the Currencies section and add all the currencies that are on the report you are trying to export. +5. Click Save. + + +# ExpensiError NS0068: You do not have permission to set a value for element - ā€œCreated Fromā€ + +**To resolve this error:** +1. In NetSuite, go to Customization > Forms > Transaction Forms. +2. Search for the form type that the report is being exported as in NetSuite (Expense Report, Journal Entry, Vendor Bill, or if the report total is negative, Vendor Credit). +3. Click Edit next to the form that has the Preferred checkbox checked. +4. Go to Screen Fields > Main and ensure the field Created From has the Show checkbox checked. +5. Sync the NetSuite connection under **Settings > Workspaces > Group > [Workspace Name] > Connections > Sync Now**. +6. Export the report(s) again. + +#### For reports with Expensify Card expenses +Expensify Card expenses export as Journal Entries. If you encounter this error when exporting a report with Expensify Card non-reimbursable expenses, ensure the field Created From has the Show checkbox checked for Journal Entries in NetSuite. + + +# ExpensiError NS0037: You do not have permission to set a value for element - ā€œReceipt URLā€ + +**To resolve this error:** +1. In NetSuite, go to Customization > Forms > Transaction Forms. +2. Search for the form type that the report is being exported as in NetSuite (Expense Report, Journal Entry, or Vendor Bill). +3. Click Edit next to the form that has the Preferred checkbox checked. + - If the report is being exported as an Expense Report: + - Go to Screen Fields > Expenses (the Expenses tab farthest to the right). + - Ensure the field ReceiptURL has the Show checkbox checked. + - If the report is being exported as a Journal Entry: + - Go to Screen Fields > Lines. + - Ensure the field ReceiptURL has the Show checkbox checked. + - If the report is being exported as a Vendor Bill: + - Go to Screen Fields > Main. + - Ensure the field ReceiptURL has the Show checkbox checked. +4. Click Sync Now to sync the NetSuite connection at **Settings > Workspaces > Group > Workspace Name > Connections**. +5. Export the report(s) again. + + +# ExpensiError NS0042: Error creating vendor - this entity already exists + +This error occurs when a vendor record already exists in NetSuite, but Expensify is still attempting to create a new one. This typically means that Expensify cannot find the existing vendor during export. +- The vendor record already exists in NetSuite, but there may be discrepancies preventing Expensify from recognizing it. +- The email on the NetSuite vendor record does not match the email of the report submitter in Expensify. +- The vendor record might not be associated with the correct subsidiary in NetSuite. + +## How to Fix ExpensiError NS0042 + +Follow these steps to resolve the issue: +1. **Check Email Matching:** + - Ensure the email on the NetSuite vendor record matches the email of the report submitter in Expensify. +2. **Check Subsidiary Association:** + - Ensure the vendor record is associated with the same subsidiary selected in the connection configurations + - You can review this under **Settings > Workspaces > Group > Workspace Name > Connections > Configure**. +3. **Automatic Vendor Creation:** + - If you want Expensify to automatically create vendors, ensure the "Automatically Create Vendor" option is enabled under **Settings > Workspaces > Group > Workspace Name > Connections > Advanced**. + +**Options to Resolve the Error:** +- **Edit the Existing Vendor:** Update the existing vendor record in NetSuite to match the report submitter's email and name. +- **Delete the Existing Vendor:** If appropriate, delete the existing vendor record in NetSuite to allow Expensify to create a new one. +- **Add Email to Existing Vendor:** Add the email address of the reportā€™s submitter to the existing vendor record in NetSuite. + +**Final Steps:** +1. After making the necessary changes, head to **Settings > Workspaces > Group > Workspace Name > Connections** in Expensify. +2. Sync the NetSuite workspace connection. +3. Retry exporting the report. + + +# ExpensiError NS0109: Failed to login to NetSuite, please verify your credentials + +This error indicates a problem with the tokens created for the connection between Expensify and NetSuite. The error message will say, "Login Error. Please check your credentials." + +## How to Fix ExpensiError NS0109 +1. Review the [Connect to NetSuite](https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/NetSuite) guide and follow steps 1 and 2 exactly as outlined. +2. If you're using an existing token and encounter a problem, you may need to create a new token. + + +# ExpensiError NS0123 Login Error: Please make sure that the Expensify integration is enabled + +This error indicates that the Expensify integration is not enabled in NetSuite. + +## How to Fix ExpensiError NS0123 +1. **Enable the Expensify Integration:** + - In NetSuite, navigate to Setup > Integrations > Manage Integrations. + - Ensure that the Expensify Integration is listed and that the State is Enabled. +2. **If you can't find the Expensify integration:** + - Click "Show Inactives" to see if Expensify is listed as inactive. + - If Expensify is listed, update its state to Enabled. + +Once the Expensify integration is enabled, try syncing the NetSuite connection again. + + +# ExpensiError NS0045: Expenses Not Categorized with a NetSuite Account + +**To resolve this error:** +1. Log into NetSuite +2. Do a global search for the missing record. + - Ensure the expense category is active and correctly named. + - Ensure the category is associated with the correct subsidiary that the Expensify workspace is linked to. +3. In Expensify, head to **Settings > Workspaces > Groups > Workspace Name > Connections** and click **Sync Now** on the NetSuite connection to resync the workspace. +4. Go back to the report, click on the offending expense(s), and re-apply the category in question. +5. Export the report again. + + +# ExpensiError NS0061: Please Enter Value(s) for: Tax Code + +This error typically occurs when attempting to export expense reports to a Canadian subsidiary in NetSuite for the first time and/or if your subsidiary in NetSuite has Tax enabled. + +## How to Fix ExpensiError NS0061 +To fix this, you need to enable Tax in the NetSuite configuration settings. + +1. Go to **Settings > Workspaces > Group > Workspace Name > Connections > NetSuite**. + - Be sure to select posting accounts for GST/HST and PST if you plan on exporting any expenses with taxes on them to Journal Entries. +2. Click **Save** +3. Click **Sync Now** to sync the connection + +**Note:** Expenses created before Tax was enabled might need to have the newly imported taxes applied to them retroactively to be exported. + + +# Error creating employee: Your current role does not have permission to access this record. + +This error indicates that the credentials or role used to connect NetSuite to Expensify do not have the necessary permissions within NetSuite. You can find setup instructions for configuring permissions in NetSuite [here](https://help.expensify.com/articles/expensify-classic/connections/netsuite/Connect-To-NetSuite#step-3-add-expensify-integration-role-to-a-user). + +**To resolve this error:** +1. If permissions are configured correctly, confirm the report submitter exists in the subsidiary set on the workspace and that their Expensify email address matches the email on the NetSuite Employee Record. +2. If the above is true, try toggling off "Automatically create vendors/employees" under the Advanced tab of the NetSuite configuration window. + - Head to **Settings > Workspaces > Group > Workspace Name > Connections > NetSuite > Configure** + - Click on the **Advanced** tab + - Disable **Automatically create vendors/employees** +3. Sync the NetSuite connection in Expensify +4. Export the report again. + +# Elimination Settings for X Do Not Match + +This error occurs when an Intercompany Payable account is set as the default in the Default Payable Account field in the NetSuite subsidiary preferences, and the Accounting Approval option is enabled for Expense Reports. + +**To resolve this error:** +Set the Default Payable Account for Expense Reports on each subsidiary in NetSuite to ensure the correct payable account is active. +1. Navigate to Subsidiaries: + - Go to Setup > Company > Subsidiaries. +2. Edit Subsidiary Preferences: + - Click Edit for the desired subsidiary. + - Go to the Preferences tab. +3. Set Default Payable Account: + - Choose the preferred account for Default Payable Account for Expense Reports. + +Repeat these steps for each subsidiary to ensure the settings are correct, and then sync Expensify to NetSuite to update the connection. + +# Why are reports exporting as `Accounting Approved` instead of `Paid in Full`? + +**This can occur for two reasons:** +- Missing Locations, Classes, or Departments in the Bill Payment Form +- Incorrect Settings in Expensify Workspace Configuration + +## Missing Locations, Classes, or Departments in Bill Payment Form + +If locations, classes, or departments are required in your accounting classifications but are not marked as 'Show' on the preferred bill payment form, this error can occur, and you will need to update the bill payment form in NetSuite: +1. Go to Customization > Forms > Transaction Forms. +2. Find your preferred (checkmarked) Bill Payment form. +3. Click Edit or Customize. +4. Under the Screen Fields > Main tab, check 'Show' near the department, class, and location options. + +## Incorrect Settings in Expensify Workspace Configuration + +To fix this, you'll want to confirm the NetSuite connection settings are set up correctly in Expensify: +1. Head to **Settings > Workspaces > Group > Workspace Name > Connections > NetSuite > Configure > Advanced** +2. **Ensure the following settings are correct:** + - Sync Reimbursed Reports: Enabled and payment account chosen. + - Journal Entry Approval Level: Approved for Posting. + - A/P Approval Account: This must match the current account being used for bill payment. +3. **Verify A/P Approval Account:** + - To ensure the A/P Approval Account matches the account in NetSuite: + - Go to your bill/expense report causing the error. + - Click Make Payment. + - This account needs to match the account selected in your Expensify configuration. +4. **Check Expense Report List:** + - Make sure this is also the account selected on the expense report by looking at the expense report list. + +Following these steps will help ensure that reports are exported as "Paid in Full" instead of "Accounting Approved." + + +# Why are reports exporting as `Pending Approval`? + +If reports are exporting as "Pending Approval" instead of "Approved," you'll need to adjust the approval preferences in NetSuite. + +**Exporting as Journal Entries/Vendor Bills:** +1. In NetSuite, go to Setup > Accounting > Accounting Preferences. +2. On the **General** tab, uncheck **Require Approvals on Journal Entries**. +3. On the **Approval Routing** tab, uncheck Journal Entries/Vendor Bills to remove the approval requirement for Journal Entries created in NetSuite. + +**Note:** This change affects all Journal Entries, not just those created by Expensify. + +**Exporting as Expense Reports:** +1. In NetSuite, navigate to Setup > Company > Enable Features. +2. On the "Employee" tab, uncheck "Approval Routing" to remove the approval requirement for Expense Reports created in NetSuite. Please note that this setting also applies to purchase orders. + + +# How do I Change the Default Payable Account for Reimbursable Expenses in NetSuite? + +NetSuite is set up with a default payable account that is credited each time reimbursable expenses are exported as Expense Reports to NetSuite (once approved by the supervisor and accounting). If you need to change this to credit a different account, follow the below steps: + +**For OneWorld Accounts:** +1. Navigate to Setup > Company > Subsidiaries in NetSuite. +2. Next to the subsidiary you want to update, click Edit. +3. Click the Preferences tab. +4. In the Default Payable Account for Expense Reports field, select the desired payable account. +5. Click Save. + +**For Non-OneWorld Accounts:** +1. Navigate to Setup > Accounting > Accounting Preferences in NetSuite. +2. Click the Time & Expenses tab. +3. Under the Expenses section, locate the Default Payable Account for Expense Reports field and choose the preferred account. +4. Click Save. + + +# Why are my Company Card Expenses Exporting to the Wrong Account in NetSuite? + +If your company card transactions are exporting to the wrong account in your accounting system, there are a couple of factors to check: +1. **Verify Card Mapping:** + - Ensure that the cards are mapped to the correct accounts at the domain level + - This can be viewed under **Settings > Domains > Domain Name > Company Cards**. +2. **Check Default Account Settings:** + - Review the account where the expenses were exported + - It should be the default account under **Settings > Workspaces > Group > Workspace Name > Connections**. + - Click **Configure** to check the default export settings for your non-reimbursable expenses. + +The most common reason expenses export to the default account is that they are not actually imported from the mapped company card. Only company card expenses (notated with the ā€œCard+Lockā€ icon) can use the export mapping settings configured at the domain level. + +Even if an expense was paid with the company card, it is considered a 'cash' expense unless it merges with a card expense marked with the Card+Lock icon. + +Less commonly, the issue may occur if the company card has been added to the user's personal settings. Expenses imported from a card linked at the individual account level will have a plain card icon. + diff --git a/docs/articles/expensify-classic/connections/quickbooks-desktop/Configure-Quickbooks-Desktop.md b/docs/articles/expensify-classic/connections/quickbooks-desktop/Configure-Quickbooks-Desktop.md new file mode 100644 index 000000000000..18b8a9ec31f9 --- /dev/null +++ b/docs/articles/expensify-classic/connections/quickbooks-desktop/Configure-Quickbooks-Desktop.md @@ -0,0 +1,88 @@ +--- +title: Configure Quickbooks Desktop +description: Configure Quickbooks Desktop +--- +# How to configure export settings for QuickBooks Desktop +To Configure Settings, go to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Connections** and click **Configure**. Click on the Export tab. + +## Preferred Exporter +This person is used in QuickBooks Desktop as the export user. They will also receive notifications for errors. + +## Date +Choose either the report's submitted date, the report's exported date, or the date of the last expense on the report when exporting reports to QuickBooks Desktop. + +## Use unique reference numbers +Enable this to allow use of a unique reference number for each transaction. Disable this to use the same Report ID for all expenses from a certain report. + +## Reimbursable expenses +* **Vendor Bill (recommended):** A single itemized vendor bill for each Expensify report. An A/P account is required to export to a vendor bill. +* **Check:** A single itemized check for each Expensify report. +* **Journal Entry:** A single itemized journal entry for each Expensify report. + * When exporting as journal entries to an Accounts Payable, this requires a vendor record, not an employee. The vendor record must have the email address of the report creator/submitter. + * If the report creator/submitter also has an employee record, you need to remove the email, because Expensify will try to export to the employee record first for journal entries. + +**Note on negative expenses:** In general, you can export negative expenses successfully to QuickBooks Desktop regardless of which export option you choose. The one thing to keep in mind is that if you have Check selected as your export option, the total of the report can not be negative. + +**Note on exporting to Employee Records:** If you want to export reports to your users' Employee Records instead of their Vendor Records, you will need to select Check or Journal Entry for your reimbursable export option. There isn't a way to export as a Vendor Bill to an Employee Record. If you are setting up Expensify users as employees, you will need to activate QuickBooks Desktop Payroll to view the Employee Profile tab where submitter's email addresses need to be entered. + + +## Non-reimbursable expenses +**Credit Card Expenses:** +* Each expense will appear as a separate credit card transaction. +* The posting date will match your credit card statement. +* To display the merchant name in the payee field in QuickBooks Desktop, ensure that a matching Vendor exists in QuickBooks. Expensify searches for an exact match during export. If no match is found, the payee is mapped to a **Credit Card Misc.** Vendor created by Expensify. +* If you're centrally managing company cards through Domain Control, you can export expenses from each card to a specific QuickBooks account (detailed instructions available). + +**Debit Card Expenses:** +* Expenses export as individual itemized checks for each Expensify report. +* The check is written to the "vendor," which is the person who created or submitted the report in Expensify. + +**Vendor Bill:** +* Each Expensify report results in a single itemized vendor bill. +* The bill is associated with the "vendor," which is the individual responsible for creating or submitting the report in Expensify. + +# How to configure coding for QuickBooks Desktop +To Configure Settings, go to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Connections** and click **Configure**. Click on the Coding tab. + +## Categories +Expensify's integration with QuickBooks brings in your Chart of Accounts as Categories in Expensify automatically. Here's how to manage them: +1. After connecting, go to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Categories** to view the accounts imported from QuickBooks Desktop. +2. You can use the enable/disable button to choose which Categories your employees can access. Additionally, you can set specific rules for each Category via the blue settings cog. +3. Expensify offers Auto-Categorization to automatically assign expenses to the appropriate expense categories. +4. If needed, you can edit the names of the imported Categories to simplify expense coding for your employees. Keep in mind that if you make changes to these accounts in QuickBooks Desktop, the category names in Expensify will update to match them during the next sync. +5. _**Important:**_ Each expense must have a category selected to export to QuickBooks Desktop. The selected category must be one imported from QuickBooks Desktop; you cannot manually create categories within Expensify policy settings. + +## Classes +Classes can be imported from QuickBooks as either tags (line-item level) or report fields (header level). + +## Customers/Projects +You can bring in Customers/Projects from QuickBooks into Expensify in two ways: as tags (at the line-item level) or as report fields (at the header level). If you're utilizing Billable Expenses in Expensify, here's what you need to know: +* Customers/Projects must be enabled if you're using Billable Expenses. +* Expenses marked as "Billable" need to be tagged with a Customer/Project to successfully export them to QuickBooks. + +## Items +Items can be imported from QuickBooks as categories alongside your expense accounts. + +{% include faq-begin.md %} +## How do I sync my connection? +1. Ensure that both the Expensify Sync Manager and QuickBooks Desktop are running. +2. On the Expensify website, navigate to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Connections** > **QuickBooks Desktop**, and click **Sync now**. +3. Wait for the syncing process to finish. Typically, this takes about 2-5 minutes, but it might take longer, depending on when you last synced and the size of your QuickBooks company file. The page will refresh automatically once syncing is complete. + +We recommend syncing at least once a week or whenever you make changes in QuickBooks Desktop that could impact how your reports export from Expensify. Changes could include adjustments to your Chart of Accounts, Vendors, Employees, Customers/Jobs, or Items. Remember, both the Sync Manager and QuickBooks Desktop need to be running for syncing or exporting to work. + +## How do I export reports? +The Sync Manager and QuickBooks Desktop both need to be running in order to sync or export. +* **Exporting an Individual Report:** You can export reports to QuickBooks Desktop one at a time from within an individual report on the Expensify website by clicking the "Export to" button. +* **Exporting Reports in Bulk:** To export multiple reports at a time, select the reports that you'd like to export from the Reports page on the website and click the "Export to" button near the top of the page. + +Once reports have been exported to QuickBooks Desktop successfully, you will see a green QuickBooks icon next to each report on the Reports page. You can check to see when a report was exported in the Comments section of the individual report. + +## Can I export negative expenses? +Generally, you can export negative expenses to QuickBooks Desktop successfully, regardless of your option. However, please keep in mind that if you have *Check* selected as your export option, the report's total cannot be negative. + +## How does multi-currency work with QuickBooks Desktop? +When using QuickBooks Desktop Multi-Currency, there are some limitations to consider based on your export options: +1. **Vendor Bills and Checks:** The currency of the vendor and the currency of the account must match, but they do not have to be in the home currency. +2. **Credit Card:** If an expense doesn't match an existing vendor in QuickBooks, it exports to the **Credit Card Misc.** vendor created by Expensify. When exporting a report in a currency other than your home currency, the transaction will be created under the vendor's currency with a 1:1 conversion. For example, a transaction in Expensify for $50 CAD will appear in QuickBooks as $50 USD. +3. **Journal Entries:** Multi-currency exports will fail because the account currency must match both the vendor currency and the home currency. diff --git a/docs/articles/expensify-classic/connections/quickbooks-desktop/Connect-To-QuickBooks-Desktop.md b/docs/articles/expensify-classic/connections/quickbooks-desktop/Connect-To-QuickBooks-Desktop.md new file mode 100644 index 000000000000..92e1e4dd841f --- /dev/null +++ b/docs/articles/expensify-classic/connections/quickbooks-desktop/Connect-To-QuickBooks-Desktop.md @@ -0,0 +1,62 @@ +--- +title: QuickBooks Desktop +description: Connect Expensify to QuickBooks Desktop +order: 1 +--- +# Overview +To connect Expensify to QuickBooks Desktop, use Right Networks as the hosting platform if possible. Right Networks is a cloud-based service that was built specifically for this integration. If you need a Right Networks account, complete [this form](https://info.rightnetworks.com/partner-expensify) to start the process. + +**A couple of notes before connecting QuickBooks Desktop to Expensify:** +- Make sure you're logged into QuickBooks Desktop as an admin +- Check that the company file you want to connect Expensify to is the only one open + + +# Connect to QuickBooks Desktop + +## Step 1: Set up submitters in QuickBooks Desktop +- Make sure all report submitters are set up as Vendors in QuickBooks Desktop and their Expensify email is in the "Main Email" field of their Vendor record. You can do this in the vendor section of QuickBooks. +- If you want to export reports to your users' employee records instead of vendor records, select Check or Journal Entry as your reimbursable export option. +- To set up Expensify users as employees, activate QuickBooks Desktop Payroll. This module is necessary to access the Employee Profile tab, where you can enter the submitter's email addresses. + +## Step 2: Enable/install the Expensify Sync Manager +1. Navigate to **Settings > Workspaces > Group > [Workspace Name] > Connections** +2. Click **Connect to QuickBooks Desktop** to initiate the connection + +**Option 1: Enable the Expensify Sync Manager in Right Networks (recommended)** +- For this option, **single-user mode** in QuickBooks Desktop is required. +- If you don't have an account with Right Networks, you can contact Right Networks [here](https://info.rightnetworks.com/partner-expensify) +- Once set up, you can enable the Expensify Sync Manager from the **My Account** section in Right Networks' portal + +**Option 2: Install the Expensify Sync Manager on Your Third-Party Remote Desktop.** +To download the Sync Manager to your desktop, you must contact your third-party remote desktop provider and request permission. They might have security restrictions, so it's best to communicate with them directly to avoid potential problems with the Sync Manager. Remember that the Sync Manager program file should be stored in the same location (i.e., the same drive) as your QuickBooks Desktop program. + +## Step 3: Complete the connection +1. Open QuickBooks and access the desired Company File using the QuickBooks Admin credentials (admin credentials are necessary for creating the connection) +2. Navigate to **Settings > Workspaces > Group > [Workspace Name] > Connections** +3. Copy the Token by selecting the copy icon +4. While QuickBooks is still running, launch the Expensify Sync Manager by pasting the Token into the Sync Manager +5. Click **Save** +6. Once the Sync Manager status displays **Connected**, return to Expensify and click **Continue** + +## Step 4: Allow access +1. Return to QuickBooks where you'll see an **Application Certificate** screen + - On the first page of the Certificate screen, click **Yes, always; allow access even if QuickBooks is not running** +3. Click **Continue** +4. On the second page of the Certificate screen, choose the Admin user from the dropdown menu +5. Click **Done** +7. Return to Expensify and wait for the sync to complete + +{% include faq-begin.md %} + +## After connecting, how do I sync QuickBooks and Expensify? +1. Confirm that both the Expensify Sync Manager and QuickBooks Desktop are running +2. On the Expensify website, navigate to **Settings > Workspaces > Group > [Workspace Name] > Connections**, and click **Sync now** +3. Wait for the sync to complete + +Typically, this takes about 2-5 minutes, but it might take longer, depending on when you last synced and the size of your QuickBooks company file. The page will refresh automatically once syncing is complete. + +We recommend syncing at least once a week or whenever you make changes in QuickBooks Desktop that could impact how your reports export from Expensify. Changes could include adjustments to your Chart of Accounts, Vendors, Employees, Customers/Jobs, or Items. + +Remember, both the Sync Manager and QuickBooks Desktop need to be running for syncing or exporting to work. + +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/connections/quickbooks-desktop/Quickbooks-Desktop-Troubleshooting.md b/docs/articles/expensify-classic/connections/quickbooks-desktop/Quickbooks-Desktop-Troubleshooting.md new file mode 100644 index 000000000000..061b01b7a924 --- /dev/null +++ b/docs/articles/expensify-classic/connections/quickbooks-desktop/Quickbooks-Desktop-Troubleshooting.md @@ -0,0 +1,45 @@ +--- +title: Quickbooks Desktop Troubleshooting +description: Quickbooks Desktop Troubleshooting +--- + +# Sync and export errors +## Error: No Vendor Found For Email in QuickBooks +To address this issue, ensure that each submitter's email is saved as the **Main Email** in their Vendor record within QuickBooks Desktop. Here's how to resolve it: +1. Go to your Vendor section in QuickBooks. +2. Verify that the email mentioned in the error matches the **Main Email** field in the respective vendor's record. It's important to note that this comparison is case-sensitive, so ensure that capitalization matches as well. +3. If you prefer to export reports to your users' employee records instead of their vendor records, select either **Check** or **Journal Entry** as your reimbursable export option. If you are setting up Expensify users as employees, activate QuickBooks Desktop Payroll to access the Employee Profile tab where submitter email addresses need to be entered. +4. Once you've added the correct email to the vendor record, save this change, and then sync your policy before attempting to export the report again. + +## Error: Do Not Have Permission to Access Company Data File +To resolve this error, follow these steps: +1. Log into QuickBooks Desktop as an Admin in single-user mode. +2. Go to **Edit** > **Preferences** > **Integrated Applications** > **Company Preferences**. +3. Select the Expensify Sync Manager and click on **Properties**. +4. Ensure that **Allow this application to login automatically** is checked, and then click **OK**. Close all windows within QuickBooks. +5. If you still encounter the error after following the above steps, go to **Edit** > **Preferences** > **Integrated Applications** > **Company Preferences**, and remove the Expensify Sync Manager from the list. +6. Next, attempt to sync your policy again in Expensify. You'll be prompted to re-authorize the connection in QuickBooks. +7. Click **Yes, always; allow access even if QuickBooks is not running.** +8. From the dropdown, select the Admin user, and then click **Continue**. Note that selecting **Admin** here doesn't mean you always have to be logged in as an admin to use the connection; it's just required for setting up the connection. +9. Click **Done** on the pop-up window and return to Expensify, where your policy should complete the syncing process. + +## Error: The Wrong QuickBooks Company is Open. +This error suggests that the wrong company file is open in QuickBooks Desktop. To resolve this issue, follow these steps: +1. First, go through the general troubleshooting steps as outlined. +2. If you can confirm that the incorrect company file is open in QuickBooks, go to QuickBooks and select **File** > **Open or Restore Company** > _[Company Name]_ to open the correct company file. After doing this, try syncing your policy again. +3. If the correct company file is open, but you're still encountering the error, completely close QuickBooks Desktop, reopen the desired company file and then attempt to sync again. +4. If the error persists, log into QuickBooks as an admin in single-user mode. Then, go to **Edit** > **Preferences** > **Integrated Applications** > **Company Preferences** and remove the Expensify Sync Manager from the list. +5. Next, try syncing your policy again in Expensify. You'll be prompted to re-authorize the connection in QuickBooks, allowing you to sync successfully. +6. If the error continues even after trying the steps above, double-check that the token you see in the Sync Manager matches the token in your connection settings. + +## Error: The Expensify Sync Manager Could Not Be Reached. +To resolve this error, follow these steps: +*Note: You must be in single-user mode to sync.* + +1. Ensure that both the Sync Manager and QuickBooks Desktop are running. +2. Confirm that the Sync Manager is installed in the correct location. It should be in the same location as your QuickBooks application. If QuickBooks is on your local desktop, the Sync Manager should be there, too. If QuickBooks is on a remote server, install the Sync Manager there. +Verify that the Sync Manager's status is **Connected**. +3. If the Sync Manager status is already **Connected**, click **Edit** and then *Save* to refresh the connection. Afterwards, try syncing your policy again. +4. If the error persists, double-check that the token you see in the Sync Manager matches the token in your connection settings. + +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/connections/quickbooks-online/Configure-Quickbooks-Online.md b/docs/articles/expensify-classic/connections/quickbooks-online/Configure-Quickbooks-Online.md new file mode 100644 index 000000000000..3fd1df0c0a1c --- /dev/null +++ b/docs/articles/expensify-classic/connections/quickbooks-online/Configure-Quickbooks-Online.md @@ -0,0 +1,140 @@ +--- +title: Configure Quickbooks Online +description: Configure Quickbooks Online +--- + +# Best Practices Using QuickBooks Online + +A connection to QuickBooks Online lets you combine the power of Expensify's expense management features with QuickBooksā€™s accounting capabilities. By following the recommended best practices below, your finances will be automatically categorized correctly and accounted for in the right place. + +- Configure your setup immediately after making the connection, and review each settings tab thoroughly. +- Keep Auto Sync enabled. + - The daily sync will update Expensify with any changes to your chart of accounts, customers/projects, or bank accounts in QuickBooks Online. + - Finalized reports will be exported to QuickBooks Online automatically, saving your admin team time with every report. +- Set your preferred exporter to a user who is both a workspace and domain admin. +- Configure your coding settings and enforce them by requiring categories and tags on expenses. + +# Accessing the QuickBooks Configuration Settings + +QuickBooks Online is connected at the workspace level, and each workspace can have a unique configuration that dictates how the connection functions. To access the configuration: + +1. Click **Settings** near the bottom of the left-hand menu. +2. Navigate to Workspaces > Groups > [workspace Name] > Connections. +3. Scroll down to the QuickBooks Online connection and click the **Configure** button to open the settings menu. + +# Step 1: Configure Export Settings + +The following steps help you determine how data will be exported from Expensify to QuickBooks Online. + +1. Click the **Configure** button under the QuickBooks Online connection to open the settings menu. +2. Under the Export tab, review each of the following export settings: + - _Preferred Exporter_: Choose a Workspace Admin to set as the Preferred Exporter. + - Concierge exports reports automatically on behalf of the preferred exporter. + - Other Workspace Admins will still be able to export to QuickBooks Online manually. + - If you set different export bank accounts for individual company cards under Settings > Domain > Company Cards, your Preferred Exporter must be a Domain Admin in addition to a Workspace Admin. + - _Date_: When exporting reports to QuickBooks Online, you can choose the reportā€™s submitted date, the reportā€™s exported date, or the date of the last expense on the report. + - If you choose a Credit Card or Debit Card for non-reimbursable expenses, weā€™ll use the transaction date on each expense during export. + - _Reimbursable expenses_: Reimbursable expenses export to QuickBooks Online as: + - Vendor Bills (recommended): This is a single itemized vendor bill for each Expensify report. + - Checks - This is a single itemized check for each Expensify report. You can mark a check to be printed later in QuickBooks Online. + - Journal Entries - This is a single itemized journal entry for each Expensify report. + - _Non-reimbursable expenses_: Non-reimbursable expenses export to QuickBooks Online as: + - Credit Card expenses - Each expense will be exported as a bank transaction with its transaction date. + - Debit Card Expenses - Each expense will be exported as a bank transaction with its transaction date. + - Vendor Bills - A single detailed vendor bill is generated for each Expensify report. + - If the accounting period is closed, the vendor bill will be posted on the first day of the next open period. If you choose to export non-reimbursable expenses as Vendor Bills, you can assign a default vendor to the bill. + - The export will use your default vendor if you have Default Vendor enabled. If the Default Vendor is disabled, the reportā€™s submitter will be set as the Vendor in QuickBooks. + - _Billable Expenses_: In Expensify, you can designate expenses as billable. These will be exported to QuickBooks Online with the billable flag. + - This feature applies only to expenses exported as Vendor Bills or Checks. To maximize this functionality, ensure that any billable expense is associated with a Customer/Job. + - _Export Invoices_: If you are creating Invoices in Expensify and exporting these to QuickBooks Online, this is the account the invoice will appear against. + +## Step 1B: Optional Configuration When Company Cards Are Connected +1. Click **Settings** near the bottom of the left-hand menu. +2. Navigate to Domains > [domain name] > Company Cards. +3. If you have more than one company card connection, select the connection first. +4. Locate the cardholder you want to configure in the list, +5. Click the **Edit Exports** button and assign the account the card expenses should export to in QuickBooks Online. + +# Step 2: Configure Coding Settings + +The following steps help you determine how data will be imported from QuickBooks Online to Expensify. + +1. Click the **Configure** button under the QuickBooks Online connection to open the settings menu. +2. Under the Coding tab, review each of the following settings and configure the options to determine what information will be imported: + - _Categories_: QuickBooks Online Chart of Accounts are imported into Expensify as categories. This is enabled by default and cannot be disabled. + - Equity-type accounts will also be imported as categories. + - Other Current Liabilities can only be exported as Journal Entries if the submitter is set up as an Employee in QuickBooks. + - _Classes and Customers/Projects_: If you use Classes or Customers/Projects in QuickBooks Online, you can import those into Expensify as Tags or Report Fields: + - Tags let you apply a Class and/or Customer/Project to each expense. + - Report Fields enables you to apply a Class and/or Customer/Project to all expenses on a report. + - Note: Although Projects can be imported into Expensify and coded to expenses, due to the limitations of the QuickBooks API, expenses cannot be created within the Projects module in QuickBooks. + - _Locations_: When enabled will import into Expensify as a Report Field or, if you export reimbursable expenses as Journal Entries and non-reimbursable expenses as Credit/Debit Card, you can import Locations as Tags. + - _Items_: If you use Items in QuickBooks Online, you can import Items defined with Purchasing Information (with or without Sales Information) into Expensify as Categories. + - _Tax_: Once enabled, QuickBooks Online tax rates can be further configured on the Settings > Workspaces > Groups > [Workspace Name] > [Tax](https://expensify.com/policy?param=%7B%22policyID%22:%22B936DE4542E9E78B%22%7D#tax) page. + - Note: Tax cannot be exported to Journal Entries in QuickBooks Online. + +# Step 3: Configure Advanced Settings + +The following steps help you determine the advanced settings for your connection, like auto-sync. + +1. Click the **Configure** button under the QuickBooks Online connection to open the settings menu. +2. Under the Advanced tab, review each of the following settings and configure the options you wish to use: + - _Auto Sync_: When enabled, the connection will sync daily to ensure that the data shared between the two systems is up-to-date. + - New report approvals/reimbursements will be synced during the next auto-sync period. + - Reimbursable expenses will export after reimbursement occurs or the report is marked as reimbursed outside Expensify when using Direct or Indirect reimbursement. + - Non-reimbursable expenses will export automatically after the report is final approved. + - _Newly Imported Categories Should Be_: When a new account is created in the QuickBooks Online chart of accounts, this setting controls whether the new category in Expensify is enabled or disabled by default. Disabled categories are not visible to employees when coding expenses. + - _Invite Employees_: When enabled, Auto Sync imports QuickBooks Online employee records and invites them to the workspace. + - _Automatically Create Entities_: If you export reimbursable expenses as Vendor Bills or Journal Entries, Expensify will automatically create a vendor in QuickBooks (If one does not already exist). Expensify will also automatically create a customer when exporting Invoices. + - _Sync Reimbursed Reports_: Enabling will mark the Vendor Bill as paid in QuickBooks Online if you reimburse a report via ACH direct deposit in Expensify. If you reimburse outside of Expensify, then marking the Vendor Bill as paid in QuickBooks Online will automatically mark the report as reimbursed in Expensify. + - _QuickBooks Account_: Select the bank account your reimbursements are coming out of, and we'll create the payment in QuickBooks. + - _Collection Account_: When exporting invoices from Expensify to Quickbooks Online, the invoice will appear against the Collection Account once marked as Paid. + +{% include faq-begin.md %} + +## Why am I seeing duplicate credit card expenses in QuickBooks Online? + +When importing a banking feed directly into QuickBooks Online while also importing transactions from Expensify, itā€™s possible to encounter duplicate entries in QuickBooks. To prevent this, follow these steps: + +- Step 1: Complete the Approval Process in Expensify +Before exporting any expenses to QuickBooks Online, ensure they are added to a report and the report receives approval. Depending on your Workspace setup, reports may require approval from one or more individuals. The approval process concludes when the last user who views the report selects ā€œFinal Approve.ā€ +- Step 2: Exporting Reports to QuickBooks Online +To ensure expenses exported from Expensify match seamlessly in the QuickBooks Banking platform, make sure these expenses are marked as non-reimbursable within Expensify and that ā€œCredit Cardā€ is selected as the non-reimbursable export option for your expenses. +- Step 3: Importing Your Credit Card Transactions into QuickBooks Online +After completing Steps 1 and 2, you can import your credit card transactions into QuickBooks Online. These imported banking transactions will align with the ones brought in from Expensify. QuickBooks Online will guide you through the process of matching these transactions, similar to the example below: + +## What happens if the report canā€™t be exported to QuickBooks Online automatically? + +If a report encounters an issue during automatic export to QuickBooks Online, youā€™ll receive an email with details about the problem, including any specific error messages. These messages will also be recorded in the reportā€™s history section. + +The report will be placed in your Home for your attention. You can address the issues there. If you need further assistance, refer to our QuickBooks Online Export Errors page or export the report manually. + +## What happens to existing approved and reimbursed reports if I enable Auto Sync? + +- If Auto Sync was disabled when your Workspace was linked to QuickBooks Online, enabling it wonā€™t impact existing reports that havenā€™t been exported. +- If a report has been exported and reimbursed via ACH, it will be automatically marked as paid in QuickBooks Online during the next sync. +- If a report has been exported and marked as paid in QuickBooks Online, it will be automatically marked as reimbursed in Expensify during the next sync. +- Reports that have yet to be exported to QuickBooks Online wonā€™t be automatically exported. + +## Does splitting a non-reimbursable expense affect how it exports to QuickBooks Online? + +When exporting non-reimbursable expenses as Credit Card or Debit Card expenses, split expenses will be consolidated it into a single credit card transaction in QuickBooks with multiple line items posted to the corresponding General Ledger accounts. + +Pro-Tip: To ensure the payee field in QuickBooks Online reflects the merchant name for Credit Card expenses, ensure thereā€™s a matching Vendor in QuickBooks Online. Expensify checks for an exact match during export. If none are found, the payee will be mapped to a vendor we create and labeled as Credit Card Misc. or Debit Card Misc. + +## Iā€™m using multi-currency in QuickBooks Online, how do I control the currency conversion rate? + +When working with QuickBooks Online Multi-Currency, there are some things to remember when exporting Vendor Bills and Check! Make sure the vendorā€™s currency and the Accounts Payable (A/P) bank account match. + +In QuickBooks Online, the currency conversion rates are not applied when exporting. All transactions will be exported with a 1:1 conversion rate, so for example, if a vendorā€™s currency is CAD (Canadian Dollar) and the home currency is USD (US Dollar), the export will show these currencies without applying conversion rates. + +To correct this, you must manually update the conversion rate after the report has been exported to QuickBooks Online. + +**Specifically for Vendor Bills**: + +- If multi-currency is enabled and the Vendorā€™s currency is different from the Workspace currency, OR if QuickBooks Online home currency is foreign from the Workspace currency, then: +- We create the Vendor Bill in the Vendorā€™s currency (this is a QuickBooks Online requirement - we donā€™t have a choice) +- We set the exchange rate between the home currency and the Vendorā€™s currency +- We convert line item amounts to the vendorā€™s currency + +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/connections/quickbooks-online/Connect-To-QuickBooks-Online.md b/docs/articles/expensify-classic/connections/quickbooks-online/Connect-To-QuickBooks-Online.md new file mode 100644 index 000000000000..970f17c59018 --- /dev/null +++ b/docs/articles/expensify-classic/connections/quickbooks-online/Connect-To-QuickBooks-Online.md @@ -0,0 +1,43 @@ +--- +title: Connect to QuickBooks Online +description: Everything you need to know about using Expensify's direct integration with QuickBooks Online. +order: 1 +--- + +The Expensify integration with QuickBooks Online brings in your expense accounts and other data and even exports reports directly to QuickBooks for easy reconciliation. Plus, with advanced features in QuickBooks Online, you can fine-tune coding settings in Expensify for automated data export to optimize your accounting workflow. + +## Before connecting + +Itā€™s crucial to understand the requirements based on your specific QuickBooks subscription: +- While all the features are available in Expensify, their accessibility may vary depending on your QuickBooks Online subscription. +- An error will occur if you try to export to QuickBooks Online with a feature enabled that isnā€™t part of your subscription. +- Please be aware that Expensify does not support the Self-Employed subscription in QuickBooks Online. + +![QuickBooks Online - Subscription types]({{site.url}}/assets/images/QBO1.png){:width="100%"} + +# Step 1: Setup Employees in QuickBooks Online +Employees must be set up as either Vendors or Employees in QuickBooks Online. Make sure to include the submitterā€™s email in their record. + +If you use vendor records, you can export as Vendor Bills, Checks, or Journal Entries. If you use employee records, you can export as Checks or Journal Entries (if exporting against a liability account). + +# Step 2: Connect Expensify and QuickBooks Online +1. Click **Settings** near the bottom of the left-hand menu. +2. Navigate to Workspaces > Groups > [workspace Name] > Connections. +3. Click on **Connect to QuickBooks Online**. +4. Click the **Create a New QuickBooks Online Connection** button. +5. Enter your QuickBooks Online Administratorā€™s login information and choose the QuickBooks Online Company File you want to connect to Expensify (you can connect one Company File per Workspace). +6. Then click **Authorize**. +7. You will be redirected back to Expensify and the connection will import some initial settings from QuickBooks Online to Expensify. +8. Once the sync is complete, the configuration window for QuickBooks Online will open automatically so you can configure your export, import, and advanced settings. +9. Click the **Save** button when youā€™re done configuring to finalize the connection. + +## Step 2B: Exporting Historical Reports to QuickBooks Online + +After connecting QuickBooks Online to Expensify, you may receive a prompt to export all historical reports from Expensify. To export multiple reports at once, follow these steps: + +1. Open the Reports page in a web browser. +2. Reset the filters and then adjust the filters to display the reports in question. +3. Check the box to the left of the reports you want to export. +4. Click **Export To** and select **QuickBooks Online**. + - If you donā€™t want to export specific reports, select ā€œMark as manually enteredā€ instead. + diff --git a/docs/articles/expensify-classic/connections/quickbooks-online/Quickbooks-Online-Troubleshooting.md b/docs/articles/expensify-classic/connections/quickbooks-online/Quickbooks-Online-Troubleshooting.md new file mode 100644 index 000000000000..158a55b93e0f --- /dev/null +++ b/docs/articles/expensify-classic/connections/quickbooks-online/Quickbooks-Online-Troubleshooting.md @@ -0,0 +1,189 @@ +--- +title: Quickbooks Online Troubleshooting +description: Quickbooks Online Troubleshooting +--- + +# ExpensiError QBO022: When exporting billable expenses, please make sure the account in QuickBooks Online has been marked as billable. + +**Why does this happen?** + +This error occurs when the account applied as a category to the expense in Expensify is not marked as as a billable type account. + +## How to fix it + +1. Log in to QuickBooks Online. +2. Click the Gear in the upper right-hand corner. +3. Under Company Settings click Expenses. +4. Enable the option ā€œMake expenses and items billableā€ +5. Click on the pencil icon on the right to check if you have "In multiple accounts" selected: +6. If "In multiple accounts" is selected, go to Chart of Accounts and click Edit for the account in question. +7. Check the billable option and select an income account within your chart of accounts +8. Sync your QuickBooks Online connection in Settings > Workspaces > [click workspace] > Connections. +9. Open the report and click the Export to button and then the QuickBooks Online option. + +# ExpensiError QBO046: Feature Not Included in Subscription + +**Why does this happen?** + +This error occurs when your version of QuickBooks Online doesnā€™t support the feature you are using in Expensify. + +## How to fix it + +Though you will see all of these features available in Expensify, you will receive an error trying to export to QuickBooks if you have a feature enabled that isn't available with your QuickBooks Online subscription. + +**Here is a list of the features supported by each version:** +_Please note: Self Employed is not supported:_ + +![QuickBooks Online - Subscription types]({{site.url}}/assets/images/QBO1.png){:width="100%"} + +# ExpensiError QBO056: Expenses are not categorized with a QuickBooks Online account + +**Why does this happen?** + +QuickBooks Online requires all expenses exported from Expensify to use a category matching an account in your chart of accounts. If a category from another source is used, QuickBooks Online will reject the expense. This errors occurs when an expense on the report has a category applied that is not valid in QuickBooks Online. + +## How to fix it + +1. Sync your QuickBooks Online connection in Expensify from Settings > Workspaces > [click workspace] > Connections, and click the **Sync Now** button. +2. Review the expenses on the report. If any appear with a red _Category no longer valid_ violation, recategorize the expense until all expenses are violation-free. +3. Click the **Export t**o button and then the **QuickBooks Online** option. + - If you receive the same error, continue. +4. Note the categories used on the expenses and check the Settings > Workspaces > [workspace name] > Categories page to confirm the exact categories used on the report are enabled and connected to QuickBooks Online (you'll see a green QB icon next to all connected categories). +5. Confirm the categories used on the expenses in the report match exactly the accounts in your QuickBooks Online chart of accounts. +6. If you make any changes in QuickBooks Online or in Expensify, always sync the connection and then try to export again. + +# ExpensiError QBO088: Error Creating Vendor + +**Why does this happen?** + +This error occurs when you have an Employee Record set up with the employee's name, which prevents the Expensify integration from automatically creating the Vendor Record with the same name, since QuickBooks Online won't allow you to have an employee and vendor with the same name. + +## How to fix it + +There are two different ways you can resolve this error. + +**Option 1**: + +1. Log into QuickBooks Online. +2. Access the Employee Records for your submitters. +3. Edit the name to differentiate them from the name they have on their account in Expensify. +4. Sync your QuickBooks Online connection in Settings > Workspaces > [click workspace] > Connections. +5. Open the report and click the Export to button and then the QuickBooks Online option. + +**Option 2**: +1. Log into QuickBooks Online. +2. Manually create all of your Vendor Records, making sure that the email matches the email address associated with the user in Expensify. + - In this case, we recommend disabling _Automatically Create Entities_ under Settings > Workspaces > [workspace name] > Connections > Configure > Advanced, so that you will receive the correct error messages when a vendor record doesn't exist. + +# ExpensiError QBO097: When You Use Accounts Payable, You Must Choose a Vendor in the Name Field + +**Why does this happen?** + +This error occurs when you are exporting reimbursable expenses as Journal Entries against an A/P account and also use Employee Records in QuickBooks Online. + +## How to fix it + +There are three different ways you can resolve this error. +- Select a different type of export for reimbursable expenses under Settings > Workspaces > [worksapce name] > Connections > Configure > Export tab. +- Enable _Automatically Create Entities_ under Settings > Workspaces > [worksapce name] > Connections > Configure > Advanced to create vendor records automatically. +- Manually create vendor records in QuickBooks Online for each employee. + +# ExpensiError QBO099: Items marked as billable must have sales information checked + +**Why does this happen?** + +This error occurs when an Item category on an expense does not have sales information in QuickBooks Online. + +## How to fix it + +1. Log into QuickBooks Online. +2. Navigate to to your items list. +3. Click **Edit** to the right of the item used on the report with the error. Here you will see an option to check either "Sales" or "Purchasing". +4. Check the option for **Sales**. +5. Select an income account. +6. Save your changes. +7. Sync your QuickBooks Online connection in Settings > Workspaces > [workspace name] > Connections. +8. Open the report and click the **Export to** button and then the **QuickBooks Online** option. + + +# ExpensiError QBO193: Couldn't Connect to QuickBooks Online + +**Why does this happen?** + +This error occurs when the QuickBooks Online credentials used to make the connection have changed. + +_Note: This error message can also show up as, "QuickBooks Reconnect error: OAuth Token rejected.ā€_ + +## How to fix it + +1. Navigate to Settings > Workspaces > Groups > [workspace name] > Connections. +2. Click the **Sync Now** button. +3. In the pop-up window, click **Reconnect** and enter your current QuickBooks Online credentials. + +Note: If you are connecting with new credentials, you will need to reconfigure your settings and re-select the categories and tags you want enabled. We recommend taking a screenshot of your configuration settings beforehand so that you can reset the connection with those settings. + +# ExpensiError QBO077: Duplicate Document Number, This bill number has already been used. + +**Why does this happen?** + +This error occurs when settings in QuickBooks Online are enabled to warn of duplicate document numbers. + +## How to fix it + +1. Log into QuickBooks Online. +2. Navigate to Settings > Advanced. +3. Under the Other Preferences section, make sure "Warn if duplicate bill number is used" is set to "Off" +4. Sync your QuickBooks Online connection in Settings > Workspaces > [workspace name] > Connections. +5. Open the report and click the **Export to** button and then the **QuickBooks Online** option. + +# Export error: QuickBooks Online: The transaction needs to be in the same currency as the A/R and A/P accounts + +**Why does this happen?** + +This error occurs because the currency on the Vendor record in QuickBooks Online doesn't match the currency on the A/P account. + +## How to fix it + +1. Log into QuickBooks Online. +2. Open the vendor record. +3. Update the record to use with the correct A/P account, currency and an email matching their Expensify email. +You can find the correct Vendor record by exporting your QuickBooks Online [vendor list](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fqbo.intuit.com%2Fapp%2Fvendors) to a spreadsheet (click the export icon on the right-hand side of the page), and search for the email address of the person who submitted the report. + +If you have multiple Vendors with different currencies with the same email, Expensify is likely trying to export to the wrong one. + +1. Try removing the email address from the vendor in QuickBooks Online you aren't trying to export to. +2. Sync your QuickBooks Online connection in Settings > Workspaces > [workspace name] > Connections. +3. Open the report and click the **Export to** button and then the **QuickBooks Online** option. + +If this still fails, you'll need to confirm that the A/P account selected in Expensify is set to the correct currency for the export. + +1. Navigate to Settings > Workspaces > [workspace name] > Connections. +2. Under the Exports tab check that both A/P accounts are the correct currency. + +# Why are company card expenses exporting to the wrong account in QuickBooks Online? + +Multiple factors could be causing your company card transactions to export to the wrong place in your accounting system, but the best place to start is always the same. + +1. First, confirm that the company cards have been mapped to the correct accounts in Settings > Domains > Company Cards > click the **Edit Export button** for the card to view the account. +2. Next, confirm the expenses in question have been imported from the company card? + - Only expenses that have the Card+Lock icon next to them will export according to the mapping settings that you configure in the domain settings. + +Itā€™s important to note that expenses imported from a card linked at the individual account level, expenses created from a SmartScanned receipt, and manually created cash expenses will export to the default bank account selected in your connection's configuration settings. + +**Is the report exporter a domain admin?** + +The user exporting the report must be a domain admin. You can check the history and comment section at the bottom of the report to see who exported the report. + +If your reports are being exported automatically by Concierge, the user listed as the Preferred Exporter under Settings > Workspaces > [workspaces name] > Connections > click **Configure** must be a domain admin as well. + +If the report exporter is not a domain admin, all company card expenses will export to the bank account set in Settings > Workspaces > [workspace name] > Connections > click **Configure** for non-reimbursable expenses. + +**Has the company card been mapped under the correct workspace?** + +If you have multiple workspaces connected to QuickBooks Online, each connected workspace will have a separate list of accounts to assign the card to. Unless you choose an account listed under the same workspace as the report you are exporting, expenses will export to the default bank account. + +# Can I export negative expenses to QuickBooks Online? + +In general, you can export negative expenses successfully to QBO regardless of which export method you choose. + +The one thing to keep in mind is that if you have Check selected as your export option, the total of the report can not be negative. diff --git a/docs/articles/expensify-classic/connections/sage-intacct/Configure-Sage-Intacct.md b/docs/articles/expensify-classic/connections/sage-intacct/Configure-Sage-Intacct.md new file mode 100644 index 000000000000..1f0be2f4571a --- /dev/null +++ b/docs/articles/expensify-classic/connections/sage-intacct/Configure-Sage-Intacct.md @@ -0,0 +1,153 @@ +--- +title: Configure Sage Intacct +description: Configure Sage Intacct's export, coding, and advanced settings. +--- + +By configuring your Sage Intacct settings in Expensify correctly, you can leverage the connection's settings to automate most tasks, making your workflow more efficient. + +# How to Configure Export Settings + +There are several options for exporting Expensify reports to Sage Intacct. Let's explore how to configure these settings to align with your business needs. + +To access these settings, go to **Settings > Workspace > Group > Connections** and select the **Configure** button. + +## Export Options + +### Preferred Exporter + +Any workspace admin can export to Sage Intacct, but only the preferred exporter will receive notifications in Expensify regarding the status of exports. + +### Date + +The three options for the date your report will export with are: +- **Date of last expense:** Uses the date on the most recent expense added to the report. +- **Exported date:** Is the date you export the report to Sage Intacct. +- **Submitted date:** Is the date the report creator originally submitted the report. + +Note: All export options except credit cards use the date in the drop-down. Credit card transactions use the transaction date. + +### Reimbursable Expenses + +Depending on your initial setup, your **reimbursable expenses** will be exported as either **Expense Reports** or **Vendor Bills** to Sage Intacct. + +### Non-Reimbursable Expenses + +**1a. Non-reimbursable expenses** will export separately from reimbursable expenses either as **Vendor Bills** or as **credit card charges** to the account you select. It is not an option to export non-reimbursable expenses as **Journal** entries. + +If you are centrally managing your company cards through your Domain Settings, you can export expenses from each individual card to a specific account in Intacct. See section 1b below on how to configure those export settings. + +Please note that credit Card Transactions cannot be exported to Sage Intacct at the top level if you have **Multi-Currency** enabled. Therefore, you will need to select an entity in the configuration of your Expensify Workspace by going to **Settings > Workspaces > Groups > [Workspace Name] > Connections > Configure**. + +**1b. Optional configuration when company cards are connected** +1. Click **Settings** near the bottom of the left-hand menu. +2. Navigate to Domains > [_domain name_] > Company Cards. +3. If you have more than one company card connection, select the connection first. +4. Locate the cardholder you want to configure in the list, +5. Click the **Edit Exports** button and assign the account the card expenses should export to in Sage Intacct. + +### Exporting Negative Expenses + +You can export negative expenses successfully to Intacct regardless of which Export Option you choose. The one thing to keep in mind is that if you have Expense Reports selected as your export option, the **total** of the report can not be negative. + +## How to Configure Coding Settings + +The appearance of your expense data in Sage Intacct depends on how you've configured it in Expensify. It's important to understand each available option to achieve the desired results. + +The appearance of your expense data in Sage Intacct depends on how you've configured it in Expensify. It's important to understand each available option to achieve the desired results. + +### Expense Types + +Categories are always enabled and are the primary means of matching expenses to the correct accounts in Sage Intact. The Categories in Expensify depend on your **Reimbursable** export options: +- If your Reimbursable export option is set to **Expense Reports** (the default), your Categories will be your **Expense Types**. +- If your Reimbursable export option is set to **Vendor Bills**, your Categories will be your **Chart of Accounts** (also known as GL Codes or Account Codes). + +You can disable unnecessary categories from your **Settings > Workspaces > Group > [Workspace Name] > Categories** page if your list is too extensive. Note that every expense must be coded with a Category, or it will not export. Also, when you first set up the integration, your existing categories will be overwritten. + +### Billable Expenses + +Enabling Billable expenses allows you to map your expense types or accounts to items in Sage Intacct. To do this, you'll need to enable the correct permissions on your Sage Intacct user or role. This may vary based on the modules you use in Sage Intacct, so you should enable read-only permissions for relevant modules such as Projects, Purchasing, Inventory Control, and Order Entry. + +Once permissions are set, you can map your categories (expense types or accounts, depending on your export settings) to specific items, which will then export to Sage Intacct. When an expense is marked as Billable in Expensify, users must select the correct billable Category (Item), or there will be an error during export. + +### Dimensions - Departments, Classes, and Locations + +If you enable these dimensions, you can choose from three data options: +- Not pulled into Expensify: Employee default (available when the reimbursable export option is set to Expense Reports) +- Pulled into Expensify and selectable on reports/expenses: Tags (useful for cross-charging between Departments or Locations) +- Report Fields (applies at the header level, useful when an employee's Location varies from one report to another) + +Please note that the term "tag" may appear instead of "Department" on your reports, so ensure that "Projects" is not disabled in your Tags configuration within your workspace settings. Make sure it's enabled within your coding settings of the Intacct configuration settings. When multiple options are available, the term will default to Tags. + +### Customers and Projects + +These settings are particularly relevant to billable expenses and can be configured as Tags or Report Fields. + +### Tax + +As of September 2023, our Sage Intacct integration supports native VAT and GST tax. To enable this feature, open the Sage Intacct configuration settings in your workspace, go to the Coding tab, and enable Tax. For existing Sage Intacct connectings, simply resync your workspace and the tax toggle will appear. For new Sage Intacct connections, the tax toggle will be available when you complete the integration steps. +Enabling this option will import your native tax rates from Sage Intacct into Expensify. From there, you can select default rates for each category. + +### User-Defined Dimensions + +You can add User-Defined Dimensions (UDD) to your workspace by locating the "Integration Name" in Sage Intacct. Please note that you must be logged in as an administrator in Sage Intacct to find the required fields. + +To find the Integration Name in Sage Intacct: +1. Go to **Platform Services > Objects > List** +2. Set "filter by application" to "user-defined dimensions." + +Now, in Expensify, navigate to **Settings > Workspaces > Group > [Workspace Name] > Connections**, and click **Configure** under Sage Intacct. On the Coding tab, enable the toggle next to User Defined Dimensions. Enter the "Integration name" and choose whether to import it into Expensify as an expense-level Tag or as a Report Field, then click **Save**. + +You'll now see the values for your custom segment available under Tags settings or Report Fields settings in Expensify. + + +## How to Configure Advanced Settings + +In multi-entity environments, you'll find a dropdown at the top of the sync options menu, where you can choose to sync with the top-level or a specific entity in your Sage Intacct instance. If you sync at the top level, we pull in employees and dimensions shared at the top level and export transactions to the top level. Otherwise, we sync information with the selected entity. + +### Auto Sync + +When a non-reimbursable report is finally approved, it will be automatically exported to Sage Intacct. Typically, non-reimbursable expenses will sync to the next open period in Sage Intacct by default. If your company uses Expensify's ACH reimbursement, reimbursable expenses will be held back and exported to Sage when the report is reimbursed. + +### Inviting Employees + +Enabling **Invite Employees** allows the integration to automatically add your employees to your workspace and create an Expensify account for them if they don't have one. +If you have your domain verified on your account, ensure that the Expensify account connected to Sage Intacct is an admin on your domain. +When you toggle on "Invite Employees" on the Advanced tab, all employees in Sage Intacct who haven't been invited to the Expensify group workspace you're connecting will receive an email invitation to join the group workspace. Approval workflow will default to Manager Approval and can be further configured on the People settings page. + +### Import Sage Intacct Approvals + +When the "Import Sage Intacct Approvals" setting is enabled, Expensify will automatically set each user's manager listed in Sage Intacct as their first approver in Expensify. If no manager exists in Sage Intacct, the approver can be set in the Expensify People table. You can also add a second level of approval to your Sage Intacct integration by setting a final approver in Expensify. +Please note that if you need to add or edit an optional final approver, you will need to select the **Manager Approval** option in the workflow. Here is how each option works: +- **Basic Approval:** All users submit to one user. +- **Manager Approval:** Each user submits to the manager (imported from Sage Intacct). Each manager forwards to one final approver (optional). +- **Configure Manually:** Import employees only, configure workflow in Expensify. + +### Sync Reimbursed Reports +When using Expensify ACH, reimbursable reports exported to Intacct are exported: +- As Vendor Bills to the default Accounts Payable account set in your Intacct Accounts Payable module configuration, OR +- As Expense Reports to the Employee Liabilities account in your Time & Expenses module configuration. +When ACH reimbursement is enabled, the "Sync Reimbursed Reports" feature will additionally export a Bill Payment to the selected Cash and Cash Equivalents account listed. If **Auto Sync** is enabled, the payment will be created when the report is reimbursed; otherwise, it will be created the next time you manually sync the workspace. +Intacct requires that the target account for the Bill Payment be a Cash and Cash Equivalents account type. If you aren't seeing the account you want in that list, please first confirm that the category on the account is Cash and Cash Equivalents. + +{% include faq-begin.md %} +## What if my report isn't automatically exported to Sage Intacct? + +There are a number of factors that can cause automatic export to fail. If this happens, the preferred exporter will receive an email and an Inbox task outlining the issue and any associated error messages. +The same information will be populated in the comments section of the report. +The fastest way to find a resolution for a specific error is to search the Community, and if you get stuck, give us a shout! +Once you've resolved any errors, you can manually export the report to Sage Intacct. + +## How can I make sure that I final approve reports before they're exported to Sage Intacct? + +Make sure your approval workflow is configured correctly so that all reports are reviewed by the appropriate people within Expensify before exporting to Sage Intacct. +Also, if you have verified your domain, consider strictly enforcing expense workspace workflows. You can set this up via Settings > Domains > [Domain Name] > Groups. + + +## If I enable Auto Sync, what happens to existing approved and reimbursed reports? + +If your workspace has been connected to Intacct with Auto Sync disabled, you can safely turn on Auto Sync without affecting existing reports which have not been exported. +If a report has been exported to Intacct and reimbursed via ACH in Expensify, we'll automatically mark it as paid in Intacct during the next sync. +If a report has been exported to Intacct and marked as paid in Intacct, we'll automatically mark it as reimbursed in Expensify during the next sync. +If a report has not been exported to Intacct, it will not be exported to Intacct automatically. + +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/Sage-Intacct.md b/docs/articles/expensify-classic/connections/sage-intacct/Connect-To-Sage-Intacct.md similarity index 65% rename from docs/articles/expensify-classic/integrations/accounting-integrations/Sage-Intacct.md rename to docs/articles/expensify-classic/connections/sage-intacct/Connect-To-Sage-Intacct.md index 560a65d0d722..e32db29ee3ab 100644 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/Sage-Intacct.md +++ b/docs/articles/expensify-classic/connections/sage-intacct/Connect-To-Sage-Intacct.md @@ -1,6 +1,7 @@ --- title: Sage Intacct description: Connect your Expensify workspace with Sage Intacct +order: 1 --- # Overview Expensifyā€™s seamless integration with Sage Intacct allows you to connect using either Role-based permissions or User-based permissions. @@ -26,7 +27,7 @@ Please follow these steps if exporting as Expense Reports with **user-based perm 3. Set up Employees in Sage Intacct **(Required if exporting as Expense Reports)**. 4. Set up Expense Types in Sage Intacct **(Required if exporting as Expense Reports)**. 5. Enable Customization Services (only applicable if you don't already use Platform Services). -6. Create a test workspace and download the [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage). +6. Create a test workspace and download the [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage). 7. Upload the Package in Sage Intacct. 8. Add web services authorization. 9. Enter credentials and connect Expensify and Sage Intacct. @@ -117,7 +118,7 @@ To enable Customization Services go to **Company > Subscriptions > Customization - If you already have Platform Services enabled, you can skip this step. -### Step 6: Create a Test Workspace in Expensify and Download the [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage) +### Step 6: Create a Test Workspace in Expensify and Download the [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage) Creating a test workspace in Expensify allows you to have a sandbox environment for testing before implementing the integration live. If you are already using Expensify, creating a test workspace ensures that your existing group workspace rules and approval workflows remain intact. Here's how to set it up: 1. Go to **expensify.com > Settings > Workspaces > New Workspace**. 2. Name the workspace something like "Sage Intacct Test Workspace." @@ -159,7 +160,7 @@ Next, youā€™ll configure the Export, Coding, and Advanced tabs of the connection In this setup guide, we'll take you through the steps to establish your connection for Vendor Bills with user-based permissions. Please follow this checklist of items to complete: 1. Create a web services user and set up permissions. 2. Enable Customization Services (only required if you don't already use Platform Services). -3. Create a test workspace in Expensify and download the [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage) +3. Create a test workspace in Expensify and download the [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage) 4. Upload the Package in Sage Intacct. 5. Add web services authorization. 6. Enter credentials and connect Expensify and Sage Intacct. @@ -199,12 +200,12 @@ These are the permissions the user needs to have if exporting reimbursable expen To enable Customization Services go to **Company > Subscriptions > Customization Services**. - If you already have Platform Services enabled, you can skip this step. -### Step 3: Create a Test Workspace in Expensify and Download [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage) +### Step 3: Create a Test Workspace in Expensify and Download [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage) Creating a test workspace in Expensify allows you to establish a sandbox environment for testing before implementing the integration in a live environment. If you're already using Expensify, creating a test workspace ensures that your existing company workspace rules and approval workflows remain intact. Here's how to set it up: 1. Go to **expensify.com > Settings > Workspaces > Groups > New Workspace**. 2. Name the workspace something like "Sage Intacct Test Workspace." 3. Go to **Connections > Sage Intacct > Connect to Sage Intacct**. -4. Select "I've completed these" if you've downloaded the [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage) and completed the previous steps in Sage Intacct. +4. Select "I've completed these" if you've downloaded the [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage) and completed the previous steps in Sage Intacct. 5. Select **Download Package** (You only need to download the file; we'll upload it from your Downloads folder later). ### Step 4: Upload the Package in Sage Intacct @@ -246,7 +247,7 @@ For this setup guide, we're going to walk you through how to get your connection 3. Set up Employees in Sage Intacct 4. Set up Expense Types in Sage Intacct 5. Enable Customization Services (only applicable if you don't already use Platform Services) -6. Create a test workspace and download the [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage) +6. Create a test workspace and download the [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage) 7. Upload the Package in Sage Intacct 8. Add web services authorization 9. Enter credentials and connect Expensify and Sage Intacct @@ -328,7 +329,7 @@ Once you've setup your Chart of Accounts, to set Expense Types, go to **Time & E To enable, go **Company > Subscriptions > Customization Services** (if you already have Platform Services enabled, you will skip this step). -### Step 6: Create a test workspace in Expensify and download [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage) +### Step 6: Create a test workspace in Expensify and download [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage) The test workspace will be used as a sandbox environment where we can test before going live with the integration. If you're already using Expensify, creating a test workspace will ensure that your existing group workspace rules, approval workflow, etc remain intact. In order to set this up: @@ -365,7 +366,7 @@ Follow the steps below to set up Sage Intacct with role-based permissions and ex 1. Create a web services user and configure permissions. 2. Enable Customization Services (if not using Platform Services). -3. Create a test workspace in Expensify and download the [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage). +3. Create a test workspace in Expensify and download the [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage). 4. Upload the Package in Sage Intacct. 5. Add web services authorization. 6. Enter credentials and connect Expensify and Sage Intacct. @@ -407,7 +408,7 @@ These are the permissions required for a user to export reimbursable expenses as Only required if you don't already use Platform Services: - To enable, go to **Company > Subscriptions > Customization Services** -### Step 3: Create a test workspace in Expensify and download the [Expensify Package](https://community.expensify.com/home/leaving?allowTrusted=1&target=https%3A%2F%2Fwww.expensify.com%2Ftools%2Fintegrations%2FdownloadPackage) +### Step 3: Create a test workspace in Expensify and download the [Expensify Package](https://www.expensify.com/tools/integrations/downloadPackage) Create a test workspace in Expensify: - Go to **Settings > Workspaces** and click **New Workspace** on the Expensify website. @@ -437,134 +438,4 @@ Now, go back to **Settings > Workspaces > [Group Workspace Name] > Connections > Once the initial sync completes, you may receive the error "No Expense Types Found" if you're not using the Time and Expenses module. Close the error dialogue, and your configuration options will appear. Switch the reimbursable export option to **Vendor Bills** and click **Save** before completing your configuration. -Next, refer to the related articles section below to finish configuring the Export, Coding, and Advanced tabs of the connection configuration. - -# How to configure export settings - -When you connect Intacct with Expensify, you can configure how information appears once exported. To do this, Admins who are connected to Intacct can go to **Settings > Workspaces > Group > [Workspace Name] > Connections**, and then click on **Configure** under Intacct. This is where you can set things up the way you want. - - -## Preferred Exporter - -Any workspace admin can export to Sage Intacct, but only the preferred exporter will see reports that are ready for export in their Inbox. - - - -## Date - -Choose which date you would like your Expense Reports or Vendor Bills to use when exported. - -- **Date of last expense:** Uses the date on the most recent expense added to the report. -- **Exported date:** Is the date you export the report to Sage Intacct. -- **Submitted date:** Is the date the report creator originally submitted the report. - -All export options except credit cards use the date in the drop-down. Credit card transactions use the transaction date. - -## Reimbursable Expenses - -Depending on your initial setup, your **reimbursable expenses** will be exported as either **Expense Reports** or **Vendor Bills** to Sage Intacct. - -## Non-Reimbursable Expenses - -**Non-reimbursable expenses** will export separately from reimbursable expenses, either as **Vendor Bills**, or as **credit card charges** to the account you select. It is not an option to export non-reimbursable expenses as **Journal** entries. - - -If you are centrally managing your company cards through Domain Control, you can export expenses from each individual card to a specific account in Intacct. -Please note, Credit Card Transactions cannot be exported to Sage Intacct at the top-level if you have **Multi-Currency** enabled, so you will need to select an entity in the configuration of your Expensify Workspace by going to **Settings > Workspaces > Groups > [Workspace Name] > Connections > Configure**. - -## Exporting Negative Expenses - -You can export negative expenses successfully to Intacct regardless of which Export Option you choose. The one thing to keep in mind is that if you have Expense Reports selected as your export option, the **total** of the report can not be negative. - -# How to configure coding settings - -The appearance of your expense data in Sage Intacct depends on how you've configured it in Expensify. It's important to understand each available option to achieve the desired results. - -## Expense Types - -Categories are always enabled and are the primary means of matching expenses to the correct accounts in Sage Intact. The Categories in Expensify depend on your **Reimbursable** export options: -- If your Reimbursable export option is set to **Expense Reports** (the default), your Categories will be your **Expense Types**. -- If your Reimbursable export option is set to **Vendor Bills**, your Categories will be your **Chart of Accounts** (also known as GL Codes or Account Codes). - -You can disable unnecessary categories from your **Settings > Workspaces > Group > [Workspace Name] > Categories** page if your list is too extensive. Note that every expense must be coded with a Category, or it will not export. Also, when you first set up the integration, your existing categories will be overwritten. - -## Billable Expenses - -Enabling Billable expenses allows you to map your expense types or accounts to items in Sage Intacct. To do this, you'll need to enable the correct permissions on your Sage Intacct user or role. This may vary based on the modules you use in Sage Intacct, so you should enable read-only permissions for relevant modules such as Projects, Purchasing, Inventory Control, and Order Entry. - -Once permissions are set, you can map your categories (expense types or accounts, depending on your export settings) to specific items, which will then export to Sage Intacct. When an expense is marked as Billable in Expensify, users must select the correct billable Category (Item), or there will be an error during export. - -## Dimensions - Departments, Classes, and Locations - -If you enable these dimensions, you can choose from three data options: -- Not pulled into Expensify: Employee default (available when the reimbursable export option is set to Expense Reports) -- Pulled into Expensify and selectable on reports/expenses: Tags (useful for cross-charging between Departments or Locations) -- Report Fields (applies at the header level, useful when an employee's Location varies from one report to another) - -Please note that the term "tag" may appear instead of "Department" on your reports, so ensure that "Projects" is not disabled in your Tags configuration within your workspace settings. Make sure it's enabled within your coding settings of the Intacct configuration settings. When multiple options are available, the term will default to Tags. - -## Customers and Projects - -These settings are particularly relevant to billable expenses and can be configured as Tags or Report Fields. - -## Tax - -As of September 2023, our Sage Intacct integration supports native VAT and GST tax. To enable this feature, open the Sage Intacct configuration settings in your workspace, go to the Coding tab, and enable Tax. For existing Sage Intacct connectings, simply resync your workspace and the tax toggle will appear. For new Sage Intacct connections, the tax toggle will be available when you complete the integration steps. -Having this option enabled will then import your native tax rates from Sage Intacct into Expensify. From there, you can select default rates for each category. - -## User-Defined Dimensions - -You can add User-Defined Dimensions (UDD) to your workspace by locating the "Integration Name" in Sage Intacct. Please note that you must be logged in as an administrator in Sage Intacct to find the required fields. - -To find the Integration Name in Sage Intacct: -1. Go to **Platform Services > Objects > List** -2. Set "filter by application" to "user-defined dimensions." - -Now, in Expensify, navigate to **Settings > Workspaces > Group > [Workspace Name] > Connections**, and click **Configure** under Sage Intacct. On the Coding tab, enable the toggle next to User Defined Dimensions. Enter the "Integration name" and choose whether to import it into Expensify as an expense-level Tag or as a Report Field, then click **Save**. - -You'll now see the values for your custom segment available under Tags settings or Report Fields settings in Expensify. - - - -# How to configure advanced settings -In multi-entity environments, you'll find a dropdown at the top of the sync options menu, where you can choose to sync with the top-level or a specific entity in your Sage Intacct instance. If you sync at the top level, we pull in employees and dimensions shared at the top level and export transactions to the top level. Otherwise, we sync information with the selected entity. -## Auto Sync -When a non-reimbursable report is finally approved, it will be automatically exported to Sage Intacct. Typically, non-reimbursable expenses will sync to the next open period in Sage Intacct by default. If your company uses Expensify's ACH reimbursement, reimbursable expenses will be held back and exported to Sage when the report is reimbursed. -## Inviting Employees -Enabling **Invite Employees** allows the integration to automatically add your employees to your workspace and create an Expensify account for them if they don't have one. -If you have your domain verified on your account, ensure that the Expensify account connected to Sage Intacct is an admin on your domain. -When you toggle on "Invite Employees" on the Advanced tab, all employees in Sage Intacct who haven't been invited to the Expensify group workspace you're connecting will receive an email invitation to join the group workspace. Approval workflow will default to Manager Approval and can be further configured on the People settings page. -## Import Sage Intacct Approvals -When the "Import Sage Intacct Approvals" setting is enabled, Expensify will automatically set each user's manager listed in Sage Intacct as their first approver in Expensify. If no manager exists in Sage Intacct, the approver can be set in the Expensify People table. You can also add a second level of approval to your Sage Intacct integration by setting a final approver in Expensify. -Please note that if you need to add or edit an optional final approver, you will need to select the **Manager Approval** option in the workflow. Here is how each option works: -- **Basic Approval:** All users submit to one user. -- **Manager Approval:** Each user submits to the manager (imported from Sage Intacct). Each manager forwards to one final approver (optional). -- **Configure Manually:** Import employees only, configure workflow in Expensify. - - -## Sync Reimbursed Reports -When using Expensify ACH, reimbursable reports exported to Intacct are exported: -- As Vendor Bills to the default Accounts Payable account set in your Intacct Accounts Payable module configuration, OR -- As Expense Reports to the Employee Liabilities account in your Time & Expenses module configuration. -When ACH reimbursement is enabled, the "Sync Reimbursed Reports" feature will additionally export a Bill Payment to the selected Cash and Cash Equivalents account listed. If **Auto Sync** is enabled, the payment will be created when the report is reimbursed; otherwise, it will be created the next time you manually sync the workspace. -Intacct requires that the target account for the Bill Payment be a Cash and Cash Equivalents account type. If you aren't seeing the account you want in that list, please first confirm that the category on the account is Cash and Cash Equivalents. - - -{% include faq-begin.md %} -## What if my report isn't automatically exported to Sage Intacct? -There are a number of factors that can cause automatic export to fail. If this happens, the preferred exporter will receive an email and an Inbox task outlining the issue and any associated error messages. -The same information will be populated in the comments section of the report. -The fastest way to find a resolution for a specific error is to search the Community, and if you get stuck, give us a shout! -Once you've resolved any errors, you can manually export the report to Sage Intacct. -## How can I make sure that I final approve reports before they're exported to Sage Intacct? -Make sure your approval workflow is configured correctly so that all reports are reviewed by the appropriate people within Expensify before exporting to Sage Intacct. -Also, if you have verified your domain, consider strictly enforcing expense workspace workflows. You can set this up via Settings > Domains > [Domain Name] > Groups. - - -## If I enable Auto Sync, what happens to existing approved and reimbursed reports? -If your workspace has been connected to Intacct with Auto Sync disabled, you can safely turn on Auto Sync without affecting existing reports which have not been exported. -If a report has been exported to Intacct and reimbursed via ACH in Expensify, we'll automatically mark it as paid in Intacct during the next sync. -If a report has been exported to Intacct and marked as paid in Intacct, we'll automatically mark it as reimbursed in Expensify during the next sync. -If a report has not been exported to Intacct, it will not be exported to Intacct automatically. - -{% include faq-end.md %} +Next, refer to the [Configure Sage Intacct](https://help.expensify.com/articles/expensify-classic/connections/sage-intacct/Configure-Sage-Intacct) article to finish setting up the Export, Coding, and Advanced tabs of the connection configuration. diff --git a/docs/articles/expensify-classic/connections/sage-intacct/Sage-Intacct-Troubleshooting.md b/docs/articles/expensify-classic/connections/sage-intacct/Sage-Intacct-Troubleshooting.md new file mode 100644 index 000000000000..db341f87e930 --- /dev/null +++ b/docs/articles/expensify-classic/connections/sage-intacct/Sage-Intacct-Troubleshooting.md @@ -0,0 +1,6 @@ +--- +title: Sage Intacct Troubleshooting +description: Sage Intacct Troubleshooting +--- + +# Coming soon diff --git a/docs/articles/expensify-classic/connections/xero/Configure-Xero.md b/docs/articles/expensify-classic/connections/xero/Configure-Xero.md new file mode 100644 index 000000000000..170e8d0b6974 --- /dev/null +++ b/docs/articles/expensify-classic/connections/xero/Configure-Xero.md @@ -0,0 +1,104 @@ +--- +title: Configure Xero +description: Configure Xero +--- + +**Best Practices Using Xero** + +A connection to Xero lets you combine the power of Expensify's expense management features with Xero's accounting capabilities. By following the recommended best practices below, your finances will be automatically categorized correctly and accounted for in the right place. + +- Configure your setup immediately after making the connection, and review each settings tab thoroughly. +- Keep Auto Sync enabled. + - The daily auto sync will update Expensify with any changes to your chart of accounts, customers/projects, or bank accounts in Xero. + - Finalized reports will be exported to Xero automatically, saving your admin team time with every report. +- Set your preferred exporter to a user who is both a workspace and domain admin. +- Configure your coding settings and enforce them by requiring categories and tags on expenses. + +# Accessing the Xero Configuration Settings +Xero is connected at the workspace level, and each workspace can have a unique configuration that dictates how the connection functions. To access the configuration: + +1. Click **Settings** near the bottom of the left-hand menu. +2. Navigate to Workspaces > Groups > [workspace Name] > Connections. +3. Scroll down to the Xero connection and click the **Configure** button to open the settings menu. + +# Step 1: Configure Export Settings +The following steps help you determine how data will be exported from Expensify to Xero. + +1. Click the **Configure** button under the Xero connection to open the settings menu. +2. Under the Export tab, review each of the following export settings: + - **Preferred Exporter**: Choose a Workspace Admin to set as the Preferred Exporter. + - Concierge exports reports automatically on behalf of the preferred exporter. + - Other Workspace Admins will still be able to export to Xero manually. + - If you set different export bank accounts for individual company cards under your Domain > Company Cards, then your Preferred Exporter must be a Domain Admin in addition to Workspace Admin. + - **Export reimbursable expenses and bills as**: Reimbursable expenses export as a Purchase Bill. This setting cannot be amended. + - **Purchase Bill Date**: Choose whether to use the date of the last expense on the report, export date, or submitted date. + - **Export invoices as**: All invoices exported to Xero will be as sales invoices. Sales invoices always display the date on which the invoice was sent. This setting cannot be amended. + - **Export non-reimbursable expenses as**: Each exported expense posts as a bank transaction to the Xero bank account you select below, and transaction dates will match the dates on your bank statement. + - **Xero Bank Account**: Select which bank account will be used to post bank transactions when non-reimbursable expenses are exported. + +## Step 1B: Optional configuration when company cards are connected +1. Click **Settings** near the bottom of the left-hand menu. +2. Navigate to Domains > [domain name] > Company Cards. +3. If you have more than one company card connection, select the connection first. +4. Locate the cardholder you want to configure in the list, +5. Click the **Edit Exports** button and assign the account the card expenses should export to in Xero. + +# Step 2: Configure Coding settings +The following steps help you determine how data will be imported from Xero to Expensify. + +1. Click the **Configure** button under the Xero connection to open the settings menu. +2. Under the Coding tab, review each of the following settings and configure the options to determine what information will be imported: + - **Chart of Accounts**: Your Xero Chart of Accounts is imported into Expensify as expense categories. _This is enabled by default and cannot be disabled._ + - **Tax Rates**: When Enabled, your tax rates in Xero will be imported into your workspace. After being imported, you can find them on the [Tax](https://expensify.com/policy?param=%7B%22policyID%22:%22B936DE4542E9E78B%22%7D#tax) page of your workspace settings. + - **Tracking Categories**: When Enabled, you can configure how Xero Cost Centres and Xero Regions import. + - Xero contact default (applies the Xero contact default during export to Xero) + - Tag (line-item level) + - Report Field (header level) + - **Billable Expenses**: When enabled, your Xero customer contacts will be imported as tags. Xero requires all billable expenses to have a customer tag to be able to be exported to Xero. + +# Step 3: Configure advanced settings +The following steps help you determine the advanced settings for your connection, like auto-sync. + +1. Click the **Configure** button under the Xero connection to open the settings menu. +2. Under the Advanced tab, review each of the following settings and configure the options you wish to use: + - **Auto Sync**: When enabled, the connection will sync daily to ensure that the data shared between the two systems is up-to-date. + - New report approvals/reimbursements will be synced during the next auto-sync period. +Reimbursable expenses will export after reimbursement occurs or the report is marked as reimbursed outside Expensify when using Direct or Indirect reimbursement. + - Non-reimbursable expenses will export automatically after the report is final approved. + - **Newly Imported Categories Should Be**: When a new account is created in the Xero chart of accounts, this setting controls whether the new category in Expensify is enabled or disabled by default. Disabled categories are not visible to employees when coding expenses. + - **Set purchase bill status** (optional): Reimbursable expenses are exported as purchase bills with the status selected. The options available are: + - Awaiting Payment (default) + - Draft + - Awaiting Approval + - **Sync Reimbursed Reports**: When enabled, you can configure the Bill Payment and Invoice Collections accounts to be used when reimbursing reports and paying invoices. + - Anytime a report is reimbursed, or an invoice is paid through Expensify, the corresponding purchase bill or sales invoice in Xero will be marked as paid. + - Similarly, if a purchase bill or sales invoice is marked as paid in Xero, the related Expensify report or invoice will be automatically marked as reimbursed/paid. + - **Xero Bill Payment Account**: Once the expense report is paid, your reimbursements will appear under this Xero Bill Payment account. + - **Xero Invoice Collections Account**: If you are exporting invoices from Expensify, select the invoice collection account under which you want invoices to appear once they are marked as paid. + +{% include faq-begin.md %} + +## I have multiple organizations in Xero. Can I connect them all to Expensify? + +Yes, you can connect each organization you have to Expensify. Here are some essential things to keep in mind: + +- Organization Selection in the Workspace > Connections > Xero Configuration > Export settings tab: This option is available only if multiple organizations are configured in Xero. +- One Workspace, One Organization: Each Workspace can connect to just one organization at a time. Itā€™s a one-to-one connection. +- Adding New Organizations: If you create a new organization in Xero after your initial connection, youā€™ll need to disconnect and then reconnect it to Xero. Donā€™t forget to take a screenshot of your current settings by clicking Configure and checking the Export, Coding, and Advanced tabs. This way, you can easily set everything up again. + +## How can I view the purchase bills exported to Xero? + +**To view the bills in Xero:** +1. Log into Xero. +2. Navigate to Business > Purchase Overview > Awaiting Payments. + - Bills will be payable to the individual who created and submitted the report in Expensify. + +## How can I view the bank transactions in Xero? + +**To view the transactions in Xero:** +1. Log into Xero. +2. Head over to your Dashboard. +3. Select your company card. +4. Locate the specific expense youā€™re interested in. + +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/connections/xero/Connect-To-Xero.md b/docs/articles/expensify-classic/connections/xero/Connect-To-Xero.md new file mode 100644 index 000000000000..2fb71a780e41 --- /dev/null +++ b/docs/articles/expensify-classic/connections/xero/Connect-To-Xero.md @@ -0,0 +1,28 @@ +--- +title: Connect to Xero +description: Everything you need to know about Expensify's direct integration with Xero +order: 1 +--- + +**Prerequisites** + +You must be a Workspace Admin in Expensify using a Collect or Control Workspace to connect your Xero account to Expensify. + +## Step 1: Connect Expensify to Xero +1. Click **Settings** near the bottom of the left-hand menu. +2. Navigate to Workspaces > Groups > [workspace Name] > Connections. +3. Click on **Connect to Xero**. +4. Click the **Create a New Xero Connection** button. +5. Enter your Xero login credentials. +6. Review the access information and click Allow Access. +7. You will be redirected back to Expensify and the connection will import some initial settings from Xero to Expensify. +8. Once the sync is complete, the configuration window for Xero will open automatically so you can configure your export, import, and advanced settings. +9. Click the **Save** button when youā€™re done configuring to finalize the connection. + +{% include faq-begin.md %} + +## I use a Cashbook or Ledger Xero account, can I still connect in Expensify? + +Starting in September 2021, thereā€™s a chance for Cashbook and Ledger-type organizations in Xero. Apps like Expensify wonā€™t be able to create invoices and bills for these accounts using the Xero API. So, if youā€™re using a Cashbook or Ledger Xero account, please be aware that this might affect your Expensify integration. + +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/connections/xero/Xero-Troubleshooting.md b/docs/articles/expensify-classic/connections/xero/Xero-Troubleshooting.md new file mode 100644 index 000000000000..f1bb398dbecf --- /dev/null +++ b/docs/articles/expensify-classic/connections/xero/Xero-Troubleshooting.md @@ -0,0 +1,155 @@ +--- +title: Xero Troubleshooting +description: Xero Troubleshooting +--- + +# Overview of Xero Troubleshooting + +Synchronizing and exporting data between Expensify and NetSuite can streamline your financial processes, but occasionally, users may encounter errors that prevent a smooth integration. These errors often arise from discrepancies in settings, missing data, or configuration issues within NetSuite or Expensify. + +This troubleshooting guide aims to help you identify and resolve common sync and export errors, ensuring a seamless connection between your financial management systems. By following the step-by-step solutions provided for each specific error, you can quickly address issues and maintain accurate and efficient expense reporting and data management. + +# ExpensiError XRO014 Billable Expenses Require A Customer + +**Why does this happen?** + +This happens because Xero requires all billable expenses exported from Expensify to have a customer associated with it. This error occurs when one or more expenses on a report have been marked "billable," and do not have a customer associated with them. + +## How to fix it + +1. Navigate to your Settings > Workspaces > [click workspace] > Connections > Configure button > Coding tab. +2. Click the **toggle** to enable Billable Expenses. +3. Click the **Save** button to save the change and sync the connection. +4. Open the report in question and apply a _Customer_ tag to each billable expense. + - _Note: A Contact in Xero is not imported as a Customer until they have had some kind of bill raised against them. If you can't see your Customer imported as a tag, you may need to raise a dummy invoice at the Xero end and then delete/void it. Donā€™t forget to sync the connection again after taking this step._ +5. Try to export the report again by clicking the **Export to** button and select the **Xero** option. + +# ExpensiError XRO027: Expense on this report is categorized with a category no longer in Xero + +**Why does this happen?** + +When exporting expense data, Xero will not accept a category on an expense that no longer exists in the chart of accounts. This error occurs when one or more expenses on the report are categorized with a category that no longer exists in Xero. + +## How to fix it + +1. Log into Xero. +2. Navigate to Settings > Chart of Accounts. +3. Confirm that each category used on an expense in the report in Expensify is still an active account in Xero. +4. If the account doesnā€™t exist, add it again and sync the connection in Expensify. +5. If the account still exists, open the details, check ā€œShow in Expense Claims,ā€ and then sync the connection in Expensify. +6. After syncing, open the report and re-categorize any expenses showing a red workspace violation for out-of-workspace categories. +7. After recategorizing, click the **Export to** button and select the **Xero** option. + +# ExpensiError XRO031: Payment has already been allocated to reimbursable expenses + +**Why does this happen?** + +Xero does not allow for paid expenses to be modified. When you attempt to export the reimbursable expenses again, Xero considers that a modification and rejects the export. This error occurs when the report contains reimbursable expenses that have already been exported to Xero where a payment was issued on the purchase bill. + +## How to fix it + +1. Log into Xero. +2. Click on Business > Bills to Pay > and then the Paid tab. +3. Locate the report from the error and click on it to open it. +4. Click on the blue text that says Payment. +5. Click the Options dropdown and then Remove and Redo to delete the payment. + - _Note: Do not void the bill in Xero._ +6. Head back to Expensify and open the report again. +7. Click the **Export to** button and select the **Xero** option. + +The new export will override the current report in Xero and retain the same report ID. + +# ExpensiError XRO087 No Bank Account or Incorrect Bank Account + +**Why does this happen?** + +Xero requires all bank transactions created from non-reimbursable expenses in Expensify to be posted to an active bank account. This error occurs when the destination account in Xero doesnā€™t exist, isnā€™t set, or is not the right type. + +## How to fix it + +1. Navigate to Settings > Workspaces > [workspace name] > Connections > click the **Configure** button. +2. Select a Xero Bank Account from the dropdown that will apply to all non-reimbursable expenses exported to Xero. +3. Click the **Save** button to sync the connection. +4. Open the report again and click the **Export to** button and then the **Xero** option. + +# ExpensiError XRO052: Expenses Are Not Categorized With A Xero Account + +**Why does this happen?** + +Xero requires all expenses exported from Expensify to use a category matching an account in your chart of accounts. If a category from another source is used, Xero will reject the expense. This error occurs when an expense on the report has a category applied that is not valid. + +## How to fix it + +1. Sync your Xero connection in Expensify from Settings > Workspaces > [click workspace] > Connections, and click the **Sync Now** button. +2. Review the expenses on the report. If any appear with a red _Category no longer valid_ violation, recategorize the expense until all expenses are violation-free. +3. Click the **Export to** button and then the **Xero** option. +4. If you receive the same error, continue. + - _Note the categories used on the expenses and check the Settings > Workspaces > [click workspace] > Categories page to confirm the exact categories used on the report are enabled and connected to Xero (you'll see a blue icon next to all connected categories)._ +5. Confirm that the categories used for expenses in the report match exactly the accounts in your Xero chart of accounts. +6. If you make any changes in Xero or in Expensify, always sync the connection and then try to export again. + +# ExpensiError XRO068: Organization is not subscribed to currency x + +**Why does this happen?** + +Xero requires the currencies youā€™re using in Expensify to be added to your account before you can export expenses in that currency. For example, if your workspace is set to Canadian currency, all expenses submitted on that workspace will be converted to CAD. You must also have the Canadian currency added to your Xero account to export successfully. This error occurs when your Xero account does not have the currency mentioned in the error added. + +## How to fix it +_Note: Not all versions of Xero allow adding currencies. To add currencies, please upgrade your Xero account to the Established [plan](https://www.xero.com/us/pricing-plans/)._ + +1. Log into Xero. +2. Navigate to Settings > General Settings. +3. Under the heading Features, select Currencies. +4. Click **Add Currency** to add the currency listed in the error message. +5. Sync your Xero connection in Settings > Workspaces > [click workspace] > Connections. +6. Open the report and click the **Export to** button and then the **Xero** option. + +# ExpensiError XRO076: This report has already been exported once to Xero, but has been voided + +**Why does this happen?** + +Xero does not allow Expensify to modify a purchase bill created from a previous export if the bill has been voided. This error occurs when the report has already been exported to Xero, and the purchase bill has been voided. + +## How to fix it +_Note: Xero does not support ā€œunvoidingā€ a bill, it is an irreversible action._ + +1. From the Reports page in Expensify, locate the report associated with the voided bill. +2. Check the box to the left of the report and click **Copy**. +3. Open the new report and submit it through the approval workflow, then confirm it exports to Xero successfully. + +# ExpensiError XRO099: You have reached the limit of invoices you can approve with your Xero account. + +**Why does this happen?** + +The Early plan only allows you to enter 5 bills per month. This error occurs when you are on a trial account of Xero and have run out of your allowable exports. + +## How to fix it +Please upgrade your Xero account to a Growing or Established [plan](https://www.xero.com/us/pricing-plans/) so you can continue to use the integration and export reports without error. + +# Why are company card expenses exported to the wrong account? + +Multiple factors could be causing your company card transactions to export to the wrong place in your accounting system, but the best place to start is always the same. + +- First, confirm that the company cards have been mapped to the correct accounts in Settings > Domains > Company Cards > click the **Edit Export** button for the card to view the account. +- Next, confirm the expenses in question have been imported from the company card? + - Only expenses that have the Card+Lock icon next to them will export according to the mapping settings that you configure in the domain settings. + +Itā€™s important to note that expenses imported from a card linked at the individual account level, expenses created from a SmartScanned receipt, and manually created cash expenses will export to the default bank account selected in your connection's configuration settings. + +**Is the report exporter a domain admin?** + +The user exporting the report must be a domain admin. You can check the history and comment section at the bottom of the report to see who exported the report. + +If your reports are being exported automatically by Concierge, the user listed as the Preferred Exporter under Settings > Workspaces > [workspaces name] > Connections > click **Configure** must be a domain admin as well. + +If the report exporter is not a domain admin, all company card expenses will export to the bank account set in Settings > Workspaces > [workspace name] > Connections > click **Configure** for non-reimbursable expenses. + +**Has the company card been mapped under the correct workspace?** + +If you have multiple workspaces connected to Xero, each connected workspace will have a separate list of accounts to assign the card to. Unless you choose an account listed under the same workspace as the report you are exporting, expenses will export to the default bank account. + +# Why do non-reimbursable expenses say 'Credit Card Misc,' instead of the merchant? + +Where the merchant in Expensify is an exact match to a contact you have set up in Xero then exported credit card expenses will show the vendor name. If not we use the the default name Expensify Credit Card Misc. This is done to prevent multiple variations of the same contact (e.g. Starbucks and Starbucks #1234 as is often seen in credit card statements) being created in Xero. + +To change merchant names to match your vendor list in Xero, we recommend using our Expense Rules feature. More information on this can be found [here](https://community.expensify.com/discussion/5654/deep-dive-using-expense-rules-to-vendor-match-when-exporting-to-an-accounting-package/p1?new=1). diff --git a/docs/articles/expensify-classic/expenses/Merge-expenses.md b/docs/articles/expensify-classic/expenses/Merge-expenses.md index 8b1f573a64b4..e1430ee67543 100644 --- a/docs/articles/expensify-classic/expenses/Merge-expenses.md +++ b/docs/articles/expensify-classic/expenses/Merge-expenses.md @@ -38,20 +38,46 @@ If the expenses exist on two different reports, you will be asked which report y # FAQs -**Why canā€™t I merge expenses that are on my submitted report?** -You cannot merge expenses that are on reports that have already been submitted. +**Helpful terminology** -**Can I merge expenses that are under different accounts?** -No, you cannot merge expenses across two separate accounts. +- SmartScanned: Any receipt where the data is automatically entered by Expensify. Expenses are SmartScanned by default unless a user stops the SmartScan and enters the details manually. +- Credit card expense: Any transaction imported from a personal card, company card feed, or CSV. +- ā€œCashā€ expense: Any expense that wasn't imported from a personal card, company card feed, or CSV. -**Can you merge expenses with different currencies?** -Yes, you can merge expenses with different currencies. The conversion amount will be based on the daily exchange rate for the date of the transaction, as long as the converted rates are within +/- 5%. If the currencies are the same, then the amounts must be an exact match to merge. +**How can the icons and receipt images help me diagnose my issue?** + +Look carefully at your expenses. Each expense has an icon that denotes where the expense came from: +- Cash (bill & coins) icon: Added manually or by SmartScanning an expense +- Credit Card icon: Imported from a connected personal credit card +- Spreadsheet icon: Imported from a personal CSV import +- Locked Credit Card icon: Imported from a company card feed or CSV upload + +Ideally, your credit card expenses will all also have a SmartScanned receipt attached. If you are in the US and your admin has allowed eReceipts for low-value expenses, your expense may include the locked credit card icon and a QR code for the receipt image. + +![Image of different expenses]({{site.url}}/assets/images/Expenses.png){:width="100%"} + +If you see any other combination of icon and image, there is likely a duplicate expense and you will need to manually merge the expenses using the steps above. **Can Expensify automatically merge a cash expense with a credit card expense?** -Yes, Expensify merges a cash expense with a credit card expense if the receipt is SmartScanned or forwarded to receipts@expensify.com. However, these expenses will not merge if: -- The card expense added to your Expensify account is older than the receipt youā€™re trying to merge it with -- The receipt is dated older than 7 days of the card expense date -- Either expense date (the date the Expense was incurred, not the date it was added into Expensify) is older than 90 days -- The transaction was imported with the Expensify API -However, if a receipt does not automatically merge with the card entry, you can complete this process manually. +Yes, when a card expense is imported that matches the date and amount for a SmartScanned expense, Expensify automatically merges the new expense into the existing SmartScanned expense, and the expense will now show a credit card icon. The same is true if a receipt is SmartScanned and the transaction has already been importedā€”it will merge as soon as the SmartScan is complete. + +When expenses merge automatically, Expensify uses the SmartScanned merchant name over the merchant data from the bank statement. If the SmartScan is stopped, Expensify can no longer guarantee that the data entry is accurate, so the expenses will not merge. + +{% include info.html %} +Expenses created via the Expensify [Expense Importer API](https://integrations.expensify.com/Integration-Server/doc/#expense-creator) will not automatically merge with card feed transactions. +{% include end-info.html %} + +**Why didnā€™t my expenses merge automatically?** + +Here are some possible reasons for receipt merge failures: +- The cash receipt was not SmartScanned (manual override by the user) +- The card expense has a different date than the cash expense +- The expenses have different amounts (same currency) +- The expense amounts are outside the FX 5% threshold (different currencies) +- The expense date is older than 90 days (cash or card) +- Itā€™s a duplicate - the same receipt was added twice (and the other one merged) +- The cash receipt was submitted as a reimbursable expense, and reimbursed/exported before the credit card transaction was imported +- The credit card transaction and the receipt are not in the same Expensify user accounts + +Using the above instructions, you can manually merge any Unreported/Open cash receipt and card transaction in the same account. diff --git a/docs/articles/expensify-classic/expensify-card/Request-the-Card.md b/docs/articles/expensify-classic/expensify-card/Request-the-Card.md index b65c66c986ad..1f412665fc2f 100644 --- a/docs/articles/expensify-classic/expensify-card/Request-the-Card.md +++ b/docs/articles/expensify-classic/expensify-card/Request-the-Card.md @@ -5,7 +5,8 @@ description: Details on requesting the Expensify Card as an employee To start using the Expensify Card, do the following: 1. **Enable Expensify Cards:** An admin must first enable the cards. Then, an admin can assign you a card by setting a limit, which allows access to the card. 2. **Request the Card:** - - If you havenā€™t been assigned a limit, look for the task on your accountā€™s homepage that says, ā€œAsk your admin for the card!ā€ Use this task to message your admin team. + - If you havenā€™t been assigned a limit, look for the task on your accountā€™s homepage that says, ā€œAsk your admin for the card!ā€ + - Completing that task will send an in-product notification to your admin team that you requested the card. - Once youā€™re assigned a card limit, youā€™ll receive an email notification. Click the link in the email to provide your shipping address on your accountā€™s homepage. - Enter your address, and the physical card will be shipped within 3-5 business days. 3. **Activate the Card:** When your physical card arrives, activate it in Expensify by entering the last four digits of the card in the activation task on your homepage. diff --git a/docs/articles/expensify-classic/expensify-card/Unlimited-Virtual-Cards.md b/docs/articles/expensify-classic/expensify-card/Unlimited-Virtual-Cards.md index 239da6518be7..fdbc178737e1 100644 --- a/docs/articles/expensify-classic/expensify-card/Unlimited-Virtual-Cards.md +++ b/docs/articles/expensify-classic/expensify-card/Unlimited-Virtual-Cards.md @@ -66,6 +66,8 @@ There are two different limit types that are best suited for their intended purp - _Fixed limit_ spend cards are ideal for one-time expenses or providing employees access to a card for a designated purchase. - _Monthly_ limit spend cards are perfect for managing recurring expenses such as subscriptions and memberships. +A virtual card with either of these limit types doesn't share its limit with any other cards, including the cardholder's smart limit cards. + **Where can employees see their virtual cards?** Employees can see their assigned virtual cards by navigating to **Settings** > **Account** > [**Credit Cards Import**](https://www.expensify.com/settings?param=%7B%22section%22:%22creditcards%22%7D) in their account. diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/Accelo.md b/docs/articles/expensify-classic/integrations/accounting-integrations/Accelo.md deleted file mode 100644 index fffe0abb43aa..000000000000 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/Accelo.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Accelo -description: Help doc for Accelo integration ---- - - -# Overview -Accelo is a cloud-based business management software platform tailored for professional service companies, offering streamlined operations. It enables seamless integration with Expensify, allowing users to effortlessly import expense details from Expensify into Accelo, associating them with the corresponding project, ticket, or retainer within the system. - -# How to Connect Expensify to Accelo -To connect Expensify to Accelo, follow these clear steps: - -## Prerequisites -Ensure you have administrator access to Accelo. -Have a Workspace Admin role in Expensify. - -## Connecting Expensify to Accelo -1. Access the Expensify Integration Server: -- Open the Expensify Integration Server. -2. Retrieve Your Partner User ID and Partner User Secret: -- Important: These credentials are distinct from your regular Expensify username and password. -- If you haven't previously set up the integration server, click where it indicates "click here." -3. Regenerating Partner User Secret (If Necessary): -- Note: If you've previously configured the integration server, you must regenerate your Partner User Secret. Do this by clicking "click here" to regenerate your partnerUserSecret. -- If you currently use the Integration Server/API for another integration, remember to update that integration to use the new Secret. -4. Configure Accelo: -- Return to your Accelo account. -- Navigate to your Integrations page and select the Expensify tab. -5. Enter Expensify Integration Server Credentials: -- Provide your Expensify Integration Server's Partner User ID and Partner User Secret. -- Click "Save" to complete the setup. -6. Connection Established: -- Congratulations! Your Expensify account is now successfully connected to Accelo. - -With this connection in place, all Expensify users can effortlessly synchronize their expenses with Accelo, streamlining their workflow and improving efficiency. - -## How to upload your Accelo Project Codes as Tags in Expensify -Once you have connected Accelo to Expensify, the next step is to upload your Accelo Project Codes as Tags in Expensify. Simply go to Go to **Settings** > **Workspaces** > **Group** > _[Workspace Name]_ > **Tags** and upload your CSV. -If you directly integrate with Xero or QuickBooks Online, you must upload your Project Codes by appending your tags. Go to **Settings** > **Workspaces** > **Group** > _[Workspace Name]_ > **Tags** and click on ā€œAppend a custom tag list from a CSVā€ to upload your Project Codes via a CSV. - -# Deep Dive -## Information sync between Expensify and Accelo -The Accelo integration does a one-way sync, which means it brings expenses from Expensify into Accelo. When this happens, it transfers specific information from Expensify expenses to Accelo: - -| Expensify | Accelo | -|---------------------|-----------------------| -| Comment | Title | -| Date | Date Incurred | -| Category | Type | -| Tags | Against (relevant Project, Ticket or Retainer) | -| Distance (mileage) | Quantity | -| Hours (time expenses) | Quantity | -| Amount | Purchase Price and Sale Price | -| Reimbursable? | Reimbursable? | -| Billable? | Billable? | -| Receipt | Attachment | -| Tax Rate | Tax Code | -| Attendees | Submitted By | - -## Expense Status -The status of your expense report in Expensify is also synced in Accelo. - -| Expensify Report Status | Accelo Expense Status | -|-------------------------|-----------------------| -| Open | Submitted | -| Submitted | Submitted | -| Approved | Approved | -| Reimbursed | Approved | -| Rejected | Declined | -| Archived | Approved | -| Closed | Approved | - -## Importing expenses from Expensify to Accelo -Accelo regularly checks Expensify for new expenses once every hour. It automatically brings in expenses that have been created or changed since the last sync. diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md b/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md deleted file mode 100644 index 6c7014827ea6..000000000000 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/Certinia.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -title: Certinia -description: Guide to connecting Expensify and Certinia FFA and PSA/SRP (formerly known as FinancialForce) ---- -# Overview -[Cetinia](https://use.expensify.com/financialforce) (formerly known as FinancialForce) is a cloud-based software solution that provides a range of financial management and accounting applications built on the Salesforce platform. There are two versions: PSA/SRP and FFA and we support both. - -# Before connecting to Certinia -Install the Expensify bundle in Certinia using the relevant installer: -* [PSA/SRP](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t2M000002J0BHD%252Fpackaging%252FinstallPackage.apexp%253Fp0%253D04t2M000002J0BH) -* [FFA](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t4p000001UQVj) - -## Check contact details in Certinia -First, make sure you have a user and contact in Certinia that match your main email in Expensify. Then, create contacts for all employees who will be sending expense reports. Ensure that each contact's email matches the one they use in their Expensify account. - -## If you use PSA/SRP -Each report approver needs both a User and a Contact. The user does not need to have a SalesForce license. These can be free chatter users. -Set permission controls in Certinia for your user for each contact/resource. -* Go to Permission Controls - - Create a new permission control - - Set yourself (exporter) as the user - - Select the resource (report submitter) - - Grant all available permissions -* Set permissions on any project you are exporting to - - Go to **Projects** > _select a project_ > **Project Attributes** > **Allow Expenses Without Assignment** - - Select the project > **Edit** - - Under the Project Attributes section, check **Allow Expenses Without Assignment** -* Set up Expense Types (categories in Expensify - _SRP only_) - - Go to **Main Menu** > _+ symbol_ > **Expense Type GLA Mappings** - - Click **New** to add new mappings - -# How to connect to Certinia -1. Go to **Settings** > **Workspaces** > **Groups** > _[Workspace Name]_ > **Connections** in Expensify -2. Click **Create a New Certinia (FinancialForce) Connection** -3. Log into your Certinia account -4. Expensify and Certinia will begin to sync (in Expensify) - -# How to configure export settings for Certinia -## Preferred Exporter -The preferred exporter is the user who will be the main exporter of reports. This person will receive the notifications for errors. - -## Payable Invoice Status and Date -Reports can be exported as Complete or In Progress, using date of last expense, submitted date or exported date. - -## Reimbursable and non-reimbursable exports -Both reimbursable and non-reimbursable reports are exported as payable invoices (FFA) or expense reports (PSA/SRP). If you have both Reimbursable and Non-Reimbursable expenses on a single report, we will create a separate payable invoice/expense report for each type. - -## Default Vendor (FFA) -Choose from the full list of vendors from your Certinia FFA account, this will be applied to the non-reimbursable payable invoices. - -# How to Configure coding for Certinia -## Company -Select which FinancialForce company to import from/export to. - -## Chart of Accounts (FFA) -Prepaid Expense Type and Profit & Loss accounts are imported to be used as categories on each expense. - -## Expense Type GLA Mappings (PSA/SRP) -Your Expense Type GLA Mappings are enabled in Expensify to use as categories on each expense when using both PSA and SRP; however, PSA will not import or export categories, while SRP will. - -## Dimensions (FFA) -We import four dimension levels and each has three options to select from: - -* Do not map: FinancialForce defaults will apply to the payable invoice, without importing into Expensify -* Tags: These are shown in the Tag section of your workspace, and employees can select them on each expense created -* Report fields: These will show in the Reports section of your workspace. Employees can select one to be applied at the header level i.e. the entire report. - -## Projects, Assignments, or Projects & Assignments (PSA/SRP) -These can be imported as tags with **Milestones** being optional. When selecting to import only projects, we will derive the account from the project. If an assignment is selected, we will derive both the account and project from the assignment. - -Note: If you are using a project that does not have an assignment, the box **Allow Expenses Without Assignment** must be checked on the project in FinancialForce. - -## Tax -Import tax rates from Certinia to apply to expenses. - -# How to configure advanced settings for Certinia -## Auto Sync -Auto Sync in Certinia performs daily updates to your coding. Additionally, it automatically exports reports after they receive final approval. For Non-Reimbursable expenses, syncing happens immediately upon final approval of the report. In the case of Reimbursable expenses, syncing occurs as soon as the report is reimbursed or marked as reimbursed. - -## Export tax as non-billable -When exporting Billable expenses, this dictates whether you will also bill the tax component to your clients/customers. - -# Deep Dive -## Multi-Currency in Certinia PSA/SRP -When exporting to Certinia PSA/SRP you may see up to three different currencies on the expense report in Certinia, if employees are submitting expenses in more than one original currency. -* Summary Total Reimbursement Amount: this currency is derived from the currency of the project selected on the expense. -* Amount field on the Expense line: this currency is derived from the Expensify workspace default report currency. -* Reimbursable Amount on the Expense line: this currency is derived from the currency of the resource with an email matching the report submitter. - -{% include faq-begin.md %} -## What happens if the report canā€™t be exported to Certinia? -* The preferred exporter will receive an email outlining the issue and any specific error messages -* Any error messages preventing the export from taking place will be recorded in the reportā€™s history -* The report will be listed in the exporterā€™s Expensify Inbox as awaiting export. - -## If I enable Auto Sync, what happens to existing approved and reimbursed reports? -You can activate Auto Sync without worry because it relies on Final Approval to trigger auto-export. Existing Approved reports won't be affected. However, for Approved reports that haven't been exported to Certinia, you'll need to either manually export them or mark them as manually entered. - -## How do I export tax? -Tax rates are created in Expensify through the tax tracking feature under **Settings** > **Workspaces** > **Groups** > _[Workspace Name]_ > **Tax**. We export the tax amount calculated on the expenses. - -## How do reports map to Payable Invoices in Certinia FFA? -* Account Name - Account associated with Expensify submitterā€™s email address -* Reference 1 - Report URL -* Invoice Description - Report title - -## How do reports map to Expense Reports in Certinia PSA/SRP? -* Expense report name - Report title -* Resource - User associated with Expensify submitterā€™s email address -* Description - Report URL -* Approver - Expensify report approver - -# Sync and Export Errors - -## ExpensiError FF0047: You must have an Ops Edit permission to edit approved records. -This error indicates that the permission control setup between the connected user and the report submitter or region is missing Ops Edit permission. - -In Certinia go to Permission Controls and click the one you need to edit. Make sure that Expense Ops Edit is selected under Permissions. - -## ExpensiError FF0076: Could not find employee in Certinia -Go to Contacts in Certinia and add the report creator/submitter's Expensify email address to their employee record, or create a record with that email listed. - -If a record already exists then search for their email address to confirm it is not associated with multiple records. - -## ExpensiError FF0089: Expense Reports for this Project require an Assignment -This error indicates that the project needs to have the permissions adjusted in Certinia - -Go to Projects > [project name] > Project Attributes and check Allow Expense Without Assignment. - -## ExpensiError FF0091: Bad Field Name ā€” [field] is invalid for [object] -This means the field in question is not accessible to the user profile in Certinia for the user whose credentials were used to make the connection within Expensify. - -To correct this: -* Go to Setup > Build > expand Create > Object within Certinia -* Then go to Payable Invoice > Custom Fields and Relationships -* Click View Field Accessibility -* Find the employee profile in the list and select Hidden -* Make sure both checkboxes for Visible are selected - -Once this step has been completed, sync the connection within Expensify by going to **Settings** > **Workspaces** > **Groups** > _[Workspace Name]_ > **Connections** > **Sync Now** and then attempt to export the report again. - -## ExpensiError FF0132: Insufficient access. Make sure you are connecting to Certinia with a user that has the 'Modify All Data' permission - -Log into Certinia and go to Setup > Manage Users > Users and find the user whose credentials made the connection. - -* Click on their profile on the far right side of the page -* Go to System > System Permissions -* Enable Modify All Data and save - -Sync the connection within Expensify by going to **Settings** > **Workspaces** > **Groups** > _[Workspace Name]_ > **Connections** > **Sync Now** and then attempt to export the report again - -{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop.md b/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop.md deleted file mode 100644 index 8fe31f3ec4f4..000000000000 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: QuickBooks Desktop -description: How to connect Expensify to QuickBooks Desktop and troubleshoot issues. ---- -# Overview -QuickBooks Desktop is an accounting package developed by Intuit. It is designed for small and medium-sized businesses to help them manage their financial and accounting tasks. You can connect Expensify to QuickBooks Desktop to make expense management seamless. -To connect Expensify with QuickBooks Desktop, using Right Networks as your hosting platform is best. Right Networks is a cloud-based service we recommend for this integration. If you need a Right Networks account, complete [this form](https://info.rightnetworks.com/partner-expensify) and contact a Sales Consultant to start the process. - -# How to connect to QuickBooks Desktop -Before you link your Expensify policy with QuickBooks Desktop, ensure you log in as an Admin in QuickBooks. Also, check that the company file you want to connect to is the only one open. - -## Set up submitters in QuickBooks Desktop -For a seamless integration, here are the steps to follow: -* Make sure all report submitters are set up as Vendors in QuickBooks Desktop and their Expensify email is in the "Main Email" field of their Vendor record. You can do this in the vendor section of QuickBooks. -* If you want to export reports to your users' employee records instead of vendor records, select Check or Journal Entry as your reimbursable export option. -* To set up Expensify users as employees, activate QuickBooks Desktop Payroll. This module is necessary to access the Employee Profile tab, where you can enter the submitter's email addresses. - -## Enable/install the Expensify Sync Manager -Navigate to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Connections**, select the Connect to QuickBooks Desktop radio button and click Connect to QuickBooks. - -**Enable the Expensify Sync Manager in Right Networks (recommended)** -*Please note: Single-user mode in QuickBooks Desktop is required.* -If you don't yet have an account with Right Networks, you must first contact Right Networks [here](https://info.rightnetworks.com/partner-expensify). You can enable the Expensify Sync Manager yourself from your Right Networks portal's **My Account** section or contact Right Networks for assistance. - -**OR, install the Expensify Sync Manager on Your Third-Party Remote Desktop.** -To download the Sync Manager to your desktop, you must contact your third-party remote desktop provider and request permission. They might have security restrictions, so it's best to communicate with them directly to avoid potential problems with the Sync Manager. Remember that the Sync Manager program file should be stored in the same location (i.e., the same drive) as your QuickBooks Desktop program. - -## Complete the connection -1. Open QuickBooks and access your desired Company File using the QuickBooks Admin credentials. Admin credentials are necessary for creating the connection due to permission requirements, but you won't need to stay logged in as an admin for syncing or exporting. -2. Navigate to your Expensify policy settings by going to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Connections**. Copy the Token by selecting the copy icon. -3. While QuickBooks is still running, launch the Expensify Sync Manager. Paste your Token into the Sync Manager and click **Save**. -4. Once the Sync Manager status displays **Connected**, return to Expensify and click the *Continue* button. - -## Allow access -1. Return to QuickBooks, and you'll encounter an **Application Certificate** screen. On the first page of the Certificate screen, click **Yes, always; allow access even if QuickBooks is not running** and then click **Continue**. -2. On the second page of the Certificate screen, choose the Admin user from the dropdown menu, and then click *Done* to complete this step. Note that selecting Admin here does not require you to be logged in as an admin to use this connection; it's simply selecting the appropriate permissions. -3. Head back to Expensify and patiently wait for the sync process to finish, then move on to the configuration. - -# How to configure export settings for QuickBooks Desktop -To Configure Settings, go to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Connections** and click **Configure**. - -## Preferred Exporter -This person is used in QuickBooks Desktop as the export user. They will also receive notifications for errors. - -## Date -Choose either the report's submitted date, the report's exported date, or the date of the last expense on the report when exporting reports to QuickBooks Desktop. - -## Use unique reference numbers -Enable this to allow use of a unique reference number for each transaction. Disable this to use the same Report ID for all expenses from a certain report. - -## Reimbursable expenses -* **Vendor Bill (recommended):** A single itemized vendor bill for each Expensify report. An A/P account is required to export to a vendor bill. -* **Check:** A single itemized check for each Expensify report. -* **Journal Entry:** A single itemized journal entry for each Expensify report. - -## Non-reimbursable expenses -**Credit Card Expenses:** -* Each expense will appear as a separate credit card transaction. -* The posting date will match your credit card statement. -* To display the merchant name in the payee field in QuickBooks Desktop, ensure that a matching Vendor exists in QuickBooks. Expensify searches for an exact match during export. If no match is found, the payee is mapped to a **Credit Card Misc.** Vendor created by Expensify. -* If you're centrally managing company cards through Domain Control, you can export expenses from each card to a specific QuickBooks account (detailed instructions available). - -**Debit Card Expenses:** -* Expenses export as individual itemized checks for each Expensify report. -* The check is written to the "vendor," which is the person who created or submitted the report in Expensify. - -**Vendor Bill:** -* Each Expensify report results in a single itemized vendor bill. -* The bill is associated with the "vendor," which is the individual responsible for creating or submitting the report in Expensify. - -# How to configure coding for QuickBooks Desktop -## Categories -Expensify's integration with QuickBooks brings in your Chart of Accounts as Categories in Expensify automatically. Here's how to manage them: -1. After connecting, go to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Categories** to view the accounts imported from QuickBooks Desktop. -2. You can use the enable/disable button to choose which Categories your employees can access. Additionally, you can set specific rules for each Category via the blue settings cog. -3. Expensify offers Auto-Categorization to automatically assign expenses to the appropriate expense categories. -4. If needed, you can edit the names of the imported Categories to simplify expense coding for your employees. Keep in mind that if you make changes to these accounts in QuickBooks Desktop, the category names in Expensify will update to match them during the next sync. -5. _**Important:**_ Each expense must have a category selected to export to QuickBooks Desktop. The selected category must be one imported from QuickBooks Desktop; you cannot manually create categories within Expensify policy settings. - -## Classes -Classes can be imported from QuickBooks as either tags (line-item level) or report fields (header level). - -## Customers/Projects -You can bring in Customers/Projects from QuickBooks into Expensify in two ways: as tags (at the line-item level) or as report fields (at the header level). If you're utilizing Billable Expenses in Expensify, here's what you need to know: -* Customers/Projects must be enabled if you're using Billable Expenses. -* Expenses marked as "Billable" need to be tagged with a Customer/Project to successfully export them to QuickBooks. - -## Items -Items can be imported from QuickBooks as categories alongside your expense accounts. - -{% include faq-begin.md %} -## How do I sync my connection? -1: Ensure that both the Expensify Sync Manager and QuickBooks Desktop are running. -2: On the Expensify website, navigate to **Settings** > **Policies** > **Group** > _[Policy Name]_ > **Connections** > **QuickBooks Desktop**, and click **Sync now**. -3: Wait for the syncing process to finish. Typically, this takes about 2-5 minutes, but it might take longer, depending on when you last synced and the size of your QuickBooks company file. The page will refresh automatically once syncing is complete. - -We recommend syncing at least once a week or whenever you make changes in QuickBooks Desktop that could impact how your reports export from Expensify. Changes could include adjustments to your Chart of Accounts, Vendors, Employees, Customers/Jobs, or Items. Remember, both the Sync Manager and QuickBooks Desktop need to be running for syncing or exporting to work. - -## Can I export negative expenses? -Generally, you can export negative expenses to QuickBooks Desktop successfully, regardless of your option. However, please keep in mind that if you have *Check* selected as your export option, the report's total cannot be negative. - -## How does multi-currency work with QuickBooks Desktop? -When using QuickBooks Desktop Multi-Currency, there are some limitations to consider based on your export options: -1. **Vendor Bills and Checks:** The currency of the vendor and the currency of the account must match, but they do not have to be in the home currency. -2. **Credit Card:** If an expense doesn't match an existing vendor in QuickBooks, it exports to the **Credit Card Misc.** vendor created by Expensify. When exporting a report in a currency other than your home currency, the transaction will be created under the vendor's currency with a 1:1 conversion. For example, a transaction in Expensify for $50 CAD will appear in QuickBooks as $50 USD. -3. **Journal Entries:** Multi-currency exports will fail because the account currency must match both the vendor currency and the home currency. - -# Sync and export errors -## Error: No Vendor Found For Email in QuickBooks -To address this issue, ensure that each submitter's email is saved as the **Main Email** in their Vendor record within QuickBooks Desktop. Here's how to resolve it: -1. Go to your Vendor section in QuickBooks. -2. Verify that the email mentioned in the error matches the **Main Email** field in the respective vendor's record. It's important to note that this comparison is case-sensitive, so ensure that capitalization matches as well. -3. If you prefer to export reports to your users' employee records instead of their vendor records, select either **Check** or **Journal Entry** as your reimbursable export option. If you are setting up Expensify users as employees, activate QuickBooks Desktop Payroll to access the Employee Profile tab where submitter email addresses need to be entered. -4. Once you've added the correct email to the vendor record, save this change, and then sync your policy before attempting to export the report again. - -## Error: Do Not Have Permission to Access Company Data File -To resolve this error, follow these steps: -1. Log into QuickBooks Desktop as an Admin in single-user mode. -2. Go to **Edit** > **Preferences** > **Integrated Applications** > **Company Preferences**. -3. Select the Expensify Sync Manager and click on **Properties**. -4. Ensure that **Allow this application to login automatically** is checked, and then click **OK**. Close all windows within QuickBooks. -5. If you still encounter the error after following the above steps, go to **Edit** > **Preferences** > **Integrated Applications** > **Company Preferences**, and remove the Expensify Sync Manager from the list. -6. Next, attempt to sync your policy again in Expensify. You'll be prompted to re-authorize the connection in QuickBooks. -7. Click **Yes, always; allow access even if QuickBooks is not running.** -8. From the dropdown, select the Admin user, and then click **Continue**. Note that selecting **Admin** here doesn't mean you always have to be logged in as an admin to use the connection; it's just required for setting up the connection. -9. Click **Done** on the pop-up window and return to Expensify, where your policy should complete the syncing process. - -## Error: The Wrong QuickBooks Company is Open. -This error suggests that the wrong company file is open in QuickBooks Desktop. To resolve this issue, follow these steps: -1. First, go through the general troubleshooting steps as outlined. -2. If you can confirm that the incorrect company file is open in QuickBooks, go to QuickBooks and select **File** > **Open or Restore Company** > _[Company Name]_ to open the correct company file. After doing this, try syncing your policy again. -3. If the correct company file is open, but you're still encountering the error, completely close QuickBooks Desktop, reopen the desired company file and then attempt to sync again. -4. If the error persists, log into QuickBooks as an admin in single-user mode. Then, go to **Edit** > **Preferences** > **Integrated Applications** > **Company Preferences** and remove the Expensify Sync Manager from the list. -5. Next, try syncing your policy again in Expensify. You'll be prompted to re-authorize the connection in QuickBooks, allowing you to sync successfully. -6. If the error continues even after trying the steps above, double-check that the token you see in the Sync Manager matches the token in your connection settings. - -## Error: The Expensify Sync Manager Could Not Be Reached. -To resolve this error, follow these steps: -*Note: You must be in single-user mode to sync.* - -1. Ensure that both the Sync Manager and QuickBooks Desktop are running. -2. Confirm that the Sync Manager is installed in the correct location. It should be in the same location as your QuickBooks application. If QuickBooks is on your local desktop, the Sync Manager should be there, too. If QuickBooks is on a remote server, install the Sync Manager there. -Verify that the Sync Manager's status is **Connected**. -3. If the Sync Manager status is already **Connected**, click **Edit** and then *Save* to refresh the connection. Afterwards, try syncing your policy again. -4. If the error persists, double-check that the token you see in the Sync Manager matches the token in your connection settings. - -{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online.md b/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online.md deleted file mode 100644 index 623e5f1dd997..000000000000 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online.md +++ /dev/null @@ -1,324 +0,0 @@ ---- -title: QuickBooks Online -description: Everything you need to know about using Expensify's direct integration with QuickBooks Online. ---- -# Overview - -The Expensify integration with QuickBooks Online brings in your expense accounts and other data and even exports reports directly to QuickBooks for easy reconciliation. Plus, with advanced features in QuickBooks Online, you can fine-tune coding settings in Expensify for automated data export to optimize your accounting workflow. - -## Before connecting - -It's crucial to understand the requirements based on your specific QuickBooks subscription: - -- While all the features are available in Expensify, their accessibility may vary depending on your QuickBooks Online subscription. -- An error will occur if you try to export to QuickBooks with a feature enabled that isn't part of your subscription. -- Please be aware that Expensify does not support the Self-Employed subscription in QuickBooks Online. - -![QuickBooks Online - Subscription types]({{site.url}}/assets/images/QBO1.png){:width="100%"} - -# How to connect to QuickBooks Online - -## Step 1: Setup employees in QuickBooks Online - -Employees must be set up as either Vendors or Employees in QuickBooks Online. Make sure to include the submitter's email in their record. - -If you use vendor records, you can export as Vendor Bills, Checks, or Journal Entries. If you use employee records, you can export as Checks or Journal Entries (if exporting against a liability account). - -Additional Options for Streamlined Setup: - -- Automatic Vendor Creation: Enable ā€œAutomatically Create Entitiesā€ in your connection settings to automatically generate Vendor or Employee records upon export for submitters that don't already exist in QBO. -- Employee Setup Considerations: If setting up submitters as Employees, ensure you activate QuickBooks Online Payroll. This will grant access to the Employee Profile tab to input employee email addresses. - -## Step 2: Connect Expensify and QuickBooks Online - -- Navigate to Settings > Workspaces > Group > [Workspace Name] > Connections > QuickBooks Online. Click Connect to QuickBooks. -- Enter your QuickBooks Online Administratorā€™s login information and choose the QuickBooks Online Company File you want to connect to Expensify (you can connect one Company File per Workspace). Then click Authorize. -- Enter your QuickBooks Online Administratorā€™s login information and choose the QuickBooks Online Company File you want to connect to Expensify (you can connect one Company File per Workspace): - -## Exporting historical Reports to QuickBooks Online: - -After connecting QuickBooks Online to Expensify, you may receive a prompt to export all historical reports from Expensify. To export multiple reports at once, follow these steps: - -- Go to the Reports page on the web. -- Tick the checkbox next to the reports you want to export. -- Click 'Export To' and select 'QuickBooks Online' from the drop-down list. - -If you don't want to export specific reports, click ā€œMark as manually enteredā€ on the report. - -# How to configure export settings for QuickBooks Online - -Our QuickBooks Online integration offers a range of features. This section will focus on Export Settings and how to set them up. - -## Preferred Exporter - -Any Workspace admin can export to your accounting integration, but the Preferred Exporter can be chosen to automate specific steps. You can set this role from Settings > Workspaces > Group > [Workspace Name] > Connections > Configure > Export > Preferred Exporter. - -The Preferred Exporter: - -- Is the user whose Concierge performs all automated exports on behalf of. -- Is the only user who will see reports awaiting export in their **Home.** -- Must be a **Domain Admin** if you have set individual GL accounts for Company Card export. -- Must be a **Domain Admin** if this is the Preferred Workspace for any Expensify Card domain using Automatic Reconciliation. - -## Date - -When exporting reports to QuickBooks Online, you can choose the report's **submitted date**, the report's **exported date**, or the **date of the last expense on the report.** - -Most export options (Check, Journal Entry, and Vendor Bill) will create a single itemized entry with one date. -Please note that if you choose a Credit Card or Debit Card for non-reimbursable expenses, we'll use the transaction date on each expense during export. - -# Reimbursable expenses - -Reimbursable expenses export to QuickBooks Online as: - -- Vendor Bills -- Checks -- Journal Entries - -## Vendor bill (recommended) - -This is a single itemized vendor bill for each Expensify report. If the accounting period is closed, we will post the vendor bill on the first day of the next open period. If you export as Vendor Bills, you can also choose to Sync reimbursed reports (set on the Advanced tab). **An A/P account is required to export to a vendor bill.** - -The submitter will be listed as the vendor in the vendor bill. - -![Vendor Bill]({{site.url}}/assets/images/QBO2-Bill.png){:width="100%"} - -## Check - -This is a single itemized check for each Expensify report. You can mark a check to be printed later in QuickBooks Online. - -![Check to print]({{site.url}}/assets/images/QBO3-Checktoprint.png){:width="100%"} - -## Journal entry - -This is a single itemized journal entry for each Expensify report. - -![Journal Entry]({{site.url}}/assets/images/QBO4-JournalEntry.png){:width="100%"} - -# Non-reimbursable expenses - -Non-reimbursable expenses export to QuickBooks Online as: - -- Credit Card expenses -- Debit Card Expenses -- Vendor Bills - -## Credit/debit card - -Using Credit/Debit Card Transactions: - -- Each expense will be exported as a bank transaction with its transaction date. -- If you split an expense in Expensify, we'll consolidate it into a single credit card transaction in QuickBooks with multiple line items posted to the corresponding General Ledger accounts. - -Pro-Tip: To ensure the payee field in QuickBooks Online reflects the merchant name for Credit Card expenses, ensure there's a matching Vendor in QuickBooks Online. Expensify checks for an exact match during export. If none are found, the payee will be mapped to a vendor we create and labeled as Credit Card Misc. or Debit Card Misc. - -![Expense]({{site.url}}/assets/images/QBO5-Expense.png){:width="100%"} - -If you centrally manage your company cards through Domains, you can export expenses from each card to a specific account in QuickBooks. - -## Vendor Bill - -- A single detailed vendor bill is generated for each Expensify report. If the accounting period is closed, the vendor bill will be posted on the first day of the next open period. If you choose to export non-reimbursable expenses as Vendor Bills, you can assign a default vendor to the bill. -- The export will use your default vendor if you have Default Vendor enabled. If the Default Vendor is disabled, the report's submitter will be set as the Vendor in QuickBooks. - -## Billable Expenses - -- In Expensify, you can designate expenses as billable. These will be exported to QuickBooks Online with the billable flag. This feature applies only to expenses exported as Vendor Bills or Checks. To maximize this functionality, ensure that any billable expense is associated with a Customer/Job. - -## Export Invoices - -If you are creating Invoices in Expensify and exporting these to QuickBooks Online, this is the account the invoice will appear against. - -# Configure coding for QuickBooks Online - -The coding tab is where your information is configured for Expensify; this will allow employees to code expenses and reports accurately. - -- Categories -- Classes and/or Customers/Projects -- Locations -- Items -- Tax - -## Categories - -QuickBooks Online expense accounts will be automatically imported into Expensify as Categories. - -## Account Import - -Equity type accounts will also be imported as categories. - -Important notes: - -- Other Current Liabilities can only be exported as Journal Entries if the submitter is set up as an Employee in QuickBooks. -- Exchange Gain or Loss detail type does not import. - -Recommended steps to take after importing the expense accounts from QuickBooks to Expensify: - -- Go to Settings > Workspaces > Groups > [Workspace Name] > Categories to see the accounts imported from QuickBooks Online. -- Use the enable/disable button to choose which Categories to make available to your employees, and set Category specific rules via the blue settings cog. -- If necessary, edit the names of imported Categories to make expense coding easier for your employees. (Please Note: If you make any changes to these accounts in QuickBooks Online, the category names on Expensify's side will revert to match the name of the account in QuickBooks Online the next time you sync). -- If you use Items in QuickBooks Online, you can import them into Expensify as Categories. - -Please note that each expense has to have a category selected to export to QuickBooks Online. The chosen category has to be imported from QuickBooks Online and cannot be manually created within the Workspace settings. - -## Classes and Customers/Projects - -If you use Classes or Customers/Projects in QuickBooks Online, you can import those into Expensify as Tags or Report Fields: - -- Tags let you apply a Class and/or Customer/Project to each expense. -- Report Fields enables you to apply a Class and/or Customer/Project to all expenses on a report. - -Note: Although Projects can be imported into Expensify and coded to expenses, due to the limitations of the QuickBooks API, expenses cannot be created within the Projects module in QuickBooks. - -## Locations - -Locations can be imported into Expensify as a Report Field or, if you export reimbursable expenses as Journal Entries and non-reimbursable expenses as Credit/Debit Card, you can import Locations as Tags. - -## Items - -If you use Items in QuickBooks Online, you can import Items defined with Purchasing Information (with or without Sales Information) into Expensify as Categories. - -## Tax - -- Using our tax tracking feature, you can assign a tax rate and amount to each expense. -- To activate tax tracking, go to connection configuration and enable it. This will automatically import purchasing taxes from QuickBooks Online into Expensify. -- After the connection is set, navigate to Settings > Workspaces > Groups > [Workspace Name] > Tax. Here, you can view the taxes imported from QuickBooks Online. -- Use the enable/disable button to choose which taxes are accessible to your employees. -- Set a default tax for the Company Workspace, which will automatically apply to all new expenses. -- Please note that, at present, tax cannot be exported to Journal Entries in QuickBooks Online. -- Expensify performs a daily sync to ensure your information is up-to-date. This minimizes errors from outdated QuickBooks Online data and saves you time on syncing. - -# How to configure advanced settings for QuickBooks Online - -The advanced settings are where functionality for automating and customizing the QuickBooks Online integration can be enabled. -Navigate to this section of your Workspace by following Settings > Workspaces > Group > [Workspace Name] > Connections > Configure button > Advanced tab. - -## Auto Sync -With QuickBooks Online auto-sync, once a non-reimbursable report is final approved in Expensify, it's automatically queued for export to QuickBooks Online. For expenses eligible for reimbursement with a linked business bank account, they'll sync when marked as reimbursed. - -## Newly Imported Categories - -This setting determines the default status of newly imported categories from QuickBooks Online to Expensify, either enabled or disabled. - -## Invite Employees - -Enabling this automatically invites all Employees from QuickBooks Online to the connected Expensify Company Workspace. If not, you can manually invite or import them using a CSV file. - -## Automatically Create Entities - -When exporting reimbursable expenses as Vendor Bills or Journal Entries, Expensify will automatically create a vendor in QuickBooks if one doesn't exist. It will also generate a customer when exporting Invoices. - -## Sync Reimbursed Reports - -Enabling this marks the Vendor Bill as paid in QuickBooks Online when you reimburse a report via ACH direct deposit in Expensify. If reimbursing outside Expensify, marking the Vendor Bill as paid will automatically in QuickBooks Online update the report as reimbursed in Expensify. Note: After enabling this feature, select your QuickBooks Account in the drop-down, indicating the bank account for reimbursements. - -## Collection Account - -If you are exporting Invoices from Expensify to Quickbooks Online, this is the account the Invoice will appear against once marked as Paid. - -# Deep Dive - -## Preventing Duplicate Transactions in QuickBooks - -When importing a banking feed directly into QuickBooks Online while also importing transactions from Expensify, it's possible to encounter duplicate entries in QuickBooks. To prevent this, follow these steps: - -Step 1: Complete the Approval Process in Expensify - -- Before exporting any expenses to QuickBooks Online, ensure they are added to a report and the report receives approval. Depending on your Workspace setup, reports may require approval from one or more individuals. The approval process concludes when the last user who views the report selects "Final Approve." - -Step 2: Exporting Reports to QuickBooks Online - -- To ensure expenses exported from Expensify match seamlessly in the QuickBooks Banking platform, make sure these expenses are marked as non-reimbursable within Expensify and that ā€œCredit Cardā€ is selected as the non-reimbursable export option for your expenses. - -Step 3: Importing Your Credit Card Transactions into QuickBooks Online - -- After completing Steps 1 and 2, you can import your credit card transactions into QuickBooks Online. These imported banking transactions will align with the ones brought in from Expensify. QuickBooks Online will guide you through the process of matching these transactions, similar to the example below: - -![Transactions]({{site.url}}/assets/images/QBO7-Transactions.png){:width="100%"} - -## Tax in QuickBooks Online - -If your country applies taxes on sales (like GST, HST, or VAT), you can utilize Expensify's Tax Tracking along with your QuickBooks Online tax rates. Please note: Tax Tracking is not available for Workspaces linked to the US version of QuickBooks Online. If you need assistance applying taxes after reports are exported, contact QuickBooks. - -To get started: - -- Go to Settings > Workspaces > Group > [Workspace Name] > Connections, and click Configure. -- Navigate to the Coding tab. -- Turn on **Tax**. -- Click Save. This imports the Tax Name and rate from QuickBooks Online. -- Visit Settings > Workspaces > Group > [Workspace Name] > Tax to view the imported taxes. -- Use the enable/disable button in the Tax tab to choose which taxes your employees can use. - -Remember, you can also set a default tax rate for the entire Workspace. This will be automatically applied to all new expenses. The user can still choose a different tax rate for each expense. - -Tax information can't be sent to Journal Entries in QuickBooks Online. Also, when dealing with multiple tax rates, where one receipt has different tax rates (like in the EU, UK, and Canada), users should split the expense into the respective parts and set the appropriate tax rate for each part. - -## Multi-currency - -When working with QuickBooks Online Multi-Currency, there are some things to remember when exporting Vendor Bills and Check! Make sure the vendor's currency and the Accounts Payable (A/P) bank account match. - -In QuickBooks Online, the currency conversion rates are not applied when exporting. All transactions will be exported with a 1:1 conversion rate, so for example, if a vendor's currency is CAD (Canadian Dollar) and the home currency is USD (US Dollar), the export will show these currencies without applying conversion rates. - -![Check]({{site.url}}/assets/images/QBO6-Check.png){:width="100%"} - -To correct this, you must manually update the conversion rate after the report has been exported to QuickBooks Online. - -Specifically for Vendor Bills: - -If multi-currency is enabled and the Vendor's currency is different from the Workspace currency, OR if QuickBooks Online home currency is foreign from the Workspace currency, then: - -- We create the Vendor Bill in the Vendor's currency (this is a QuickBooks Online requirement - we don't have a choice) -- We set the exchange rate between the home currency and the Vendor's currency -- We convert line item amounts to the vendor's currency - -Let's consider this example: - -- QuickBooks Online home currency is USD -- Vendor's currency is VND -- Workspace (report) currency is JPY - -Upon export, we: - -1. Specified the bill is in VND -2. Set the exchange rate between VND and USD (home currency), computed at the time of export. -3. Converted line items from JPY (currency in Expensify) to VND -4. QuickBooks Online automatically computed the USD amount (home currency) based on the exchange rate we specified -5. Journal Entries, Credit Card, and Debit Card: - -Multi-currency exports will fail as the account currency must match both the vendor and home currencies. - -## Report Fields - -Report fields are a handy way to collect specific information for a report tailored to your organization's needs. They can specify a project, business trip, client, location, and more! - -When integrating Expensify with Your Accounting Software, you can create your report fields in your accounting software so the next time you sync your Workspace, these fields will be imported into Expensify. - -To select how a specific field imports to Expensify, head to Settings > Workspaces > Group > -[Workspace Name] > Connections > Accounting Integrations > QuickBooks Online > Configure > Coding. - -Here are the QuickBooks Online fields that can be mapped as a report field within Expensify: - -- Classes -- Customers/Projects -- Locations - -{% include faq-begin.md %} - -## What happens if the report can't be exported to QuickBooks Online automatically? - -If a report encounters an issue during automatic export to QuickBooks Online, you'll receive an email with details about the problem, including any specific error messages. These messages will also be recorded in the report's history section. - -The report will be placed in your Home for your attention. You can address the issues there. If you need further assistance, refer to our QuickBooks Online Export Errors page or export the report manually. - -## How can I ensure that I final approve reports before they're exported to QuickBooks Online? - -To ensure reports are reviewed before export, set up your Workspaces with the appropriate workflow in Expensify. Additionally, consider changing your Workspace settings to enforce expense Workspace workflows strictly. This guarantees that your Workspace's workflow is consistently followed. - -## What happens to existing approved and reimbursed reports if I enable Auto Sync? - -- If Auto Sync was disabled when your Workspace was linked to QuickBooks Online, enabling it won't impact existing reports that haven't been exported. -- If a report has been exported and reimbursed via ACH, it will be automatically marked as paid in QuickBooks Online during the next sync. -- If a report has been exported and marked as paid in QuickBooks Online, it will be automatically marked as reimbursed in Expensify during the next sync. -- Reports that have yet to be exported to QuickBooks Online won't be automatically exported. - -{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/integrations/accounting-integrations/Xero.md b/docs/articles/expensify-classic/integrations/accounting-integrations/Xero.md deleted file mode 100644 index 9dd479e90cf1..000000000000 --- a/docs/articles/expensify-classic/integrations/accounting-integrations/Xero.md +++ /dev/null @@ -1,262 +0,0 @@ ---- -title: The Xero Integration -description: Everything you need to know about Expensify's direct integration with Xero ---- - -# About - -The integration enables seamless import of expense accounts into Expensify and sends expense reports back to Xero as purchasing bills awaiting payment or "spend money" bank transactions. - -# How-to Connect to Xero - -## Prerequisites - -You must be a Workspace Admin in Expensify using a Collect or Control Workspace to connect your Xero account to Expensify. - -## Connect Expensify and Xero - -1. Let's get started by heading over to your Settings. You can find it by following this path: *Settings > Workspaces > Groups > [Workspace Name] > Connections > Xero.* -2. To connect Expensify to Xero, click on the "Connect to Xeroā€ button, then choose "Create a new Xero connection." -3. Next, enter your Xero login details. After that, you'll need to select the Xero organization you want to link with Expensify. Remember, you can connect one organization for each Workspace. - -One important note: Starting in September 2021, there's a chance for Cashbook and Ledger-type organizations in Xero. Apps like Expensify won't be able to create invoices and bills for these accounts using the Xero API. So, if you're using a Cashbook or Ledger Xero account, please be aware that this might affect your Expensify integration. - -# How to Configure Export Settings for Xero - -When you integrate Expensify with Xero you gain control over several settings that determine how your reports will be displayed in Xero. To manage these settings simply follow this path: *Settings > Workspaces > Group > [Workspace Name] > Connections > Accounting Integrations > Xero > Configure > Export*. This is where you can fine-tune how your reports appear on the Xero side, making your expense management a breeze! - -## Xero Organization - -When you have multiple organizations set up in Xero you can choose which one you'd like to connect. Here are some essential things to keep in mind: - -1. Organization Selection: You'll see this option only if you have multiple organizations configured in Xero. -2. One Workspace, One Organization: Each Workspace can connect to just one organization at a time. It's a one-to-one connection. -3. Adding New Organizations: If you create a new organization in Xero after your initial connection, you'll need to disconnect and then reconnect it to Xero. Don't forget to take a screenshot of your current settings by clicking on "Configure" and checking the Export, Coding, and Advanced tabs. This way, you can easily set everything up again. - -Now you can seamlessly manage your connections with Xero while staying in control of your configurations! - -## Preferred Exporter - -Any Workspace admin can export to Xero, but only the preferred exporter will see reports that are ready for export in their Home. - -## Reimbursable Expenses - -Export to Xero as bills awaiting payment with the following additional settings: - -- Bill date ā€” the bill is posted on the last day of the month in which expenses were incurred. - -To view the bills in Xero, navigate to *Business > Purchase Overview > Awaiting Payments*. Bills will be payable to the individual who created and reported the expense. - -## Non-reimbursable Expenses - -When you export non-reimbursable expenses, like company card transactions, to Xero they'll show up as bank transactions. Each expense is neatly listed as a separate line item in the bank account of your choice. Plus the transaction date matches the date on your bank statement for seamless tracking. - -To check out these expenses in Xero please follow these steps: - -1. Head over to your Dashboard. -2. Select your company card. -3. Locate the specific expense you're interested in. - -If you're managing company cards centrally, you can export expenses from each card to a designated account in Xero using Domains. This way, you have complete control and clarity over your company's finances! - -# How to Configure Coding for Xero - -The Coding tab in Expensify is where you configure Xero information to ensure accurate expense coding by your employees. Here's how you can access these settings: - -1. Navigate to Settings. -2. Go to Workspace within your specified group (Workspace Name). -3. Click on Connections, and then hit the Configure button. -4. Now, select the Coding tab. - -## Categories - -Xero expense accounts and those marked "Show In Expense Claims" will be automatically imported into Expensify as Categories. - -To manage these categories, follow these steps: - -1. After connecting, go to *Settings > Workspaces > Groups > [Workspace Name] > Categories*. -2. You can enable/disable categories using the checkbox. -3. For specific category rules (like default tax rate, maximum amount, receipts required, comments, and comment hints), click the settings cog. -4. Note that each expense must have a category selected for it to export to Xero, and these categories need to be imported from Xero; manual creation isn't an option within Workspace settings. - -## Tracking Categories - -1. If you use Tracking categories in Xero, you can import them into Expensify as Tags, Report Fields, or the Xero contact default. -- Tags apply a tracking category per expense. -- Report Field applies a tracking category to the entire report. -- Xero contact default applies the default tracking category set for the submitter in Xero. - -## Tax - -Looking to track tax in Expensify? Make sure that you have tax rates enabled in Xero and we will automatically grab those rates from Xero to allow your employees to categorize expenses with the appropriate tax rate. As an admin, you have the ability to set a default rate and also hide rates that are not applicable to the Workspace members. - -Tax tracking allows you to apply a tax rate and tax amount to each expense. -1. To set this up, enable Tax tracking in your Xero configuration. -2. After connecting, go to *Settings > Workspaces > Groups > [Workspace Name] > Tax to manage imported taxes from Xero.* -3. You can enable/disable taxes and set default tax rates for both Workspace currency expenses and foreign currency expenses. - -## Billable Expenses - -If you bill expenses to your customers, you can track and invoice them using Expensify and Xero. - -1. When enabled, Xero customer contacts are imported into Expensify as Tags for expense tracking. -- Note: In Xero, a Contact isn't a 'Customer' until they've had a bill raised against them. If you don't see your Customer imported as a tag, try raising a dummy invoice in Xero and then deleting/voiding it. -2. After exporting to Xero, tagged billable expenses can be included on a sales invoice to your customer. - -Please ensure that you meet the following requirements for expenses to be placed on a sales invoice: -1. Billable Expenses must be enabled in the Xero configuration settings. -2. The expense must be marked as billable. -3. The expense must be tagged with a customer. - -These steps should help you seamlessly manage your Xero integration within Expensify. - -# How to Configure Xeroā€™s Advanced Settings - -If you've already set up your integration, but want to make adjustments, simply follow these steps: - -1. Go to Settings. -2. Then, navigate to Workspaces within your designated group [Workspace Name]. -3. Click on Connections, and next, hit the Configure button. - -From there, you can dive into the "Advanced" tab to make any additional tweaks. - -## Auto Sync - -For non-reimbursable reports: Once a report has completed the approval workflow in Expensify, we'll automatically queue it for export to Xero. - -But, if you've added a business bank account for ACH reimbursement, any reimbursable expenses will be sent to Xero automatically when the report is marked as reimbursed or enabled for reimbursement. - -### Controlling Newly Imported Categories: - -You can decide how newly imported categories behave in Expensify: - -1. Enabling or disabling this control determines the status of new categories imported from Xero to Expensify. Enabled categories are visible for employees when they categorize expenses, while disabled categories remain hidden. - -These settings give you the flexibility to manage your expenses and Workspace in the way that best suits your needs! - -## Sync Reimbursed Reports - -This nifty setting lets you synchronize the status of your reports between Expensify and Xero. Utilizing this setting will make sure that there is no confusion or possibility that a reimbursable report is paid out twice by mistake or that a non-reimbursable report is double entered throwing off month-end reconciliation. Here's how it works: - -1. When you reimburse a report via ACH direct deposit within Expensify, the purchase bill will automatically be marked as paid in Xero, and Expensify will note it as reimbursed. -2. Don't forget to pick the Xero account where the corresponding bill payment should be recorded. -3. It's a simple way to keep everything in sync, especially when you're awaiting payment. - -# Deep Dive - -## An Automatic Export Fails - -Sometimes, reports may encounter issues during automatic export to Xero. Not to worry, though! Here's what happens: - -1. The Technical Contact, your go-to person for technical matters, will receive an email explaining the problem. -2. You'll also find specific error messages at the bottom of the report. -3. To get things back on track, the report will be placed in the preferred exporterā€™s Home. They can review it and resolve any issues. - -## Consider Enforcing Expense Workspace Workflows: - -For added control, you can adjust your Workspace settings to strictly enforce expense Workspace. This way, you guarantee that your Workspaceā€™s workflow is always followed. By default this flow is in place, but employees can modify the person they submit their reports to if it's not strictly enforced. - -## Customize Purchase Bill Status (Optional): - -You have the flexibility to set the status of your purchase bills just the way you want. Choose from the following options: - -1. Draft: Keep bills in a draft state until you're ready to finalize them. -2. Awaiting Approval: If you need approval before processing bills, this option is here for you. - -## Multi-Currency - -### Handling Multi-Currency in Xero - -When dealing with multi-currency transactions in Xero and exporting reimbursable expenses from Expensify here's what you need to know: - -1. The bill created in Xero will adopt the output currency set in your Expensify Workspace, provided that it's enabled in Xero. -2. Your general ledger reports will automatically convert to your home currency in Xero, leveraging the currency exchange rates defined in your Xero settings. It ensures everything aligns seamlessly. - -Now, for non-reimbursable expenses, things work slightly differently: - -1. Bank transactions will use the currency specified in your bank account in Xero, regardless of the currency used in Expensify. -2. If these currencies don't match, no worries! We apply a 1:1 exchange rate to make things smooth. To ensure a hassle-free experience, just ensure that the output currency in Expensify matches the currency specified in your Xero bank account. - -## Tax - -### Enabling Tax Tracking for Seamless Integration: - -To simplify tax tracking, enable it in your Xero configuration. This action will automatically bring all your Xero tax settings into Expensify, turning them into usable Taxes. - -### After connecting your Xero account with Expensify: - -1. Head to Settings. -2. Navigate to Workspaces within your specific group [Workspace Name]. -3. Click on Tax to view the taxes that have been imported from Xero. - -Now, here's where you can take control: - -1. Use the enable/disable button to choose which taxes your employees can apply to their expenses. Customize it to fit your needs. -2. You can set a default tax rate for expenses in your Workspace currency. Additionally, if you deal with foreign currency expenses, you have the option to set another default tax (including exempt) that will automatically apply to all new expenses in foreign currencies. - -This setup streamlines your tax management, making it effortless for your team to handle taxes on their expenses. - -## Export Invoices to Xero - -You can effortlessly export your invoices from Expensify to Xero and even attribute them to the right Customer. Plus, when you mark an invoice as paid in Expensify, the same status will smoothly transfer to Xero and vice versa, keeping your invoice tracking hassle-free. Let's dive in: - -### Setting up Invoice Export to Xero: - -1. Navigate to Settings. -2. Go to Workspaces within your designated group [Workspace Name]. -3. Click on Connections, then select Configuration. -4. Now, click on the Advanced tab. - -### Selecting Your Xero Invoice Collection Account: - -1. Scroll down until you find "Xero invoice collection account." You'll see a dropdown list of your available Accounts Receivable accounts imported from Xero. -2. Simply choose the account where you'd like your invoices to be exported. - -Pro Tip: If you don't see any accounts in the dropdown, try syncing your Xero connection. To do this, go back to the Connections page and hit "Sync Now." - -### Exporting an Invoice to Xero: - -Invoices will automatically make their way to Xero when they're in the Processing or Paid state. This ensures consistent tracking of unpaid and paid invoices. However, if you have Auto Sync disabled, you'll need to manually export your invoices along with your expense reports. Here's how: - -1. Head to your Reports page. -2. Use the filters to locate the invoices you want to export. -3. Select the invoices you wish to export. -4. Click Export to > Xero on the top right-hand side. - -### Matching Customers and Emails: - -When exporting to Xero, we match the recipient's email address with a customer record in Xero. So, make sure each customer in Xero has their email listed in their profile. -If we can't find a match, we'll create a new customer record in Xero. - -### Updating Invoice Status: - -1. When you mark an invoice as Paid in Expensify, this status will automatically reflect in Xero. -2. Similarly, if you mark an invoice as Paid in Xero, it will update automatically in Expensify. -3. The payment will be recorded in the Collection account you've chosen in your Advanced Settings Configuration. - -And that's it! You've successfully set up and managed your invoice exports to Xero, making your tracking smooth and efficient. - -{% include faq-begin.md %} - -## Will receipt images be exported to Xero? - -Yes! The receipt images will be exported to Xero. To see them in Xero click the 'paper' icon in the upper right corner of the expense details and view a PDF of the Expensify report including the receipt image. - -## How does Auto Sync work if your workspace was initially connected to Xero with Auto Sync disabled? - -You can safely switch it on without affecting existing reports that haven't been exported. - -## How does Auto Sync work if a report has already been exported to Xero and reimbursed through ACH or marked as reimbursed in Expensify? - -It will be automatically marked as paid in Xero during the next sync. You may either manually update by clicking Sync Now in the Connections tab or Expensify does this on your behalf overnight every day! - -## How does Auto Sync work if a report has been exported to Xero and marked as paid in Xero? - -It will be automatically marked as reimbursed in Expensify during the next sync. If you need it updated immediately please go to the Connections tab and click Sync Now or if you can wait just let Expensify do it for you overnight. - -## How does Auto Sync work if a report has been exported to Xero and marked as paid in Xero? - -Reports that haven't been exported to Xero won't be sent automatically. - - -{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/reports/Assign-report-approvers-to-specific-employees.md b/docs/articles/expensify-classic/reports/Assign-report-approvers-to-specific-employees.md index 5f79ea11378c..dbeca5a49f04 100644 --- a/docs/articles/expensify-classic/reports/Assign-report-approvers-to-specific-employees.md +++ b/docs/articles/expensify-classic/reports/Assign-report-approvers-to-specific-employees.md @@ -8,18 +8,51 @@ description: Create approval hierarchies for reports To assign different approvers for different employees, your workspace must use Advanced Approvals as the report approval workflow. {% include end-info.html %} -Rather than having one approver for all members of the workspace, you can use the Advanced Approvals workflow to assign different report approvers to specific employees. +To assign different approvers for different employees (instead of everyone submitting to the same person), your workspace must use Advanced Approval as the report approval workflow. To assign a report approver to a specific member of your workspace, -1. Hover over Settings, then click **Workspaces**. -2. Click the desired workspace name. -3. Click the **Members** tab on the left. -4. Click **Settings** next to the desired member. -5. Click the ā€œApproves toā€ dropdown and select the desired approver for the memberā€™s reports. -6. Click **Save**. - -You can also set -- Over-limit approval rules that require a secondary approver when a specific memberā€™s report expenses exceed a set limit. -- Approvers for expenses under a specific tag or category. + +1. Hover over Settings, then click Workspaces. +2. Click the desired workspace name. +3. Click the Members tab on the left. +4. Scroll down to the Approval Mode section and ensure that Advanced Approval is selected. +5. Locate the employee in the Workspace Members table, which shows each member (in the User column) and who their reports are approved by (in the Submits To column). +6. Click a userā€™s Submits To field to set or update their approver. + +## Add levels of approval +1. On the Workspaceā€™s Members tab, locate the employee in the Workspace Members table and click Settings. +2. Select the additional levels of approval you want to add for the employee: + - Role: Determines the employeeā€™s level of access to reports and workspace settings. For instructions on setting roles, visit our [workspace roles guide](https://help.expensify.com/articles/expensify-classic/workspaces/Change-member-workspace-roles). + - Approves To: Determines who must approve a report after this user has approved it. This creates an approval chain. When added, a note is visible in the Details column of the Workspace Members table. If blank, the user is a ā€œfinal approver.ā€ + - If Report Total is Over $X then Approves To: These two fields add an extra approver if the report total exceeds the set amount. When added, a note is visible in the Details column of the Workspace Members table. + +![Image of user approval settings]({{site.url}}/assets/images/Approves_To.png){:width="100%"} + +## Example + +Let's look at a basic workflow: + +| User | Submits To | Details | +|----------|----------|-----------------| +| Employee | Manager 1 | | +| Manager 1 | Finance Team | Approves to Manager 2
Approves to Finance Team over $1000.00 | +| Manager 2 | Finance Team | Approves to Finance Team | +| Finance Team | Finance Team | | + +Here is what this setup means: + +- Employee doesnā€™t approve any reports. When they submit a report, it goes to Manager 1 for approval. +- After Manager 1 approves a report from the Employee, the report goes to Manager 2 for approval unless the report is over $1,000. In that case, it goes directly to the Finance Team. +- When Manager 1 submits their own report, it goes to the Finance Team for approval. +- When Manager 2 approves a report or submits their own report, it goes to the Finance Team for approval. +- When the Finance Team submits a report, it is approved by the Finance Team. They are the final approver. + +Visit our How Complex Approval Workflows Work guide for more details. + +## FAQ + +Whatā€™s the difference between ā€œSubmits toā€ and ā€œApproves to?ā€ +- Submits to: The person you submit your reports to for 1st level approval. +- Approves to: The person you send reports that you've approved so they can complete an additional approval. This creates an approval chain. diff --git a/docs/articles/expensify-classic/workspaces/Configure-Reimbursement-Settings.md b/docs/articles/expensify-classic/workspaces/Configure-Reimbursement-Settings.md new file mode 100644 index 000000000000..aea84d338934 --- /dev/null +++ b/docs/articles/expensify-classic/workspaces/Configure-Reimbursement-Settings.md @@ -0,0 +1,55 @@ +--- +title: Configure Reimbursement Settings +description: Set up direct or indirect reimbursements for your workspace. +--- + + +Reimbursing employees in Expensify is quick, easy, and completely free. Let Expensify do the tedious work for you by taking advantage of the features available to automate employee reimbursement. + +# Configure a Workspace's Reimbursement Settings +There are a few ways to reimburse employees in Expensify. The option that's best suited for you and your business will depend on a few different factors: +- **Direct Reimbursement**: For companies with a business bank account located in the US that reimburse employees within the US. +- **Indirect Reimbursement**: This option is available to all members, and connecting a bank account to Expensify is not required. Indirect reimbursement indicates that all reports are reimbursed outside of Expensify. +- **Global Reimbursement**: If your companyā€™s business bank account is in the US, Canada, the UK, Europe, or Australia, you can reimburse employees directly in nearly any country worldwide. + +## Set Up Direct Reimbursement + +Once a [business bank account is connected to Expensify](https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/Business-Bank-Accounts-USD#how-to-add-a-verified-business-bank-account), a workspace admin can enable indirect reimbursement via **Settings > Workspaces > Workspace Name > Reimbursement > Direct**. + +#### Additional features available with Direct Reimbursement: +- **Select a default reimburser for the Workspace from the dropdown menu**: + - The default reimburser will receive notifications to reimburse reports in Expensify. + - Any workspace admin who also has access to the business bank account can be added as a default reimburser. +- **Set a default withdrawal account for the Workspace**: + - The default bank account is used to reimburse all of the reports submitted on the corresponding workspace. +- **Set a manual reimbursement threshold to automate reimbursement**: + - If the total of a given report is less than the threshold set, reimbursement will occur automatically upon final approval. + - If the total of a given report is more than the threshold, it will need to be reimbursed manually. + +## Set Up Indirect Reimbursement + +A Workspace admin can enable indirect reimbursement via **Settings > Workspaces > Workspace Name > Reimbursement > Indirect**. + +**Additional features under Reimbursement > Indirect:** +If you reimburse through a separate system or through payroll, Expensify can collect and export employee bank account details for you. Reach out to your Account Manager or Concierge to have the Reimbursement Details Export format added to the account. + +## Set Up Global Reimbursement + +Once [a business bank account is connected to Expensify](https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/Business-Bank-Accounts-USD#how-to-add-a-verified-business-bank-account), a workspace admin can enable indirect reimbursement via **Settings > Workspaces > Workspace Name > Reimbursement > Direct > Enable Global Reimbursements**. + +More information on setting up global reimbursements can be found **[here](https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/Global-Reimbursements)**. + +{% include faq-begin.md %} + +## How do I export employee bank account details once the Reimbursement Details Export format is added to my account? + +Employee bank account details can be exported from the Reports page by selecting the relevant Approved reports and then clicking **Export to > Reimbursement Details Export**. + +## Is it possible to change the name of a verified business bank account in Expensify? + +Bank account names can be updated by going to _**Settings > Accounts > Payments**_ and clicking the pencil icon next to the bank account name. + +## What is the benefit of setting a default reimburser? + +Setting a default reimburser on the Workspace ensures that all outstanding reports are reimbursed as this member will receive notifications alerting them to reports that require their action. +{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/workspaces/Expenses.md b/docs/articles/expensify-classic/workspaces/Expense-Settings.md similarity index 61% rename from docs/articles/expensify-classic/workspaces/Expenses.md rename to docs/articles/expensify-classic/workspaces/Expense-Settings.md index 4a2dc56c430f..c3a8ab31394d 100644 --- a/docs/articles/expensify-classic/workspaces/Expenses.md +++ b/docs/articles/expensify-classic/workspaces/Expense-Settings.md @@ -2,19 +2,29 @@ title: Expensify Workspace Expense Settings description: Expense Settings --- -# Overview +Expensify offers multiple ways to customize how expenses are created and managed at the workspace level. Whether youā€™re using an individual workspace or managing expenses in a group workspace, there are various expense settings you can customize. -Expensify offers multiple ways to customize how expenses are created in your workspace. In this doc, youā€™ll learn how to set up expense basics, distance expenses, and time expenses. +# Set up the expense settings on a workspace -Whether youā€™re flying solo with your Individual workspace or submitting with a team on your Group workspace, we have settings to support how you use Expensify. +You can manage the expense settings on a workspace under **Settings** > **Workspaces** > **Individual** or **Group** > [_Workspace Name_] > **Expenses**. From here you can customize the following expense-level settings: +- **Violations**: When enabled, employee expenses that fall outside of workspace preferences are flagged as violations. +- **Preferences**: Configure the reimbursable and billable settings for the expenses submitted to the corresponding workspace. +- **Distance**: This is where you can set the reimbursable mileage rates for yourself or your employees. +- **Time**: Set an hourly billable rate so members of the workspace can create time expenses for reimbursement. -# How to manage expense settings in your workspace +## Violations +A workspace admin can customize the following parameters at the expense level: +- **Max Expense Age (Days)** +- **Max Expense Amount** +- **Receipt Required Amount** -Letā€™s cover the expense basics first! In the following sections, weā€™ll go through each part of managing expense settings in your workspace. +If an expense is submitted that falls outside of those parameters, Expensify will automatically detect it as a violation and alert both the expense creator and reviewer that it needs to be corrected. -## Controlling cash expenses +More information on violations can be found [**here**](https://help.expensify.com/articles/expensify-classic/workspaces/Enable-and-set-up-expense-violations). -A cash expense is any expense created manually or by uploading a receipt for SmartScan; a cash expense does not mean the expense was paid for with cash. The other type of expense youā€™ll most commonly see is credit card expenses, which means the expenses imported from a credit card or bank connection. +## Preferences + +A cash expense is any expense created manually or by uploading a receipt for SmartScan; it does not mean the expense was paid for with cash. The other type of expense youā€™ll most commonly see is credit card expenses, which are expenses imported from a credit card or bank connection. There are four options for cash expenses: @@ -23,7 +33,7 @@ There are four options for cash expenses: - **Forced always reimbursable** - All cash expenses are forced to be reimbursable; they cannot be marked as non-reimbursable. - **Forced always non-reimbursable** - All cash expenses are forced to be non-reimbursable; they cannot be marked as reimbursable. -## Setting up billable expenses +### Billable expenses Billable expenses refer to expenses you or your employees incur that need to be re-billed to a specific client or vendor. @@ -37,7 +47,7 @@ Under Expense Basics, you can choose the setting that is best for you. If your Group workspace is connected to Xero, QuickBooks Online, NetSuite, or Sage Intacct, you can export billable expenses to be invoiced to customers. To set this up, go to the Coding tab in the connection configuration settings. -## Using eReceipts +### eReceipts eReceipts are full digital replacements of their paper equivalents for purchases of $75 or less. @@ -46,65 +56,57 @@ Click the toggle to your preferred configuration. - **Enabled** - All imported credit card expenses in US dollars of $75 or less will have eReceipts in the receipt image. - **Disabled** - No expenses will generate an eReceipt. -Note: _We will not generate an eReceipt for lodging expenses._ +Note: Expensify will not generate an eReceipt for lodging expenses. -## Securing receipt images +### Secure receipt images Whether youā€™re sharing your receipts with your accountant, having an auditor review exported expenses, or simply wanting to export to keep a hard copy for yourself, receipt visibility will be an essential consideration. Under _Public Receipt Visibility_, you can determine who can view receipts on your workspace. - **Enabled** means receipts are viewable by anyone with the URL. They don't need to be an Expensify user or a workspace member to view receipts. -- **Disabled** means receipts are viewable by users of Expensify, who would have access to view the receipt in the application. You must be an Expensify user with access to the report a receipt is on and logged into your account to view a receipt image via URL. +- **Disabled** means receipts are viewable by Expensify users, who would have access to view the receipt in the application. You must be an Expensify user with access to the report a receipt is on and logged into your account to view a receipt image via URL. -## Track mileage expenses +## Distance Expenses +How to set up distance expenses: +1. Select whether you want to capture _miles_ or _kilometers_, +2. Set the default category to be used on distance expenses, +3. Click **Add A Mileage Rate** to add as many rates as you need, +4. Set the reimbursable amount per mile or kilometer. -Whether using the Individual or Group workspace, you can create distance rates to capture expenses in miles or kilometers. +**Note:** If a rate is toggled off it is immediately disabled. This means that users are no longer able to select it when creating a new distance expense. If only one rate is available then that rate will be toggled on by default. -Preliminary setup steps include: +### Track tax on mileage expenses +If youā€™re tracking tax in Expensify you can also track tax on distance expenses. The first step is to enable tax in the workspace. You can do this by going to **Settings** > **Workspaces** > **Individual** or **Group** > [_Workspace Name_] > **Tax**. -1. Selecting whether you want to capture _miles_ or _kilometers_, -2. Setting the default category to be used on distance expenses, -3. Click **Add A Mileage Rate** to add as many rates as you need, -4. Set the reimbursable amount per mile or kilometer. +Once tax is enabled on a workspace level you will see a toggle to _Track Tax_ in the Distance section of the workspace settings. If tax is disabled on the workspace the Track Tax toggle will not display. -Note: _If a rate is toggled off it is immediately disabled. This means that users are no longer able to select it when creating a new distance expense. If only one rate is available then that rate will be toggled on by default._ +When Track Tax is enabled, you will need to enter additional information about the rates you have set. This includes the _Tax Reclaimable on_ and _Tax Rate_ fields. With that information, Expensify will work out the correct tax reclaim for each expense. -## Set an hourly rate +If you enable tax but donā€™t select a tax rate or enter a tax reclaimable amount, we will not calculate any tax amount for that rate. If, at any point, you switch the tax rate or enter a different reclaimable portion for an existing distance rate, the mileage rate will need to be re-selected on expenses for the tax amount to update according to the new values. -Using Expensify you can track time-based expenses to bill your clients at an hourly rate or allow employees to claim an hourly stipend. +**Note:** Expensify wonā€™t automatically track cumulative mileage. If you need to track cumulative mileage per employee, we recommend building a mileage report using our custom export formulas. -Click the toggle under the _Time_ section to enable the feature and set a default hourly rate. After that, you and your users will be able to create time-based expenses from the [**Expenses**](https://expensify.com/expenses) page of the account. +## Time Expenses -# Deep dives +Using Expensify you can track time-based expenses to bill your clients at an hourly rate or allow employees to claim an hourly stipend. -## What is Concierge Receipt Audit for the Control Plan? +Click the toggle under the _Time_ section to enable the feature and set a default hourly rate. Then, you and your users can create time-based expenses from the [**Expenses**](https://expensify.com/expenses) page of the account. -Concierge Receipt Audit is a real-time audit and compliance of receipts submitted by employees and workspace users. Concierge checks every receipt for accuracy and compliance, flagging any expenses that seem fishy before expense reports are even submitted for approval. All risky expenses are highlighted for manual review, leaving you with more control over and visibility into expenses. When a report is submitted and there are risky expenses on it, you will be immediately prompted to review the risky expenses and determine the next steps. +## Concierge Receipt Audit -**Why you should use Concierge Receipt Audit** +Concierge Receipt Audit is a real-time audit and compliance of receipts submitted by employees and workspace users. Concierge checks every receipt for accuracy and compliance, flagging any expenses that seem fishy before expense reports are even submitted for approval. All risky expenses are highlighted for manual review, leaving you with more control over and visibility into expenses. When a report is submitted and there are risky expenses on it, you will be immediately prompted to review the risky expenses and determine the next steps. +**Benefits of Concierge Receipt Audit** - To make sure you don't miss any risky expenses that need human oversight. - To avoid needing to manually review all your company receipts. - It's included at no extra cost with the [Control Plan](https://www.expensify.com/pricing). - Instead of paying someone to audit your company expenses or being concerned that your expenses might be audited by a government agency. -- It's easy to use! Concierge will alert you to the risky expense and present it to you in an easy-to-follow review tutorial. +- It's easy -- Concierge will alert you to the risky expense and present it to you in an easy-to-follow review tutorial. - In addition to the risky expense alerts, Expensify will include a Note with audit details on every report. -Note: _If a report has audit alerts on it, you'll need to Review the report and Accept the alerts before it can be approved._ - -## Tracking tax on mileage expenses - -If youā€™re tracking tax in Expensify you can also track tax on distance expenses. The first step is to enable tax in the workspace. You can do this by going to **Settings** > **Workspaces** > **Individual** or **Group** > [_Workspace Name_] > **Tax**. - -Once tax is enabled on a workspace level you will see a toggle to _Track Tax_ in the Distance section of the workspace settings. If tax is disabled on the workspace the Track Tax toggle will not display. - -When Track Tax is enabled you will need to enter additional information to the rates you have set, this includes the _Tax Reclaimable on_ and _Tax Rate_ fields. With that information, Expensify will work out the correct tax reclaim for each expense. - -If you enable tax but donā€™t select a tax rate or enter a tax reclaimable amount, we will not calculate any tax amount for that rate. If, at any point, you switch the tax rate or enter a different reclaimable portion for an existing distance rate, the mileage rate will need to be re-selected on expenses for the tax amount to update according to the new values. - -Note: _Expensify wonā€™t automatically track cumulative mileage. If you need to track cumulative mileage per employee, we recommend building a mileage report using our custom export formulas._ +**Note:** If a report has audit alerts on it, you'll need to Review the report and Accept the alerts before it can be approved. {% include faq-begin.md %} diff --git a/docs/articles/expensify-classic/workspaces/Invoicing.md b/docs/articles/expensify-classic/workspaces/Invoicing.md deleted file mode 100644 index f692f8f8d62e..000000000000 --- a/docs/articles/expensify-classic/workspaces/Invoicing.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Expensify Invoicing -description: Expensify Invoicing supports your business with unlimited invoice sending and receiving, payments, and status tracking in one single location. ---- -# Overview -Expensify Invoicing lets you create and send invoices, receive payments, and track the status of your invoices with Expensify, regardless of whether your customer has an Expensify account. Invoicing is included with all Expensify subscriptions, no matter the plan ā€” just pay the processing fee (2.9%) per transaction. - -# How to Set Up Expensify Invoicing - -**If you have a Group Workspace:** - -1. Log into your Expensify account from the web (not the mobile app) -3. Head to **Settings** > **Workspaces** > **Group** > [_Workspace Name_] > [**Invoices**](https://expensify.com/policy?param={"policyID":"20AB6A03EB9CE54D"}#invoices). - -**If you have an Individual Workspace:** - -1. Log into your Expensify account from the web (not the mobile app) -2. Head to **Settings** > **Workspaces** > **Individual** > [_Workspace Name_]> [**Invoices**](https://expensify.com/policy?param={"policyID":"BD5FB746D3B220D6"}#invoices). - -Here, youā€™ll be able to create a markup or add a payment account. Donā€™t forget you need a verified bank account to send or accept invoice payments via ACH. - -# Deep Dive - -To help your invoice stand out and look more professional, you can: - -- Add your logo -- Set your workspace currency to add default report-level fields -- Create additional report-level fields to display more details - -## Add a Logo - -From your Expensify account on the web (not the mobile app), go to **Settings** > **Account** > **Account Details**. Then click **Edit Photo** under _Your Details_ to upload your logo. - -## Set the Workspace Currency - -To set your currency, head to **Settings** > **Workspaces** > **Individual** or **Group** > **Reports**. This will add default report-level fields to your invoices. You can see these at the bottom of your [**Reports**](https://expensify.com/reports) page. - -Here are the default report-level fields based on common currencies: - -- GBP: VAT Number & Supplier Address (your company address) -- EUR: VAT Number & Supplier Address (your company address) -- AUD: ABN Number & Supplier Address (your company address) -- NZD: GST Number & Supplier Address (your company address) -- CAD: Business Number & Supplier Address (your company address) - -## Adding Additional Fields to Your Invoices - -In addition to the default report-level fields, you can create custom invoice fields. - -At the bottom of the same Reports page, under the _Add New Field_ section, youā€™ll have multiple options. - -- **Field Title**: This is the name of the field as displayed on your invoice. -- **Type**: You have the option to select a _text-based_ field, a _dropdown_ of selections, or a _date_ selector. -- **Report Type**: Select _Invoice_ to add the field to your invoices. - -Donā€™t forget to click the **Add** button once youā€™ve set your field parameters! - -For example, you may want to add a PO number, business address, website, or any other custom fields. - -_Please check the regulations in your local jurisdiction to ensure tax and business compliance._ - -## Removing Fields from Your Invoices - -If you want to delete a report field, click the red trashcan on the field in your **Workspace** > **Individual** or **Group** > **Report** settings to remove it from all future invoices. Unsent invoices will have a red **X** next to the report field, which you can click to remove before sending the invoice to your customer. diff --git a/docs/articles/expensify-classic/workspaces/Reimbursement.md b/docs/articles/expensify-classic/workspaces/Reimbursement.md deleted file mode 100644 index ed2384d12006..000000000000 --- a/docs/articles/expensify-classic/workspaces/Reimbursement.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Reimbursement -description: Enable reimbursement and reimburse expense reports ---- - - -# Overview -Reimbursement in Expensify is quick, easy, and completely free. Let Expensify do the tedious work for you by taking advantage of features to automate employee reimbursement. - -# How to Enable Reimbursement -There are several options for reimbursing employees in Expensify. The options available will depend on which country your business bank account is domiciled in. - -## Direct Reimbursement - -Direct reimbursement is available to companies who have a verified US bank account and are reimbursing employees within the US. To use direct reimbursement, you must have a US business bank account verified in Expensify. - -A Workspace admin can enable direct reimbursement via **Settings > Workspaces > Workspace Name > Reimbursement > Direct**. - -**Additional features under Reimbursement > Direct:** - - Select a **default reimburser** for the Workspace from the dropdown menu. The default reimburser is the person who will receive notifications to reimburse reports in Expensify. Youā€™ll be able to choose among all Workspace Admins who have access to the business bank account. - - Set a **default withdrawal account** for the Workspace. This will set a default bank account that report reimbursements are withdrawn from. - - Set a **manual reimbursement threshold** to automate reimbursement. Reports whose total falls under the manual reimbursement threshhold will be reimbursed automatocally upon final approval; reports whose total falls above the threshhold will need to be reimbursed manually by the default reimburser. - -Expensify also offers direct global reimbursement to some companies with verified bank accounts in USD, GBP, EUR and AUD who are reimbursing employees internationally. For more information about Global Reimbursement, see LINK - -## Indirect Reimbursement - -Indirect reimbursement is available to all companies in Expensify and no bank account is required. Indirect reimbursement indicates that the report will be reimbursed outside of Expensify. - -A Workspace admin can enanble indirect reimbursement via **Settings > Workspaces > Workspace Name > Reimbursement > Indirect**. - -**Additional features under Reimbursement > Indirect:** -If you reimburse through a seperate system or through payroll, Expensify can collect and export employee bank account details for you. Just reach out to your Account Manager or concierge@expensify.com for us to add the Reimbursement Details Export format to the account. - -{% include faq-begin.md %} - -## How do I export employee bank account details once the Reimbursement Details Export format is added to my account? - -Employee bank account details can be exported from the Reports page by selecting the relevant Approved reports and then clicking **Export to > Reimbursement Details Export**. - -## Is it possible to change the name of a verified business bank account in Expensify? - -Bank account names can be updated via **Settings > Accounts > Payments** and clicking the pencil icon next to the bank account name. - -## What is the benefit of setting a default reimburser? - -The main benefit of being defined as the "reimburser" in the Workspace settings is that this user will receive notifications on their Home page alerting them when reports need to be reimbursed. -{% include faq-end.md %} diff --git a/docs/articles/expensify-classic/workspaces/Currency.md b/docs/articles/expensify-classic/workspaces/Set-Currency.md similarity index 80% rename from docs/articles/expensify-classic/workspaces/Currency.md rename to docs/articles/expensify-classic/workspaces/Set-Currency.md index 77b5fbbb3ebc..4537f510b8b7 100644 --- a/docs/articles/expensify-classic/workspaces/Currency.md +++ b/docs/articles/expensify-classic/workspaces/Set-Currency.md @@ -1,18 +1,17 @@ --- -title: Report Currency -description: Understanding expense and report currency +title: Setting Up Report Currency +description: Define a currency in your workspace's settings --- # Overview As a workspace admin, you can choose a default currency for your employees' expense reports, and weā€™ll automatically convert any expenses into that currency. -Here are a few essential things to remember: - +Here are a few things to remember: - Currency settings for a workspace apply to all expenses under that workspace. If you need different default currencies for certain employees, creating separate workspaces and configuring the currency settings is best. - As an admin, the currency settings you establish in the workspace will take precedence over any currency settings individual users may have in their accounts. - Currency is a workspace-level setting, meaning the currency you set will determine the currency for all expenses submitted on that workspace. -# How to select the currency on a workspace +# Select the currency on a workspace ## As an admin on a group workspace @@ -28,11 +27,9 @@ Here are a few essential things to remember: Please note the currency setting on an individual workspace is overridden when you submit a report on a group workspace. -# Deep Dive - ## Conversion Rates -Using data from Open Exchange Rates, Expensify takes the average rate on the day the expense occurred to convert an expense from one currency to another. The conversion rate can vary depending on when the expense happened since the rate is determined after the market closes on that specific date. +Using data from Open Exchange Rates, Expensify converts expenses from one currency to another using the average rate on the day the expense occurred. The conversion rate can vary depending on when the expense occurred since it is determined after the market closes on that specific date. If the markets arenā€™t open on the day the expense takes place (i.e., on a Saturday), Expensify will use the daily average rate from the last available market day before the purchase took place. @@ -40,7 +37,7 @@ When an expense is logged for a future date, possibly to anticipate a purchase t ## Managing expenses for employees in several different countries -Suppose you have employees scattered across the globe who submit expense reports in various currencies. The best way to manage those expenses is to create separate group workspaces for each location or region where your employees are based. +If you have employees scattered across the globe who submit expense reports in various currencies, the best way to manage those expenses is to create separate group workspaces for each location or region where your employees are based. Then, set the default currency for that workspace to match the currency in which the employees are reimbursed. diff --git a/docs/articles/expensify-classic/workspaces/Set-Up-Invoicing.md b/docs/articles/expensify-classic/workspaces/Set-Up-Invoicing.md new file mode 100644 index 000000000000..8ec279da29a6 --- /dev/null +++ b/docs/articles/expensify-classic/workspaces/Set-Up-Invoicing.md @@ -0,0 +1,51 @@ +--- +title: Expensify Invoicing +description: Expensify Invoicing offers the ability to send, receive, and track the status of payments in one location. +--- +Invoicing lets you create and send invoices, receive payments, and track the status of your invoices, regardless of whether the customer has an Expensify account. This feature is included with all Expensify subscriptions, no matter the plan ā€” you'll just pay the processing fee (2.9%) per transaction. + +# Set Up Expensify Invoicing +Before using the invoice feature, you'll need to [connect a business bank account](https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/Business-Bank-Accounts-USD) to Expensify. + +Then, do the following: +1. Log into your Expensify account from the web (not the mobile app) +2. Head to _**Settings > Workspaces > Workspace Name > [Invoices](https://expensify.com/policy?param={"policyID":"20AB6A03EB9CE54D"}#invoices)**_. + +Here, youā€™ll be able to create a markup or add a payment account. + +## Add a Logo + +From your Expensify account on the web, go to _**Settings > Account > Account Details**_. Then click **Edit Photo** under _Your Details_ to upload your company logo. + +## Set the Workspace Currency + +To set the currency, head to _**Settings** > **Workspaces** > **Reports**_. This will add default report-level fields to your invoices. You can see these at the bottom of the [**Reports**](https://expensify.com/reports) page. + +Below are the default report-level fields based on common currencies: +- GBP: VAT Number & Supplier Address (your company address) +- EUR: VAT Number & Supplier Address (your company address) +- AUD: ABN Number & Supplier Address (your company address) +- NZD: GST Number & Supplier Address (your company address) +- CAD: Business Number & Supplier Address (your company address) + +## Adding Additional Fields to Invoices + +In addition to the default report-level fields, you can create custom invoice fields. + +At the bottom of the same Reports page, under the _Add New Field_ section, youā€™ll have multiple options. + +- **Field Title**: This is the name of the field as displayed on your invoice. +- **Type**: You have the option to select a _text-based_ field, a _dropdown_ of selections, or a _date_ selector. +- **Report Type**: Select _Invoice_ to add the field to your invoices. + +Donā€™t forget to click the **Add** button once youā€™ve set your field parameters! + +For example, you may want to add a PO number, business address, website, or any other custom fields. + +_Please check the regulations in your local jurisdiction to ensure tax and business compliance._ + +## Removing Fields from Invoices + +If you want to delete a report field, click the red trashcan on the field under _**Settings** > **Workspaces** > **Reports**_. This will remove that field from all future invoices. + +Unsent invoices will have a red **X** next to the report field, which you can click to remove before sending the invoice to your customer. diff --git a/docs/articles/new-expensify/connections/Netsuite/Configure-Netsuite.md b/docs/articles/new-expensify/connections/Netsuite/Configure-Netsuite.md new file mode 100644 index 000000000000..7ae0aa577468 --- /dev/null +++ b/docs/articles/new-expensify/connections/Netsuite/Configure-Netsuite.md @@ -0,0 +1,6 @@ +--- +title: Configure Netsuite +description: Coming soon +--- + +# Coming soon diff --git a/docs/articles/new-expensify/connections/Netsuite/Connect-to-NetSuite.md b/docs/articles/new-expensify/connections/Netsuite/Connect-to-NetSuite.md new file mode 100644 index 000000000000..7cf70cca5abc --- /dev/null +++ b/docs/articles/new-expensify/connections/Netsuite/Connect-to-NetSuite.md @@ -0,0 +1,375 @@ +--- +title: Connect to NetSuite +description: Integrate NetSuite with Expensify +order: 1 +--- + +# Connect to NetSuite + +## Overview +Expensifyā€™s integration with NetSuite allows you to sync data between the two systems. Before you start connecting Expensify with NetSuite, there are a few things to note: + +- You must use NetSuite administrator credentials to initiate the connection +- A Control Plan in Expensify is required to integrate with NetSuite +- Employees donā€™t need NetSuite access or a NetSuite license to submit expense reports and sync them to NetSuite +- Each NetSuite subsidiary must be connected to a separate Expensify workspace +- The workspace currency in Expensify must match the NetSuite subsidiary's default currency + +## Step 1: Install the Expensify Bundle in NetSuite +1. While logged into NetSuite as an administrator, go to **Customization > SuiteBundler > Search & Install Bundles**, then search for ā€œExpensifyā€ +2. Click on the Expensify Connect bundle (Bundle ID 283395) +3. Click **Install** +4. If you already have the Expensify Connect bundle installed, head to **Customization > SuiteBundler > Search & Install Bundles > List**, and update it to the latest version +5. Select "Show on Existing Custom Forms" for all available fields + +## Step 2: Enable Token-Based Authentication +1. In NetSuite, go to **Setup > Company > Enable Features > SuiteCloud > Manage Authentication** +2. Make sure ā€œToken Based Authenticationā€ is enabled +3. Click **Save** + + +## Step 3: Add Expensify Integration Role to a User +1. In NetSuite, head to **Lists > Employees**, and find the user who you would like to add the Expensify Integration role to. The user you select must at least have access to the permissions included in the Expensify Integration Role, and Admin access works too, but Admin access is not required. +2. Click **Edit > Access**, then find the Expensify Integration role in the dropdown and add it to the user +3. Click **Save** + +Remember that Tokens are linked to a User and a Role, not solely to a User. Itā€™s important to note that you cannot establish a connection with tokens using one role and then switch to another role afterward. Once youā€™ve initiated a connection with tokens, you must continue using the same token/user/role combination for all subsequent sync or export actions. + +## Step 4: Create Access Tokens +1. In NetSuite, enter ā€œpage: tokensā€ in the Global Search +2. Click **New Access Token** +3. Select Expensify as the application (this must be the original Expensify integration from the bundle) +4. Select the role Expensify Integration +5. Click **Save** +6. Copy and paste the token and token ID to a saved location on your computer (this is the only time you will see these details) + +## Step 5: Confirm Expense Reports are enabled in NetSuite +Expense Reports must be enabled in order to use Expensifyā€™s integration with NetSuite. + +1. In NetSuite, go to **Setup > Company > Enable Features > Employees** +2. Confirm the checkbox next to "Expense Reports" is checked +3. If not, click the checkbox and then click **Save** to enable Expense Reports + +## Step 6: Confirm Expense Categories are set up in NetSuite +Once Expense Reports are enabled, Expense Categories can be set up in NetSuite. Expense Categories are synced to Expensify as Categories. Each Expense Category is an alias mapped to a General Ledger account so that employees can more easily categorize expenses. + +1. In NetSuite, go to **Setup > Accounting > Expense Categories** (a list of Expense Categories should show) +2. If no Expense Categories are visible, click **New** to create new ones + +## Step 7: Confirm Journal Entry Transaction Forms are Configured Properly +1. In NetSuite, go to **Customization > Forms > Transaction Forms** +2. Click **Customize** or **Edit** next to the Standard Journal Entry form +3. Click **Screen Fields > Main**. Please verify the ā€œCreated Fromā€ label has ā€œShowā€ checked and the "Display Type" is set to "Normal" +4. Click the sub-header **Lines** and verify that the ā€œShowā€ column for ā€œReceipt URLā€ is checked +5. Go to **Customization > Forms > Transaction Forms** and ensure that all other transaction forms with the journal type have this same configuration + +## Step 8: Confirm Expense Report Transaction Forms are Configured Properly +1. In NetSuite, go to **Customization > Forms > Transaction Forms** +2. Click **Customize** or **Edit** next to the Standard Expense Report form, then click **Screen Fields > Main** +3. Verify the ā€œCreated Fromā€ label has ā€œShowā€ checked and the "Display Type" is set to "Normal" +4. Click the second sub-header, **Expenses**, and verify that the "Show" column for "Receipt URL" is checked +5. Go to **Customization > Forms > Transaction Forms** and ensure that all other transaction forms with the expense report type have this same configuration + +## Step 9: Confirm Vendor Bill Transactions Forms are Configured Properly +1. In NetSuite, go to **Customization > Forms > Transaction Forms** +2. Click **Customize** or **Edit** next to your preferred Vendor Bill form +3. Click **Screen Fields > Main** and verify that the ā€œCreated Fromā€ label has ā€œShowā€ checked and that Departments, Classes, and Locations have the ā€œShowā€ label unchecked +4. Under the **Expenses** sub-header (make sure to click the ā€œExpensesā€ sub-header at the very bottom and not ā€œExpenses & Itemsā€), ensure ā€œShowā€ is checked for Receipt URL, Department, Location, and Class +5. Go to **Customization > Forms > Transaction Forms** and ensure that all other transaction forms with the vendor bill type have this same configuration + +## Step 10: Confirm Vendor Credit Transactions Forms are Configured Properly +1. In NetSuite, go to **Customization > Forms > Transaction Forms** +2. Click **Customize** or **Edit** next to your preferred Vendor Credit form, then click **Screen Fields > Main** and verify that the ā€œCreated Fromā€ label has ā€œShowā€ checked and that Departments, Classes, and Locations have the ā€œShowā€ label unchecked +3. Under the **Expenses** sub-header (make sure to click the ā€œExpensesā€ sub-header at the very bottom and not ā€œExpenses & Itemsā€), ensure ā€œShowā€ is checked for Receipt URL, Department, Location, and Class +4. Go to **Customization > Forms > Transaction Forms** and ensure that all other transaction forms with the vendor credit type have this same configuration + +## Step 11: Set up Tax Groups (only applicable if tracking taxes) +Expensify imports NetSuite Tax Groups (not Tax Codes), which you can find in NetSuite under **Setup > Accounting > Tax Groups**. + +Tax Groups are an alias for Tax Codes in NetSuite and can contain one or more Tax Codes (Please note: for UK and Ireland subsidiaries, please ensure your Tax Groups do not have more than one Tax Code). We recommend naming Tax Groups so your employees can easily understand them, as the name and rate will be displayed in Expensify. + +To set up Tax Groups in NetSuite: + +1. Go to **Setup > Accounting > Tax Groups** +2. Click **New** +3. Select the country for your Tax Group +4. Enter the Tax Name (this is what employees will see in Expensify) +5. Select the subsidiary for this Tax Group +6. Select the Tax Code from the table you wish to include in this Tax Group +7. Click **Add** +8. Click **Save** +9. Create one NetSuite Tax Group for each tax rate you want to show in Expensify + +Ensure Tax Groups can be applied to expenses by going to **Setup > Accounting > Set Up Taxes** and setting the Tax Code Lists Include preference to ā€œTax Groups And Tax Codesā€ or ā€œTax Groups Only.ā€ If this field does not display, itā€™s not needed for that specific country. + +## Step 12: Connect Expensify to NetSuite +1. Log into Expensify as a workspace admin +2. Click your profile image or icon in the bottom left menu +3. Scroll down and click **Workspaces** in the left menu +4. Select the workspace you want to connect to NetSuite +5. Click **More features** in the left menu +6. Scroll down to the Integrate section and enable Accounting +7. Click **Accounting** in the left menu +8. Click **Set up** next to NetSuite +9. Click **Next** until you reach setup step 5 (If you followed the instructions above, then the first four setup steps will be complete) +10. On setup step 5, enter your NetSuite Account ID, Token ID, and Token Secret (the NetSuite Account ID can be found in NetSuite by going to **Setup > Integration > Web Services Preferences**) +11. Click **Confirm** to complete the setup + +After completing the setup, the NetSuite connection will sync. It can take 1-2 minutes to sync with NetSuite. + +Once connected, all reports exported from Expensify will be generated in NetSuite using SOAP Web Services (the term NetSuite employs when records are created through the integration). + +## FAQ +### What type of Expensify plan is required to connect to NetSuite? +You need a Control workspace to integrate with NetSuite. If you have a Collect workspace, you will need to upgrade to Control. + +### Page size +Make sure your page size is set to 1000 in NetSuite for importing your customers and vendors. Go to **Setup > Integration > Web Services Preferences** and search **Page Size** to determine your page size. + + +# Configure NetSuite integration +## Step 1: Configure import settings + +The following section will help you determine how data will be imported from NetSuite into Expensify. To change your import settings, navigate to the Accounting settings for your workspace, then click **Import** under the NetSuite connection. + +### Expense Categories +Your NetSuite Expense Categories are automatically imported into Expensify as categories. This cannot be amended, and any new categories you'd like to add must be added as Expense Categories in NetSuite. + +Once imported, you can turn specific Categories on or off under **Settings > Workspaces > [Workspace Name] > Categories**. + +### Departments, Classes, and Locations +The NetSuite integration allows you to import departments, classes, and locations from NetSuite into Expensify as Tags, Report Fields, or using the NetSuite Employee Default. + +- **NetSuite Employee Default:** If default Department, Class, and Locations have been configured on NetSuite employee records, then you can choose to have the NetSuite employee default applied upon export from Expensify to NetSuite. With this selection, employees will not make a selection in Expensify. +- **Tags:** Employees can select the department, class, or location on each individual expense. If the employee's NetSuite employee record has a default value, then each expense will be defaulted to that tag upon creation, with the option for the employee to select a different value on each expense. +- **Report Fields:** Employees can select one department/class/location for each expense report. + + +New departments, classes, and locations must be added in NetSuite. Once imported, you can turn specific tags on or off under **Settings > Workspaces > [Workspace Name] > Tags**. You can turn specific report fields on or off under **Settings > Workspaces > [Workspace Name] > Report Fields**. + +### Customers and Projects +The NetSuite integration allows you to import customers and projects into Expensify as Tags or Report Fields. + +- **Tags:** Employees can select the customer or project on each individual expense. +- **Report Fields:** Employees can select one department/class/location for each expense report. + +New customers and projects must be added in NetSuite. Once imported, you can turn specific tags on or off under **Settings > Workspaces > [Workspace Name] > Tags**. You can turn specific report fields on or off under **Settings > Workspaces > [Workspace Name] > Report Fields**. + +When importing customers or projects, you can also choose to enable **Cross-subsidiary customers/projects**. This setting allows you to import Customers and Projects across all NetSuite subsidiaries to a single Expensify workspace. This setting requires you to enable ā€œIntercompany Time and Expenseā€ in NetSuite. To enable that feature in NetSuite, go to **Setup > Company > Setup Tasks: Enable Features > Advanced Features**. + +### Tax +The NetSuite integration allows users to apply a tax rate and amount to each expense for non-US NetSuite subsidiaries. To do this, import Tax Groups from NetSuite: + +1. In NetSuite, head to **Setup > Accounting > Tax Groups** +2. Once imported, go to the NetSuite connection configuration page in Expensify (under **Settings > Workspaces > [Workspace Name] > Accounting > NetSuite > Import**) +3. Enable Tax +4. Go back to the Accounting screen, click the three dots next to NetSuite, and click **Sync now** +5. All Tax Groups for the connected NetSuite subsidiary will be imported to Expensify as taxes. +6. After syncing, go to **Settings > Workspace > [Workspace Name] > Tax** to see the tax groups imported from NetSuite + +### Custom Segments +You can import one or more Custom Segments from NetSuite for selection in Expensify. To add a Custom Segment to your Expensify workspace: + +1. Go to **Settings > Workspaces > [Workspace Name] > Accounting** +2. Click **Import** under NetSuite +3. Click **Custom segments/records** +4. Click **Add custom segment/record** + +From there, you'll walk through a simple setup wizard. You can find detailed instructions below for each setup step. + +1. In Step 1, you'll select whether you'd like to import a custom segment or a custom record. For a Custom Segment, continue. We have separate instructions for [Custom Records](link) and [Custom Lists](link). +2. **Segment Name** + a. Log into NetSuite as an administrator + b. Go to **Customization > Lists, Records, & Fields > Custom Segments** + c. Youā€™ll see the Segment Name on the Custom Segments page +3. Internal ID + a. Ensure you have internal IDs enabled in NetSuite under **Home > Set Preferences** + b. Navigate back to the **Custom Segments** page + c. Click the **Custom Record Type** link + d. Youā€™ll see the Internal ID on the Custom Record Type page +4. **Script ID/Field ID** + a. If configuring Custom Segments as Report Fields, use the Field ID on the Transactions tab (under **Custom Segments > Transactions**). If no Field ID is shown, use the unified ID (just called ā€œIDā€ right below the ā€œLabelā€). + b. If configuring Custom Segments as Tags, use the Field ID on the Transaction Columns tab (under **Custom Segments > Transaction Columns**). If no Field ID is shown, use the unified ID (just called ā€œIDā€ right below the ā€œLabelā€). + c. Note that as of 2019.1, any new custom segments that you create automatically use the unified ID, and the "Use as Field ID" box is not visible. If you are editing a custom segment definition that was created before 2019.1, the "Use as Field ID" box is available. To use a unified ID for the entire custom segment definition, check the "Use as Field ID" box. When the box is checked, no field ID fields or columns are shown on the Application & Sourcing subtabs because one ID is used for all fields. +5. Select whether you'd like to import the custom segment as Tags or Report Fields +6. Finally, confirm that all the details look correct + +**Note:** Donā€™t use the ā€œFiltered byā€ feature available for Custom Segments. Expensify canā€™t make these dependent on other fields. If you do have a filter selected, we suggest switching that filter in NetSuite to ā€œSubsidiaryā€ and enabling all subsidiaries to ensure you donā€™t receive any errors upon exporting reports. + +### Custom Records +You can import one or more Custom Records from NetSuite for selection in Expensify. To add a Custom Record to your Expensify workspace: + +1. Go to **Settings > Workspaces > [Workspace Name] > Accounting** +2. Click **Import** under NetSuite +3. Click **Custom segments/records** +4. Click **Add custom segment/record** + +From there, you'll walk through a simple setup wizard. You can find detailed instructions below for each setup step. + +1. In Step 1, you'll select whether you'd like to import a custom segment or a custom record. For a Custom Record, continue. We have separate instructions for [Custom Segments](link) and [Custom Lists](link). +2. **Segment Name** + a. Log into NetSuite as an administrator + b. Go to **Customization > Lists, Records, & Fields > Custom Segments** + c. Youā€™ll see the Custom Record Name on the Custom Segments page +3. **Internal ID** + a. Make sure you have Internal IDs enabled in NetSuite under **Home > Set Preferences** + b. Navigate back to the **Custom Segment** page + c. Click the **Custom Record Type** hyperlink + d. Youā€™ll see the Internal ID on the Custom Record Type page +4. **Transaction Column ID** + a. If configuring Custom Records as Report Fields, use the Field ID on the Transactions tab (under **Custom Segments > Transactions**). + b. If configuring Custom Records as Tags, use the Field ID on the Transaction Columns tab (under **Custom Segments > Transaction Columns**). +5. Select whether you'd like to import the custom record as Tags or Report Fields +6. Finally, confirm that all the details look correct + +### Custom Lists +You can import one or more Custom Lists from NetSuite for selection in Expensify. To add a Custom List to your Expensify workspace: + +1. Go to **Settings > Workspaces > [Workspace Name] > Accounting** +2. Click **Import** under NetSuite +3. Click **Custom list** +4. Click **Add custom list** + +From there, you'll walk through a simple setup wizard. You can find detailed instructions below for each setup step. + +1. In Step 1, you'll select which Custom List you'd like to import from a pre-populated list +2. **Transaction Line Field ID** + a. Log into NetSuite as an admin + b. Search **ā€œTransaction Line Fieldsā€** in the global search + c. Click into the desired Custom List + d. You'll find the transaction Line Field ID along the left-hand side of the page +3. Select whether you'd like to import the custom list as Tags or Report Fields +4. Finally, confirm that all the details look correct + +From there, you should see the values for the Custom Lists under the Tag or Report Field settings in Expensify. +## Step 2: Configure export settings +There are numerous options for exporting data from Expensify to NetSuite. To access these settings, head to **Settings > Workspaces > [Workspace name] > Accounting** and click **Export** under NetSuite. + +### Preferred Exporter +Any workspace admin can export reports to NetSuite. For auto-export, Concierge will export on behalf of the preferred exporter. The preferred exporter will also be notified of any expense reports that fail to export to NetSuite due to an error. + +### Date +You can choose which date to use for the records created in NetSuite. There are three date options: + +1. **Date of last expense:** This will use the date of the previous expense on the report +2. **Submitted date:** The date the employee submitted the report +3. **Exported date:** The date you export the report to NetSuite + +### Export out-of-pocket expenses as +**Expense Reports** +Out-of-pocket expenses will be exported to NetSuite as expense reports, which will be posted to the payables account designated in NetSuite. + +**Vendor Bills** +Out-of-pocket expenses will be exported to NetSuite as vendor bills. Each report will be posted as payable to the vendor associated with the employee who submitted the report. You can also set an approval level in NetSuite for vendor bills. + +**Journal Entries** +Out-of-pocket expenses will be exported to NetSuite as journal entries. All the transactions will be posted to the payable account specified in the workspace. You can also set an approval level in NetSuite for the journal entries. + +Note: By default, journal entry forms do not contain a customer column, so it is not possible to export customers or projects with this export option. Also, The credit line and header level classifications are pulled from the employee record. + +### Export company card expenses as +**Expense Reports** +To export company card expenses as expense reports, you will need to configure your default corporate cards in NetSuite. To do this, you must select the correct card on the NetSuite employee records (for individual accounts) or the subsidiary record (If you use a non-One World account, the default is found in your accounting preferences). + +To update your expense report transaction form in NetSuite: + +1. Go to **Customization > Forms > Transaction Forms** +2. Click **Edit** next to the preferred expense report form +3. Go to the **Screen Fields > Main** tab +4. Check ā€œShowā€ for "Account for Corporate Card Expenses" +5. Go to the **Screen Fields > Expenses** tab +6. Check ā€œShowā€ for "Corporate Card" + +You can also select the default account on your employee record to use individual corporate cards for each employee. Make sure you add this field to your employee entity form in NetSuite. If you have multiple cards assigned to a single employee, you cannot export to each account. You can only have a single default per employee record. + +**Vendor Bills** +Company card expenses will be posted as a vendor bill payable to the default vendor specified in your workspace Accounting settings. You can also set an approval level in NetSuite for the bills. + + +**Journal Entries** +Company Card expenses will be posted to the Journal Entries posting account selected in your workspace Accounting settings. + +Important Notes: + +- Expensify Card expenses will always export as Journal Entries, even if you have Expense Reports or Vendor Bills configured for non-reimbursable expenses on the Export tab +- Journal entry forms do not contain a customer column, so it is not possible to export customers or projects with this export option +- The credit line and header level classifications are pulled from the employee record + +### Export invoices to +Select the Accounts Receivable account where you want your Invoice reports to export. In NetSuite, the invoices are linked to the customer, corresponding to the email address where the invoice was sent. + +### Export foreign currency amount +Enabling this feature allows you to send the original amount of the expense rather than the converted total when exporting to NetSuite. This option is only available when exporting out-of-pocket expenses as Expense Reports. + +### Export to next open period +When this feature is enabled and you try exporting an expense report to a closed NetSuite period, we will automatically export to the next open period instead of returning an error. + + +## Step 3: Configure advanced settings +To access the advanced settings of the NetSuite integration, head to **Settings > Workspaces > [Workspace name] > Accounting** and click **Advanced** under NetSuite. + + +Letā€™s review the different advanced settings and how they interact with the integration. + +### Auto-sync +We strongly recommend enabling auto-sync to ensure that the information in NetSuite and Expensify is always in sync. The following will occur when auto-sync is enabled: + +**Daily sync from NetSuite to Expensify:** Once a day, Expensify will sync any changes from NetSuite into Expensify. This includes any new, updated, or removed departments/classes/locations/projects/etc. + +**Auto-export:** When an expense report reaches its final state in Expensify, it will be automatically exported to NetSuite. The final state will either be reimbursement (if you reimburse members through Expensify) or final approval (if you reimburse members outside of Expensify). + +**Reimbursement-sync:** If Sync Reimbursed Reports (more details below) is enabled, then we will sync the reimbursement status of reports between Expensify and NetSuite. + +### Sync reimbursed reports +When Sync reimbursed reports is enabled, the reimbursement status will be synced between Expensify and NetSuite. + +**If you reimburse members through Expensify:** Reimbursing an expense report will trigger auto-export to NetSuite. When the expense report is exported to NetSuite, a corresponding bill payment will also be created in NetSuite. + +**If you reimburse members outside of Expensify:** Expense reports will be exported to NetSuite at time of final approval. After you mark the report as paid in NetSuite, the reimbursed status will be synced back to Expensify the next time the integration syncs. + +To ensure this feature works properly for expense reports, make sure that the reimbursement account you choose within the settings matches the default account for Bill Payments in NetSuite. When exporting invoices, once marked as Paid, the payment is marked against the account selected after enabling the Collection Account setting. + +### Invite employees and set approvals +Enabling this feature will invite all employees from the connected NetSuite subsidiary to your Expensify workspace. Once imported, Expensify will send them an email letting them know theyā€™ve been added to a workspace. + +In addition to inviting employees, this feature enables a custom set of approval workflow options, which you can manage in Expensify Classic: + +- **Basic Approval:** A single level of approval, where all users submit directly to a Final Approver. The Final Approver defaults to the workspace owner but can be edited on the people page. +- **Manager Approval (default):** Two levels of approval route reports first to an employeeā€™s NetSuite expense approver or supervisor, and second to a workspace-wide Final Approver. By NetSuite convention, Expensify will map to the supervisor if no expense approver exists. The Final Approver defaults to the workspace owner but can be edited on the people page. +- **Configure Manually:** Employees will be imported, but all levels of approval must be manually configured on the workspaceā€™s People settings page. If you enable this setting, itā€™s recommended you review the newly imported employees and managers on the **Settings > Workspaces > Group > [Workspace Name] > People** page. + +### Auto-create employees/vendors +With this feature enabled, Expensify will automatically create a new employee or vendor in NetSuite (if one doesnā€™t already exist) using the name and email of the report submitter. + +### Enable newly imported categories +With this feature enabled, anytime a new Expense Category is created in NetSuite, it will be imported into Expensify as an enabled category. If the feature is disabled, then new Expense Categories will be imported into Expensify as disabled. + +### Setting approval levels +You can set the NetSuite approval level for each different export type: + +- **Expense report approval level:** Choose from "NetSuite default preference," ā€œOnly supervisor approved,ā€ ā€œOnly accounting approved,ā€ or ā€œSupervisor and accounting approved.ā€ +- **Vendor bill approval level and Journal entry approval level:** Choose from "NetSuite default preference," ā€œPending approval,ā€ or ā€œApproved for posting.ā€ + +If you have Approval Routing selected in your accounting preference, this will override the selections in Expensify. If you do not wish to use Approval Routing in NetSuite, go to **Setup > Accounting > Accounting Preferences > Approval Routing** and ensure Vendor Bills and Journal Entries are not selected. + +### Custom form ID +By default, Expensify will create entries using the preferred transaction form set in NetSuite. Alternatively, you have the option to designate a specific transaction form to be used. + + + +## FAQ + +### How does Auto-sync work with reimbursed reports? +If a report is reimbursed via ACH or marked as reimbursed in Expensify and then exported to NetSuite, the report is automatically marked as paid in NetSuite. + +If a report is exported to NetSuite, then marked as paid in NetSuite, the report will automatically be marked as reimbursed in Expensify during the next sync. + +### Will enabling auto-sync affect existing approved and reimbursed reports? +Auto-sync will only export newly approved reports to NetSuite. Any reports that were approved or reimbursed before enabling auto-sync will need to be manually exported in order to sync them to NetSuite. + + +### When using multi-currency features in NetSuite, can expenses be exported with any currency? +When using multi-currency features with NetSuite, remember these points: + +**Employee/Vendor currency:** The currency set for a NetSuite vendor or employee record must match the subsidiary currency for whichever subsidiary you export that user's reports to. A currency mismatch will cause export errors. +**Bank Account Currency:** When synchronizing bill payments, your bank accountā€™s currency must match the subsidiaryā€™s currency. Failure to do so will result in an ā€œInvalid Accountā€ error. diff --git a/docs/articles/new-expensify/connections/Netsuite/Netsuite-Troubleshooting.md b/docs/articles/new-expensify/connections/Netsuite/Netsuite-Troubleshooting.md new file mode 100644 index 000000000000..2ac1aaadbef4 --- /dev/null +++ b/docs/articles/new-expensify/connections/Netsuite/Netsuite-Troubleshooting.md @@ -0,0 +1,6 @@ +--- +title: Netsuite Troubleshooting +description: Coming soon +--- + +# Coming soon diff --git a/docs/articles/new-expensify/connections/Quickbooks-Online/Configure-Quickbooks-Online.md b/docs/articles/new-expensify/connections/Quickbooks-Online/Configure-Quickbooks-Online.md new file mode 100644 index 000000000000..db050e5be312 --- /dev/null +++ b/docs/articles/new-expensify/connections/Quickbooks-Online/Configure-Quickbooks-Online.md @@ -0,0 +1,6 @@ +--- +title: Configure Quickbooks Online +description: Coming soon +--- + +# Coming soon diff --git a/docs/articles/new-expensify/connections/Set-up-QuickBooks-Online-connection.md b/docs/articles/new-expensify/connections/Quickbooks-Online/Connect-to-QuickBooks-Online.md similarity index 97% rename from docs/articles/new-expensify/connections/Set-up-QuickBooks-Online-connection.md rename to docs/articles/new-expensify/connections/Quickbooks-Online/Connect-to-QuickBooks-Online.md index 155512866a8f..60fdbe94b33b 100644 --- a/docs/articles/new-expensify/connections/Set-up-QuickBooks-Online-connection.md +++ b/docs/articles/new-expensify/connections/Quickbooks-Online/Connect-to-QuickBooks-Online.md @@ -1,8 +1,8 @@ --- -title: Set up QuickBooks Online connection +title: Connect to QuickBooks Online description: Integrate QuickBooks Online with Expensify +order: 1 --- -
{% include info.html %} To use the QuickBooks Online connection, you must have a QuickBooks Online account and an Expensify Collect plan. The QuickBooks Self-employed subscription is not supported. @@ -52,6 +52,12 @@ Log in to QuickBooks Online and ensure all of your employees are setup as either ![The QuickBooks Online Connect button]({{site.url}}/assets/images/ExpensifyHelp-QBO-3.png){:width="100%"} +![The QuickBooks Online Connect Accounting button]({{site.url}}/assets/images/ExpensifyHelp-QBO-4.png){:width="100%"} + +![The QuickBooks Online Connect Connect button]({{site.url}}/assets/images/ExpensifyHelp-QBO-5.png){:width="100%"} + + + # Step 3: Configure import settings The following steps help you determine how data will be imported from QuickBooks Online to Expensify. @@ -128,5 +134,3 @@ This may occur if you incorrectly enter your QuickBooks Online login information 3. Enter your Intuit login details (the login information you use for QuickBooks Online) to establish the connection. {% include faq-end.md %} - -
diff --git a/docs/articles/new-expensify/connections/Quickbooks-Online/Quickbooks-Online-Troubleshooting.md b/docs/articles/new-expensify/connections/Quickbooks-Online/Quickbooks-Online-Troubleshooting.md new file mode 100644 index 000000000000..5256459d6f9a --- /dev/null +++ b/docs/articles/new-expensify/connections/Quickbooks-Online/Quickbooks-Online-Troubleshooting.md @@ -0,0 +1,6 @@ +--- +title: Quickbooks Online Troubleshooting +description: Coming soon +--- + +# Coming soon diff --git a/docs/articles/new-expensify/connections/Sage-Intacct/Configure-Sage-Intacct.md b/docs/articles/new-expensify/connections/Sage-Intacct/Configure-Sage-Intacct.md new file mode 100644 index 000000000000..c5e549ff74d1 --- /dev/null +++ b/docs/articles/new-expensify/connections/Sage-Intacct/Configure-Sage-Intacct.md @@ -0,0 +1,6 @@ +--- +title: Configure Sage Intacct +description: Coming soon +--- + +# Coming soon diff --git a/docs/articles/new-expensify/connections/Sage-Intacct/Connect-to-Sage-Intacct.md b/docs/articles/new-expensify/connections/Sage-Intacct/Connect-to-Sage-Intacct.md new file mode 100644 index 000000000000..35a009ae8d4a --- /dev/null +++ b/docs/articles/new-expensify/connections/Sage-Intacct/Connect-to-Sage-Intacct.md @@ -0,0 +1,317 @@ +--- +title: Connect to Sage Intacct +description: Integrate Sage Intacct with Expensify +order: 1 +--- + +# Connect to Sage Intacct + +## Overview +Expensifyā€™s integration with Sage Intacct allows you to connect using either role-based permissions or user-based permissions and exporting either expense reports or vendor bills. + +Checklist of items to complete: + +1. Create a web services user and configure permissions +1. Enable the T&E module (only required if exporting out-of-pocket expenses as Expense Reports) +1. Set up Employees in Sage Intacct (only required if exporting expenses as Expense Reports) +1. Set up Expense Types (only required if exporting expenses as Expense Reports) +1. Enable Customization Services +1. Download the Expensify Package +1. Upload the Expensify Package in Sage Intacct +1. Add web services authorization +1. Enter credentials and connect Expensify and Sage Intacct +1. Configure integration sync options + +## Step 1a: Create a web services user (Connecting with User-based permissions) +Note: If the steps in this section look different in your Sage Intacct instance, you likely use role-based permissions. If thatā€™s the case, follow the steps [here]. + +To connect to Sage Intacct, youā€™ll need to create a special web services user (please note that Sage Intacct does not charge extra for web services users). + +1. Go to **Company > Web Services Users > New**. +2. Configure the user as outlined below: + - **User ID**: ā€œxmlgateway_expensifyā€ + - **Last Name and First Name:** ā€œExpensifyā€ + - **Email Address:** Your shared accounting team email + - **User Type:** ā€œBusinessā€ + - **Admin Privileges:** ā€œFullā€ + - **Status:** ā€œActiveā€ + +Next, configure correct permissions for the new web services user. + +1. Go to the subscription link for this user in the user list +1. Click on the checkbox next to the Application/Module +1. Click **Permissions** + +These are the permissions required for this integration when exporting out-of-pocket expenses as vendor bills: + +- **Administration (All)** +- **Company (Read-only)** +- **Cash Management (All)** +- **General Ledger (All)** +- **Time & Expense (All)** - Only required if exporting out-of-pocket expenses as expense reports +- **Projects (Read-only)** - Only required if using Projects or Customers +- **Accounts Payable (All)** - Only required if exporting any expenses expenses as vendor bills + +## Step 1b: Create a web services user (Connecting with Role-based permissions) +Note: If the steps in this section look different in your Sage Intacct instance, you likely use role-based permissions. If thatā€™s the case, follow the steps [here]. + +**First, you'll need to create the new role:** + +1. In Sage Intacct, click **Company**, then click on the **+ button** next to Roles +1. Name the role "Expensify", then click **Save** +1. Go to **Roles > Subscriptions** and find the ā€œExpensifyā€ role you just created +1. Configure correct permissions for this role by clicking the checkbox and then clicking on the Permissions hyperlink. These are the permissions required for this integration when exporting out-of-pocket expenses as vendor bills: + - **Administration (All)** + - **Company (Read-only)** + - **Cash Management (All)** + - **General Ledger (All)** + - **Time & Expense (All)** - Only required if exporting out-of-pocket expenses as expense reports + - **Projects (Read-only)** - Only required if using Projects or Customers + - **Accounts Payable (All)** - Only required if exporting any expenses expenses as vendor bills + +**Next, youā€™ll create a web services user and assign the role to that user:** + +1. Go to **Company > Web Services Users > New** +2. Set up the user as described below: + - **User ID:** ā€œxmlgateway_expensifyā€ + - **Last name and First name:** ā€œExpensifyā€ + - **Email address:** your shared accounting team email + - **User type:** ā€œBusinessā€ + - **Admin privileges:** ā€œFullā€ + - **Status:** ā€œActiveā€ +3. Assign the role to that user: click the **+ button**, then select the ā€œExpensifyā€ role and click **Save** + + +## Step 2: Enable and configure the Time & Expenses Module +**Note: This step is only required if exporting out-of-pocket expenses from Expensify to Sage Intacct as Expense Reports.** + +Enabling the T&E module is a paid subscription through Sage Intacct and the T&E module is often included in your Sage Intacct instance. For information on the costs of enabling this module, please contact your Sage Intacct account manager. + +**To enable the Time & Expenses module:** + +In Sage Intacct, go to **Company menu > Subscriptions > Time & Expenses** and toggle the switch to subscribe. + +**After enabling T&E, configure it as follows:** + +1. Ensure that **Expense types** is checked +2. Under **Auto-numbering sequences** set the following: + - **Expense Report:** EXP + - **Employee:** EMP + - **Duplicate Numbers:** Select ā€œDo not allow creationā€ + - To create the EXP sequence, click on the down arrow on the expense report line and select **Add: + 1. **Sequence ID:** EXP + 1. **Print Title:** EXPENSE REPORT + 1. **Starting Number:** 1 + 1. **Next Number:** 2 +3. Select **Advanced Settings** and configure the following: + a. **Fixed Number Length:** 4 + b. **Fixed Prefix:** EXP +4. Click **Save** +5. Under Expense Report approval settings, ensure that **Enable expense report approval** is unchecked +6. Click **Save** to confirm your configuration + + +## Step 3: Set up Employees in Sage Intacct +**Note: This step is only required if exporting out-of-pocket expenses from Expensify to Sage Intacct as Expense Reports.** + +To set up employees in Sage Intacct: + +1. Navigate to Time & Expenses and click the **plus button** next to Employees. + - If you donā€™t see the Time & Expense option in the top ribbon, you may need to adjust your settings. Go to **Company > Roles > Time & Expenses** and enable all permissions. +2. To create an employee, youā€™ll need to provide the following information: + - Employee ID + - Primary contact name + - Email address + 1. In the "Primary contact name" field, click the dropdown arrow. + 1. Select the employee if theyā€™ve already been created. + 1. Otherwise, click **+ Add** to create a new employee. + 1. Fill in their Primary Email Address along with any other required information + + +## Step 4: Set up Expense Types in Sage Intacct +**Note: This step is only required if exporting out-of-pocket expenses from Expensify to Sage Intacct as Expense Reports.** + +Expense Types provide a user-friendly way to display the names of your expense accounts to your employees. To set up expense types in Sage Intacct: + +1. **Setup Your Chart of Accounts** + - Before configuring Expense Types, ensure your Chart of Accounts is set up. You can set up accounts in bulk by going to **Company > Open Setup > Company Setup Checklist** and clicking **Import**. +2. **Set up Expense Types** + - Go to Time & Expense + - Open Setup and click the **plus button** next to Expense Types +3. For each Expense Type, provide the following information: + - **Expense Type** + - **Description** + - **Account Number** (from your General Ledger) + +## Step 5: Enable Customization Services +**Note:** If you already have Platform Services enabled, you can skip this step. + +To enable Customization Services, go to **Company > Subscriptions > Customization Services**. + + +## Step 6: Download the Expensify Package +1. In Expensify, go to Settings > Workspaces +1. Click into the workspace where you'd like to connect to Sage Intacct + - If you already use Expensify, you can optionally create a test workspace by clicking **New Workspace** at the top-right of the Workspaces page. A test workspace allows you to have a sandbox environment for testing before implementing the integration live. +1. Go to **Connections > Sage Intacct > Connect to Sage Intacct** +1. Select **Download Package** (You only need to download the file; weā€™ll upload it from your Downloads folder later) + +## Step 7: Upload Package in Sage Intacct +If you use Customization Services: + +1. Go to **Customization Services > Custom Packages > New Package** +1. Click on **Choose File** and select the Package file from your downloads folder +1. Click **Import** + +If you use Platform Services: + +1. Go to **Platform Services > Custom Packages > New Package** +1. Click on **Choose File** and select the Package file from your downloads folder +1. Click **Import** + + +## Step 8: Add Web Services Authorization +1. Go to **Company > Company Info > Security** in Sage Intacct and click **Edit** +2. Scroll down to **Web Services Authorizations** and add ā€œexpensifyā€ (all lower case) as a Sender ID + +## Step 9: Enter Credentials and Connect Expensify and Sage Intacct +1. In Expensify, go to **Settings > Workspaces > [Workspace Name] > Accounting** +1. Click **Set up** next to Sage Intacct +1. Enter the credentials you set for your web services user in Step 1 +1. Click **Confirm** + + + +# Configure Sage Intacct integration + +## Step 1: Select entity (multi-entity setups only) +If you have a multi-entity setup in Sage Intacct, you will be able to select in Expensify which Sage Intacct entity to connect each workspace to. Each Expensify workspace can either be connected to a single entity or connected at the Top Level. + +To select or change the Sage Intacct entity that your Expensify workspace is connected to, navigate to the Accounting settings for your workspace and click **Entity** under the Sage Intacct connection. + +## Step 2: Configure import settings +The following section will help you determine how data will be imported from Sage Intacct into Expensify. To change your import settings, navigate to the Accounting settings for your workspace, then click **Import** under the Sage Intacct connection. + +### Expense Types / Chart of Accounts +The categories in Expensify depend on how you choose to export out-of-pocket expenses: + +- If you choose to export out-of-pocket expenses as Expense Reports, your categories in Expensify will be imported from your Sage Intacct Expense Types +- If you choose to export out-of-pocket expenses as Vendor Bills, your categories will be imported directly from your Chart of Accounts (also known as GL Codes or Account Codes). + +You can disable unnecessary categories in Expensify by going to **Settings > Workspaces > [Workspace Name] > Categories**. Note that every expense must be coded with a Category, or it will fail to export. + +### Billable Expenses +Enabling billable expenses allows you to map your expense types or accounts to items in Sage Intacct. To do this, youā€™ll need to enable the correct permissions on your Sage Intacct user or role. This may vary based on the modules you use in Sage Intacct, so you should enable read-only permissions for relevant modules such as Projects, Purchasing, Inventory Control, and Order Entry. + +Once permissions are set, you can map categories to specific items, which will then export to Sage Intacct. When an expense is marked as Billable in Expensify, users must select the correct billable Category (Item), or there will be an error during export. + + +### Standard dimensions: Departments, Classes, and Locations +The Sage Intacct integration allows you to import standard dimensions into Expensify as tags, report fields, or using the Sage Intacct employee default. + +- **Sage Intacct Employee default:** This option is only available when exporting as expense reports. When this option is selected, nothing will be imported into Expensify - instead, the employee default will be applied to each expense upon export. +- **Tags:** Employees can select the department, class, or location on each individual expense. If the employee's Sage Intacct employee record has a default value, then each expense will default to that tag, with the option for the employee to select a different value on each expense. +- **Report Fields:** Employees can select one department/class/location for each expense report. + +New departments, classes, and locations must be added in Sage Intacct. Once imported, you can turn specific tags on or off under **Settings > Workspaces > [Workspace Name] > Tags**. You can turn specific report fields on or off under **Settings > Workspaces > [Workspace Name] > Report Fields**. + +Please note that when importing departments as tags, expense reports may show the tag name as "Tag" instead of "Department." + +### Customers and Projects +The Sage Intacct integration allows you to import customers and projects into Expensify as Tags or Report Fields. + +- **Tags:** Employees can select the customer or project on each individual expense. +- **Report Fields:** Employees can select one department/class/location for each expense report. + +New customers and projects must be added in Sage Intacct. Once imported, you can turn specific tags on or off under **Settings > Workspaces > [Workspace Name] > Tags**. You can turn specific report fields on or off under **Settings > Workspaces > [Workspace Name] > Report Fields**. + + +### Tax +The Sage Intacct integration supports native VAT and GST tax. To enable this feature, go to **Settings > Workspaces > [Workspace Name] > Accounting**, click **Import** under Sage Intacct, and enable Tax. Enabling this option will import your native tax rates from Sage Intacct into Expensify. From there, you can select default rates for each category under **Settings > Workspaces > [Workspace Name] > Categories**. + +For older Sage Intacct connections that don't show the Tax option, simply resync the connection by going to **Settings > Workspaces > [Workspace Name] > Accounting** and clicking the three dots next to Sage Intacct, and the tax toggle will appear. + +### User-Defined Dimensions +You can add User-Defined Dimensions (UDDs) to your workspace by locating the ā€œIntegration Nameā€ in Sage Intacct. Please note that you must be logged in as an administrator in Sage Intacct to find the required fields. + +To find the Integration Name in Sage Intacct: + +1. Go to **Platform Services > Objects > List** +1. Set ā€œfilter by applicationā€ to ā€œuser-defined dimensionsā€ +1. In Expensify, go to **Settings > Workspaces > [Workspace Name] > Accounting** and click **Import** under Sage Intacct +1. Enable User Defined Dimensions +1. Enter the ā€œIntegration nameā€ and choose whether to import it into Expensify as expense-level tags or as report fields +1. Click **Save** + +Once imported, you can turn specific tags on or off under **Settings > Workspaces > [Workspace Name] > Tags**. You can turn specific report fields on or off under **Settings > Workspaces > [Workspace Name] > Report Fields**. + + +## Step 5: Configure export settings +To access export settings, head to **Settings > Workspaces > [Workspace name] > Accounting** and click **Export** under Sage Intacct. + +### Preferred exporter +Any workspace admin can export reports to Sage Intacct. For auto-export, Concierge will export on behalf of the preferred exporter. The preferred exporter will also be notified of any expense reports that fail to export to Sage Intacct due to an error. + +### Export date +You can choose which date to use for the records created in Sage Intacct. There are three date options: + +1. **Date of last expense:** This will use the date of the previous expense on the report +1. **Export date:** The date you export the report to Sage Intacct +1. **Submitted date:** The date the employee submitted the report + +### Export out-of-pocket expenses as +Out-of-pocket expenses can be exported to Sage Intacct as **expense reports** or as **vendor bills**. If you choose to export as expense reports, you can optionally select a **default vendor**, which will apply to reimbursable expenses that don't have a matching vendor in Sage Intacct. + +### Export company card expenses as +Company Card expenses are exported separately from out-of-pocket expenses, and can be exported to Sage Intacct as credit card charges** or as **vendor bills**. + +- **Credit card charges:** When exporting as credit card charges, you must select a credit card account. You can optionally select a default vendor, which will apply to company card expenses that don't have a matching vendor in Sage Intacct. + - Credit card charges cannot be exported to Sage Intacct at the top-level if you have multi-currency enabled, so you will need to select an individual entity if you have this setup. +- **Vendor bills:** When exporting as vendor bills, you can select a default vendor, which will apply to company card expenses that don't have a matching vendor in Sage Intacct. + +If you centrally manage your company cards through Domains in Expensify Classic, you can export expenses from each individual card to a specific account in Sage Intacct in the Expensify Company Card settings. + +### 6. Configure advanced settings +To access the advanced settings of the Sage Intacct integration, head to **Settings > Workspaces > [Workspace name] > Accounting** and click **Advanced** under Sage Intacct. + + +Letā€™s review the different advanced settings and how they interact with the integration. + +### Auto-sync +We strongly recommend enabling auto-sync to ensure that the information in Sage Intacct and Expensify is always in sync. The following will occur when auto-sync is enabled: + +**Daily sync from Sage Intacct to Expensify:** Once a day, Expensify will sync any changes from Sage Intacct into Expensify. This includes any changes or additions to your Sage Intacct dimensions. + +**Auto-export:** When an expense report reaches its final state in Expensify, it will be automatically exported to Sage Intacct. The final state will either be reimbursement (if you reimburse members through Expensify) or final approval (if you reimburse members outside of Expensify). + +**Reimbursement-sync:** If Sync Reimbursed Reports (more details below) is enabled, then we will sync the reimbursement status of reports between Expensify and Sage Intacct. + +### Invite employees +Enabling this feature will invite all employees from the connected Sage Intacct entity to your Expensify workspace. Once imported, each employee who has not already been invited to that Expensify workspace will receive an email letting them know theyā€™ve been added to the workspace. + +In addition to inviting employees, this feature enables a custom set of approval workflow options, which you can manage in Expensify Classic: + +- **Basic Approval:** A single level of approval, where all users submit directly to a Final Approver. The Final Approver defaults to the workspace owner but can be edited on the people page. +- **Manager Approval (default):** Each user submits to their manager, who is imported from Sage Intacct. You can optionally select a final approver who each manager forwards to for second-level approval. +- **Configure Manually:** Employees will be imported, but all levels of approval must be manually configured in Expensify. If you enable this setting, you can configure approvals by going to **Settings > Workspaces > [Workspace Name] > People**. + + +### Sync reimbursed reports +When Sync reimbursed reports is enabled, the reimbursement status will be synced between Expensify and Sage Intacct. + +**If you reimburse employees through Expensify:** Reimbursing an expense report will trigger auto-export to Sage Intacct. When the expense report is exported to Sage Intacct, a corresponding bill payment will also be created in Sage Intacct in the selected Cash and Cash Equivalents account. If you don't see the account you'd like to select in the dropdown list, please confirm that the account type is Cash and Cash Equivalents. + +**If you reimburse employees outside of Expensify:** Expense reports will be exported to Sage Intacct at time of final approval. After you mark the report as paid in Sage Intacct, the reimbursed status will be synced back to Expensify the next time the integration syncs. + +To ensure this feature works properly for expense reports, make sure that the account you choose within the settings matches the default account for Bill Payments in NetSuite. When exporting invoices, once marked as Paid, the payment is marked against the account selected after enabling the Collection Account setting. +## FAQ + +### Why wasn't my report automatically exported to Sage Intacct? +There are a number of factors that can cause auto-export to fail. If this happens, you will find the specific export error in the report comments for the report that failed to export. Once youā€™ve resolved any errors, you can manually export the report to Sage Intacct. + +### Will enabling auto-sync affect existing approved and reimbursed reports? +Auto-sync will only export newly approved reports to Sage Intacct. Any reports that were approved or reimbursed before enabling auto-sync will need to be manually exported in order to sync them to Sage Intacct. + + +### Can I export negative expenses to Sage Intacct? +Yes, you can export negative expenses to Sage Intacct. If you are exporting out-of-pocket expenses as expense reports, then the total of each exported report cannot be negative. diff --git a/docs/articles/new-expensify/connections/Sage-Intacct/Sage-Intacct-Troubleshooting.md b/docs/articles/new-expensify/connections/Sage-Intacct/Sage-Intacct-Troubleshooting.md new file mode 100644 index 000000000000..ae8a0f16d9b9 --- /dev/null +++ b/docs/articles/new-expensify/connections/Sage-Intacct/Sage-Intacct-Troubleshooting.md @@ -0,0 +1,6 @@ +--- +title: Sage Intacct Troubleshooting +description: Coming soon +--- + +# Coming soon diff --git a/docs/articles/new-expensify/connections/Xero/Configure-Xero.md b/docs/articles/new-expensify/connections/Xero/Configure-Xero.md new file mode 100644 index 000000000000..0c65db1b4fd9 --- /dev/null +++ b/docs/articles/new-expensify/connections/Xero/Configure-Xero.md @@ -0,0 +1,6 @@ +--- +title: Configure Xero +description: Coming soon +--- + +# Coming soon diff --git a/docs/articles/new-expensify/connections/Set-up-Xero-connection.md b/docs/articles/new-expensify/connections/Xero/Connect-to-Xero.md similarity index 98% rename from docs/articles/new-expensify/connections/Set-up-Xero-connection.md rename to docs/articles/new-expensify/connections/Xero/Connect-to-Xero.md index 47917f2dffc3..eb35b1589db4 100644 --- a/docs/articles/new-expensify/connections/Set-up-Xero-connection.md +++ b/docs/articles/new-expensify/connections/Xero/Connect-to-Xero.md @@ -1,8 +1,8 @@ --- -title: Set up Xero connection +title: Connect to Xero description: Integrate Xero with Expensify +order: 1 --- -
{% include info.html %} To use the Xero connection, you must have a Xero account and an Expensify Collect plan. @@ -104,5 +104,3 @@ The following steps help you determine the advanced settings for your connection You will no longer see the imported options from Xero. {% include faq-end.md %} - -
diff --git a/docs/articles/new-expensify/connections/Xero/Xero-Troubleshooting.md b/docs/articles/new-expensify/connections/Xero/Xero-Troubleshooting.md new file mode 100644 index 000000000000..9c211efbaf24 --- /dev/null +++ b/docs/articles/new-expensify/connections/Xero/Xero-Troubleshooting.md @@ -0,0 +1,6 @@ +--- +title: Xero Troubleshooting +description: Coming soon +--- + +# Coming soon diff --git a/docs/articles/new-expensify/expenses-&-payments/Duplicate-detection.md b/docs/articles/new-expensify/expenses-&-payments/Duplicate-detection.md new file mode 100644 index 000000000000..9fab52bca76a --- /dev/null +++ b/docs/articles/new-expensify/expenses-&-payments/Duplicate-detection.md @@ -0,0 +1,73 @@ +--- +title: Manage duplicate expenses +description: Identify and manage duplicate expense requests +--- + +
+ +Duplicate Detection helps prevent duplicate expense requests by flagging expense requests that have the same date and amount as another request in the same member's account. + +When an expense has been flagged as a potential duplicate, a red dot appears in the left menu or the expenseā€™s chat room, and it is put on ā€œhold.ā€ + +{% include info.html %} +This feature is available exclusively for Collect & Control plans. +{% include end-info.html %} + +# Review & resolve duplicates + +{% include selector.html values="desktop, mobile" %} + +{% include option.html value="desktop" %} +1. Click the red dot in the left menu or open the expenseā€™s chat room to open the flagged request. +2. Click the green **Review duplicates** button at the top of the request. +3. Review the list of potential duplicates. +4. To resolve a duplicate, click either **Keep all** or **Keep this one**. + - **Keep all**: Keeps all expenses as their separate charges and removes the hold. + - **Keep this one**: Keeps this expense and discards its other related duplicates. +5. If discrepancies exist between the duplicates (e.g., category, tags), choose which details to keep. +6. Confirm your selection to merge the requests or keep all. + +The expenses are removed from the duplicates list and the hold is removed. + +{% include end-option.html %} + +{% include option.html value="mobile" %} +1. Tap the red dot in the left menu or open the expenseā€™s chat room to open the flagged request. +2. Tap the green **Review duplicates** button at the top of the request. +3. Review the list of potential duplicates. +4. To resolve a duplicate, tap either **Keep all** or **Keep this one**. + - **Keep all**: Keeps all expenses as their separate charges and removes the hold. + - **Keep this one**: Keeps this expense and discards its other related duplicates. +5. If discrepancies exist between the duplicates (e.g., category, tags), choose which details to keep. +6. Confirm your selection to merge the requests or keep all. + +The expenses are removed from the duplicates list and the hold is removed. +{% include end-option.html %} + +{% include end-selector.html %} + + + + +{% include faq-begin.md %} +**Can I review a discarded duplicate later?** + +Yes, approvers can review discarded duplicates to ensure accuracy and prevent fraud. + +**Can I edit a duplicate request once resolved?** + +Yes, you can edit the details of a duplicate request once it has been resolved, but the hold must be removed first. + +**If two expenses are SmartScanned on the same day for the same amount, will they be flagged as duplicates?** + +Yes, the expenses will be flagged as duplicates unless one of the following is true: +- The expenses were split from a single expense +- The expenses were imported from a credit card +- Matching email receipts sent to receipts@expensify.com were received with different timestamps + +**What happens if Concierge flags a receipt as a duplicate?** + +If Concierge lets you know it has flagged a receipt as a duplicate, scanning the receipt again will trigger the same duplicate flagging. You can still find these in the [deleted](https://www.expensify.com/expenses?reportStatusList=Deleted) filter on Expensify Classic. +{% include faq-end.md %} + +
diff --git a/docs/articles/new-expensify/expenses-&-payments/Send-an-invoice.md b/docs/articles/new-expensify/expenses-&-payments/Send-an-invoice.md index 588f0da20154..6546f57073ee 100644 --- a/docs/articles/new-expensify/expenses-&-payments/Send-an-invoice.md +++ b/docs/articles/new-expensify/expenses-&-payments/Send-an-invoice.md @@ -38,6 +38,9 @@ Once an invoice is sent, the customer receives an automated email or text messag 4. Click **Pay Elsewhere**, which will mark the invoice as Paid. Currently, invoices must be paid outside of Expensify. However, the ability to make payments through Expensify is coming soon. + +![A photo of the pay button]({{site.url}}/assets/images/ExpensifyHelp-Invoice-1.png){:width="100%"} + # FAQs diff --git a/docs/articles/new-expensify/travel/Expensify-Travel-demo-video.md b/docs/articles/new-expensify/travel/Expensify-Travel-demo-video.md new file mode 100644 index 000000000000..ceb40254c607 --- /dev/null +++ b/docs/articles/new-expensify/travel/Expensify-Travel-demo-video.md @@ -0,0 +1,8 @@ +--- +title: Expensify Travel demo video +description: Check out a demo of Expensify Travel +--- + +Check out a video of how Expensify Travel works below: + + diff --git a/docs/articles/new-expensify/workspaces/Create-expense-categories.md b/docs/articles/new-expensify/workspaces/Create-expense-categories.md index 6f810d8f96d0..3eb148e92fe1 100644 --- a/docs/articles/new-expensify/workspaces/Create-expense-categories.md +++ b/docs/articles/new-expensify/workspaces/Create-expense-categories.md @@ -89,6 +89,24 @@ You can enable, disable, or delete categories in bulk by selecting the checkbox {% include end-selector.html %} +# Add or edit a GL code or payroll code + +If your workspace is on the Control plan, you can optionally add a GL code and payroll code to each category. Collect plan users will need to upgrade to Control for access to GL codes and payroll codes. + +GL codes and payroll codes can be exported to a CSV export. They are not displayed to users. + +**To edit GL codes or payroll codes for a category:** + +1. Click your profile image or icon in the bottom left menu +2. Click **Workspaces** in the left menu +3. Select a workspace +4. Click **Categories** +5. Click a category to open the category-settings +6. To add or edit a GL code, click the GL code field, make the desired change, then click **Save** +7. To add or edit a payroll code, click the payroll code field, make the desired change, then click **Save** + + + # Automatic Expensify categories Over time, Expensify learns how you categorize specific merchants and automatically applies that category to the merchant in the future. diff --git a/docs/articles/new-expensify/workspaces/Create-expense-tags.md b/docs/articles/new-expensify/workspaces/Create-expense-tags.md index e048ad9ca768..cc76b4016856 100644 --- a/docs/articles/new-expensify/workspaces/Create-expense-tags.md +++ b/docs/articles/new-expensify/workspaces/Create-expense-tags.md @@ -95,6 +95,22 @@ You can enable, disable, or delete tags in bulk by selecting the checkbox to the {% include end-selector.html %} +# Add or edit a GL code or payroll code + +If your workspace is on the Control plan, you can optionally add a GL code and payroll code to each category. Collect plan users will need to upgrade to Control for access to GL codes and payroll codes. + +GL codes and payroll codes can be exported to a CSV export. They are not displayed to users. + +**To edit GL codes or payroll codes for a category:** + +1. Click your profile image or icon in the bottom left menu +2. Click **Workspaces** in the left menu +3. Select a workspace +4. Click **Categories** +5. Click a category to open the category-settings +6. To add or edit a GL code, click the GL code field, make the desired change, then click **Save** +7. To add or edit a payroll code, click the payroll code field, make the desired change, then click **Save** + # Automatic Expensify tags Over time, Expensify learns how you tag specific merchants and automatically applies that tag to the merchant in the future. diff --git a/docs/articles/new-expensify/workspaces/Track-taxes.md b/docs/articles/new-expensify/workspaces/Track-taxes.md new file mode 100644 index 000000000000..c98af9746607 --- /dev/null +++ b/docs/articles/new-expensify/workspaces/Track-taxes.md @@ -0,0 +1,66 @@ +--- +title: Track taxes +description: Set up tax rates in your Expensify workspace +--- +
+ +# Track taxes + +Each Expensify workspace can be configured with one or more tax rates. Once tax rates are enabled on your workspace, all expenses will have a default tax rate applied based on the currency, and employees will be able to select the correct tax rate for each expense. + +Tax rates are only available on the Control plan. Collect plan users will need to upgrade to Control for access to tag tax codes. + +## Enable taxes on a workspace + +Taxes can be enabled on any workspace where the default currency is not USD. Please note that if you have a direct accounting integration, tax rates will be managed through the integration and cannot be manually enabled or disabled using the instructions below. + +**To enable taxes on your workspace:** + +1. Click your profile image or icon in the bottom left menu +2. Click **Workspaces** in the left menu +3. Select the workspace where you want to enable tax codes +4. Click **More features** in the left menu +5. Click the toggle next to **Taxes** + +After toggling on taxes, you will see a new **Taxes** option in the left menu. + +## Manually add, delete, or edit tax rates + +**To manually add a tax rate:** + +1. Click your profile image or icon in the bottom left menu +2. Scroll down and click **Workspaces** in the left menu +3. Select the workspace where you want to add tax codes +4. Click **Taxes** in the left menu +5. Click **Add rate** in the top right +6. Enter a name, value, and tax code, then click **Save** + +**To enable, disable, edit or delete a single tax rate:** + +1. Click the tax rate on the **Taxes** settings page +2. To enable or disable the tax rate, click the toggle next to **Enable rate**, then click **Save** +3. To edit the name, value, or tax code, click into the **Name**, **Value**, or **Tax Code** field, then click **Save** +4. To permanently delete the tax rate, click **Delete** + +Please note: The workspace currency default rate cannot be deleted or disabled. + +**To enable, disable, or delete tax rates in bulk:** + +1. On the **Taxes** settings page, click the checkboxes next to the tax rates you'd like to delete +2. Click "x selected" in the top right +3. To enable or disable all the selected tax rates, click **Enable rates** or **Disable rates** +4. To permanently delete the tax rates, click **Delete rates** + +Please note: The workspace currency default rate cannot be deleted or disabled. + +## Change the default tax rates + +After enabling taxes in your workspace, you can set two default rates: + +- **Workspace currency default:** Any expenses created in the workspace default currency will default to this tax rate. Employees can select a different tax rate if applicable. +- **Foreign currency default:** Expenses created in any currency besides the workspace default currency will default to this tax rate. Employees can select a different tax rate if applicable. + +**To change the default tax rates:** + +1. On the **Taxes** settings page, click **Settings** in the top right +2. Click **Workspace currency default** or **Foreign currency default** and select the desired tax rate diff --git a/docs/assets/images/Approves_To.png b/docs/assets/images/Approves_To.png new file mode 100644 index 000000000000..004f75377234 Binary files /dev/null and b/docs/assets/images/Approves_To.png differ diff --git a/docs/assets/images/Expenses.png b/docs/assets/images/Expenses.png new file mode 100644 index 000000000000..f018737be803 Binary files /dev/null and b/docs/assets/images/Expenses.png differ diff --git a/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_01.png b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_01.png new file mode 100644 index 000000000000..e7332f65e832 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_01.png differ diff --git a/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_02.png b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_02.png new file mode 100644 index 000000000000..b5c176e829c9 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_02.png differ diff --git a/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_03.png b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_03.png new file mode 100644 index 000000000000..ffed1ff6ade2 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_03.png differ diff --git a/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_04.png b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_04.png new file mode 100644 index 000000000000..88cb7d2704a8 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_04.png differ diff --git a/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_05.png b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_05.png new file mode 100644 index 000000000000..2175697461dc Binary files /dev/null and b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_05.png differ diff --git a/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_06.png b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_06.png new file mode 100644 index 000000000000..cce21e52e185 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_06.png differ diff --git a/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_07.png b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_07.png new file mode 100644 index 000000000000..5e9297f0c100 Binary files /dev/null and b/docs/assets/images/ExpensifyHelp-WorkspaceFeeds_07.png differ diff --git a/docs/assets/images/Itinerary.png b/docs/assets/images/Itinerary.png new file mode 100644 index 000000000000..52ddb33d8489 Binary files /dev/null and b/docs/assets/images/Itinerary.png differ diff --git a/docs/assets/images/amounts.png b/docs/assets/images/amounts.png new file mode 100644 index 000000000000..6d5751811495 Binary files /dev/null and b/docs/assets/images/amounts.png differ diff --git a/docs/expensify-classic/hubs/connect-credit-cards/business-bank-accounts.html b/docs/expensify-classic/hubs/bank-accounts-and-payments/payments.html similarity index 100% rename from docs/expensify-classic/hubs/connect-credit-cards/business-bank-accounts.html rename to docs/expensify-classic/hubs/bank-accounts-and-payments/payments.html diff --git a/docs/expensify-classic/hubs/connect-credit-cards/deposit-accounts.html b/docs/expensify-classic/hubs/connections/accelo.html similarity index 100% rename from docs/expensify-classic/hubs/connect-credit-cards/deposit-accounts.html rename to docs/expensify-classic/hubs/connections/accelo.html diff --git a/docs/expensify-classic/hubs/expenses/expenses.html b/docs/expensify-classic/hubs/connections/certinia.html similarity index 100% rename from docs/expensify-classic/hubs/expenses/expenses.html rename to docs/expensify-classic/hubs/connections/certinia.html diff --git a/docs/expensify-classic/hubs/integrations/index.html b/docs/expensify-classic/hubs/connections/index.html similarity index 100% rename from docs/expensify-classic/hubs/integrations/index.html rename to docs/expensify-classic/hubs/connections/index.html diff --git a/docs/expensify-classic/hubs/expenses/reports.html b/docs/expensify-classic/hubs/connections/netsuite.html similarity index 100% rename from docs/expensify-classic/hubs/expenses/reports.html rename to docs/expensify-classic/hubs/connections/netsuite.html diff --git a/docs/expensify-classic/hubs/getting-started/approved-accountants.html b/docs/expensify-classic/hubs/connections/quickbooks-desktop.html similarity index 100% rename from docs/expensify-classic/hubs/getting-started/approved-accountants.html rename to docs/expensify-classic/hubs/connections/quickbooks-desktop.html diff --git a/docs/expensify-classic/hubs/getting-started/support.html b/docs/expensify-classic/hubs/connections/quickbooks-online.html similarity index 100% rename from docs/expensify-classic/hubs/getting-started/support.html rename to docs/expensify-classic/hubs/connections/quickbooks-online.html diff --git a/docs/expensify-classic/hubs/getting-started/tips-and-tricks.html b/docs/expensify-classic/hubs/connections/sage-intacct.html similarity index 100% rename from docs/expensify-classic/hubs/getting-started/tips-and-tricks.html rename to docs/expensify-classic/hubs/connections/sage-intacct.html diff --git a/docs/expensify-classic/hubs/integrations/HR-integrations.html b/docs/expensify-classic/hubs/connections/xero.html similarity index 100% rename from docs/expensify-classic/hubs/integrations/HR-integrations.html rename to docs/expensify-classic/hubs/connections/xero.html diff --git a/docs/expensify-classic/hubs/integrations/accounting-integrations.html b/docs/new-expensify/hubs/connections/netsuite.html similarity index 100% rename from docs/expensify-classic/hubs/integrations/accounting-integrations.html rename to docs/new-expensify/hubs/connections/netsuite.html diff --git a/docs/expensify-classic/hubs/integrations/other-integrations.html b/docs/new-expensify/hubs/connections/quickbooks-online.html similarity index 100% rename from docs/expensify-classic/hubs/integrations/other-integrations.html rename to docs/new-expensify/hubs/connections/quickbooks-online.html diff --git a/docs/expensify-classic/hubs/integrations/travel-integrations.html b/docs/new-expensify/hubs/connections/sage-intacct.html similarity index 100% rename from docs/expensify-classic/hubs/integrations/travel-integrations.html rename to docs/new-expensify/hubs/connections/sage-intacct.html diff --git a/docs/expensify-classic/hubs/workspaces/reports.html b/docs/new-expensify/hubs/connections/xero.html similarity index 100% rename from docs/expensify-classic/hubs/workspaces/reports.html rename to docs/new-expensify/hubs/connections/xero.html diff --git a/docs/redirects.csv b/docs/redirects.csv index 67ca238c1aed..4b7cc43bd072 100644 --- a/docs/redirects.csv +++ b/docs/redirects.csv @@ -203,6 +203,9 @@ https://help.expensify.com/articles/new-expensify/chat/Expensify-Chat-For-Admins https://help.expensify.com/articles/new-expensify/bank-accounts-and-payments/Connect-a-Bank-Account.html,https://help.expensify.com/articles/new-expensify/expenses/Connect-a-Business-Bank-Account https://help.expensify.com/articles/expensify-classic/travel/Coming-Soon,https://help.expensify.com/expensify-classic/hubs/travel/ https://help.expensify.com/articles/new-expensify/expenses/Manually-submit-reports-for-approval,https://help.expensify.com/new-expensify/hubs/expenses/ +https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/Reimbursements.html,https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/payments/Receive-Payments +https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/Pay-Bills.html,https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/payments/Reimburse-Reports-Invoices-and-Bills +https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/Reimbursing-Reports.html,https://help.expensify.com/articles/expensify-classic/bank-accounts-and-payments/payments/Reimburse-Reports-Invoices-and-Bills https://help.expensify.com/articles/expensify-classic/expensify-card/Auto-Reconciliation,https://help.expensify.com/articles/expensify-classic/expensify-card/Expensify-Card-Reconciliation.md https://help.expensify.com/articles/new-expensify/expenses/Approve-and-pay-expenses,https://help.expensify.com/articles/new-expensify/expenses-&-payments/Approve-and-pay-expenses https://help.expensify.com/articles/new-expensify/expenses/Connect-a-Business-Bank-Account,https://help.expensify.com/articles/new-expensify/expenses-&-payments/Connect-a-Business-Bank-Account @@ -214,4 +217,69 @@ https://help.expensify.com/articles/new-expensify/expenses/Set-up-your-wallet,ht https://help.expensify.com/articles/new-expensify/expenses/Split-an-expense,https://help.expensify.com/articles/new-expensify/expenses-&-payments/Split-an-expense https://help.expensify.com/articles/new-expensify/expenses/Track-expenses,https://help.expensify.com/articles/new-expensify/expenses-&-payments/Track-expenses https://help.expensify.com/articles/new-expensify/expenses/Unlock-a-Business-Bank-Account,https://help.expensify.com/articles/new-expensify/expenses-&-payments/Unlock-a-Business-Bank-Account -https://help.expensify.com/articles/new-expensify/expenses/Validate-a-Business-Bank-Account,https://help.expensify.com/articles/new-expensify/expenses-&-payments/Validate-a-Business-Bank-Account \ No newline at end of file +https://help.expensify.com/expensify-classic/hubs/integrations/HR-integrations,https://help.expensify.com/expensify-classic/hubs/connections +https://help.expensify.com/expensify-classic/hubs/integrations/accounting-integrations,https://help.expensify.com/expensify-classic/hubs/connections +https://help.expensify.com/expensify-classic/hubs/integrations/other-integrations,https://help.expensify.com/expensify-classic/hubs/connections +https://help.expensify.com/expensify-classic/hubs/integrations/travel-integrations,https://help.expensify.com/expensify-classic/hubs/connections +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/ADP,https://help.expensify.com/articles/expensify-classic/connections/ADP +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Accelo,https://help.expensify.com/expensify-classic/hubs/connections/accelo +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Additional-Travel-Integrations,https://help.expensify.com/articles/expensify-classic/connections/Additional-Travel-Integrations +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Certinia,https://help.expensify.com/expensify-classic/hubs/connections/certinia +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Egencia,https://help.expensify.com/articles/expensify-classic/connections/Egencia +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Global-VaTax,https://help.expensify.com/articles/expensify-classic/connections/Global-VaTax +https://help.expensify.com/articles/expensify-classic/integrations/other-integrations/Google-Apps-SSO,https://help.expensify.com/articles/expensify-classic/connections/Google-Apps-SSO +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Greenhouse,https://help.expensify.com/articles/expensify-classic/connections/Greenhouse +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Gusto,https://help.expensify.com/articles/expensify-classic/connections/Gusto +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Indirect-Accounting-Integrations,https://help.expensify.com/articles/expensify-classic/connections/Indirect-Accounting-Integrations +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Lyft,https://help.expensify.com/articles/expensify-classic/connections/Lyft +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Navan,https://help.expensify.com/articles/expensify-classic/connections/Navan +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/NetSuite,https://help.expensify.com/expensify-classic/hubs/connections/netsuite +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/QuickBooks-Time,https://help.expensify.com/articles/expensify-classic/connections/QuickBooks-Time +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop,https://help.expensify.com/expensify-classic/hubs/connections/quickbooks-desktop +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online,https://help.expensify.com/expensify-classic/hubs/connections/quickbooks-online +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Rippling,https://help.expensify.com/articles/expensify-classic/connections/Rippling +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Sage-Intacct,https://help.expensify.com/expensify-classic/hubs/connections/sage-intacct +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/TravelPerk,https://help.expensify.com/articles/expensify-classic/connections/TravelPerk +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Uber,https://help.expensify.com/articles/expensify-classic/connections/Uber +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Workday,https://help.expensify.com/articles/expensify-classic/connections/Workday +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Xero,https://help.expensify.com/expensify-classic/hubs/connections/xero +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Zenefits,https://help.expensify.com/articles/expensify-classic/connections/Zenefits +https://help.expensify.com/articles/expensify-classic/workspaces/tax-tracking,https://help.expensify.com/articles/expensify-classic/workspaces/Tax-Tracking +https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Approval-Workflows,https://help.expensify.com/articles/expensify-classic/reports/Assign-report-approvers-to-specific-employees +https://help.expensify.com/articles/expensify-classic/settings/Notification-Troubleshooting,https://help.expensify.com/articles/expensify-classic/settings/account-settings/Set-Notifications +https://help.expensify.com/articles/new-expensify/expenses/Validate-a-Business-Bank-Account,https://help.expensify.com/articles/new-expensify/expenses-&-payments/Validate-a-Business-Bank-Account +https://help.expensify.com/articles/expensify-classic/workspaces/Currency,https://help.expensify.com/articles/expensify-classic/workspaces/Set-Currency +https://help.expensify.com/articles/expensify-classic/workspaces/Expenses,https://help.expensify.com/articles/expensify-classic/workspaces/Expense-Settings +https://help.expensify.com/articles/expensify-classic/workspaces/Reimbursement,https://help.expensify.com/articles/expensify-classic/workspaces/Configure-Reimbursement-Settings +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/ADP.html,https://help.expensify.com/articles/expensify-classic/connections/ADP +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Accelo.html,https://help.expensify.com/expensify-classic/hubs/connections/accelo +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Additional-Travel-Integrations.html,https://help.expensify.com/articles/expensify-classic/connections/Additional-Travel-Integrations +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Certinia.html,https://help.expensify.com/expensify-classic/hubs/connections/certinia +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Egencia.html,https://help.expensify.com/articles/expensify-classic/connections/Egencia +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Global-VaTax.html,https://help.expensify.com/articles/expensify-classic/connections/Global-VaTax +https://help.expensify.com/articles/expensify-classic/integrations/other-integrations/Google-Apps-SSO.html,https://help.expensify.com/articles/expensify-classic/connections/Google-Apps-SSO +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Greenhouse.html,https://help.expensify.com/articles/expensify-classic/connections/Greenhouse +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Gusto.html,https://help.expensify.com/articles/expensify-classic/connections/Gusto +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Indirect-Accounting-Integrations.html,https://help.expensify.com/articles/expensify-classic/connections/Indirect-Accounting-Integrations +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Lyft.html,https://help.expensify.com/articles/expensify-classic/connections/Lyft +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Navan.html,https://help.expensify.com/articles/expensify-classic/connections/Navan +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/NetSuite.html,https://help.expensify.com/expensify-classic/hubs/connections/netsuite +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/QuickBooks-Time.html,https://help.expensify.com/articles/expensify-classic/connections/QuickBooks-Time +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Desktop.html,https://help.expensify.com/expensify-classic/hubs/connections/quickbooks-desktop +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/QuickBooks-Online.html,https://help.expensify.com/expensify-classic/hubs/connections/quickbooks-online +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Rippling.html,https://help.expensify.com/articles/expensify-classic/connections/Rippling +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Sage-Intacct.html,https://help.expensify.com/expensify-classic/hubs/connections/sage-intacct +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/TravelPerk.html,https://help.expensify.com/articles/expensify-classic/connections/TravelPerk +https://help.expensify.com/articles/expensify-classic/integrations/travel-integrations/Uber.html,https://help.expensify.com/articles/expensify-classic/connections/Uber +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Workday.html,https://help.expensify.com/articles/expensify-classic/connections/Workday +https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Xero.html,https://help.expensify.com/expensify-classic/hubs/connections/xero +https://help.expensify.com/articles/expensify-classic/integrations/HR-integrations/Zenefits.html,https://help.expensify.com/articles/expensify-classic/connections/Zenefits +https://help.expensify.com/articles/expensify-classic/settings/Close-or-reopen-account,https://help.expensify.com/articles/expensify-classic/settings/account-settings/Close-or-reopen-account +https://help.expensify.com/articles/new-expensify/connections/Set-Up-NetSuite-Connection,https://help.expensify.com/articles/new-expensify/connections/netsuite/Connect-to-NetSuite +https://help.expensify.com/articles/new-expensify/connections/Set-Up-NetSuite-Connection.html,https://help.expensify.com/articles/new-expensify/connections/netsuite/Connect-to-NetSuite +https://help.expensify.com/articles/new-expensify/connections/Set-up-QuickBooks-Online-connection,https://help.expensify.com/articles/new-expensify/connections/quickbooks-online/Connect-to-QuickBooks-Online +https://help.expensify.com/articles/new-expensify/connections/Set-up-QuickBooks-Online-connection.html,https://help.expensify.com/articles/new-expensify/connections/quickbooks-online/Connect-to-QuickBooks-Online +https://help.expensify.com/articles/new-expensify/connections/Set-Up-Sage-Intacct-connection,https://help.expensify.com/articles/new-expensify/connections/sage-intacct/Connect-to-Sage-Intacct +https://help.expensify.com/articles/new-expensify/connections/Set-Up-Sage-Intacct-connection.html,https://help.expensify.com/articles/new-expensify/connections/sage-intacct/Connect-to-Sage-Intacct +https://help.expensify.com/articles/new-expensify/connections/Set-up-Xero-connection,https://help.expensify.com/articles/new-expensify/connections/xero/Connect-to-Xero +https://help.expensify.com/articles/new-expensify/connections/Set-up-Xero-connection.html,https://help.expensify.com/articles/new-expensify/connections/xero/Connect-to-Xero \ No newline at end of file diff --git a/fastlane/Fastfile b/fastlane/Fastfile index af9e798d2343..2560e48728c5 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -10,6 +10,8 @@ # https://docs.fastlane.tools/plugins/available-plugins # +require 'ostruct' + skip_docs opt_out_usage diff --git a/ios/NewApp_AdHoc.mobileprovision.gpg b/ios/NewApp_AdHoc.mobileprovision.gpg index 32ed6ba30059..d5f3c582327d 100644 Binary files a/ios/NewApp_AdHoc.mobileprovision.gpg and b/ios/NewApp_AdHoc.mobileprovision.gpg differ diff --git a/ios/NewApp_AdHoc_Notification_Service.mobileprovision.gpg b/ios/NewApp_AdHoc_Notification_Service.mobileprovision.gpg index 5712b0d86b19..8300bd34ef76 100644 Binary files a/ios/NewApp_AdHoc_Notification_Service.mobileprovision.gpg and b/ios/NewApp_AdHoc_Notification_Service.mobileprovision.gpg differ diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index f86952ca7aca..3afc8d4e6cf0 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -388,6 +388,7 @@ FBC7D704E4E9CC08E91D7919 /* [CP] Copy Pods Resources */, 9FF963998EFF771D82D473D2 /* [CP-User] [RNFB] Core Configuration */, A2BE84E8C8EFD6C81A2B41F1 /* [CP-User] [RNFB] Crashlytics Configuration */, + 498240F82C49553900C15857 /* Run Fullstory Asset Uploader */, ); buildRules = ( ); @@ -620,6 +621,24 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; + 498240F82C49553900C15857 /* Run Fullstory Asset Uploader */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Run Fullstory Asset Uploader"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/FullStory/tools/FullStoryCommandLine\" \"${CONFIGURATION_BUILD_DIR}/${WRAPPER_NAME}\"\n"; + }; 5CF45ABA52C0BB0D7B9D139A /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -1561,7 +1580,11 @@ "$(inherited)", "-DRN_FABRIC_ENABLED", ); - OTHER_LDFLAGS = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Wl", + "-ld_classic", + ); PRODUCT_BUNDLE_IDENTIFIER = ""; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; @@ -1629,7 +1652,11 @@ "$(inherited)", "-DRN_FABRIC_ENABLED", ); - OTHER_LDFLAGS = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Wl", + "-ld_classic", + ); PRODUCT_BUNDLE_IDENTIFIER = ""; PRODUCT_NAME = ""; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; @@ -1707,7 +1734,11 @@ "$(inherited)", "-DRN_FABRIC_ENABLED", ); - OTHER_LDFLAGS = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Wl", + "-ld_classic", + ); PRODUCT_BUNDLE_IDENTIFIER = ""; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; @@ -1852,7 +1883,11 @@ "$(inherited)", "-DRN_FABRIC_ENABLED", ); - OTHER_LDFLAGS = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Wl", + "-ld_classic", + ); PRODUCT_BUNDLE_IDENTIFIER = ""; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; @@ -1989,7 +2024,11 @@ "$(inherited)", "-DRN_FABRIC_ENABLED", ); - OTHER_LDFLAGS = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Wl", + "-ld_classic", + ); PRODUCT_BUNDLE_IDENTIFIER = ""; PRODUCT_NAME = ""; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; @@ -2124,7 +2163,11 @@ "$(inherited)", "-DRN_FABRIC_ENABLED", ); - OTHER_LDFLAGS = "$(inherited)"; + OTHER_LDFLAGS = ( + "$(inherited)", + "-Wl", + "-ld_classic", + ); PRODUCT_BUNDLE_IDENTIFIER = ""; PRODUCT_NAME = ""; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 2826f7e51db9..ab8d16cdb230 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -19,7 +19,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 9.0.6 + 9.0.14 CFBundleSignature ???? CFBundleURLTypes @@ -40,11 +40,13 @@ CFBundleVersion - 9.0.6.0 + 9.0.14.1 FullStory OrgId o-1WN56P-na1 + RecordOnStart + ITSAppUsesNonExemptEncryption diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index cf3e420de4e7..52d34bc7f3d0 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 9.0.6 + 9.0.14 CFBundleSignature ???? CFBundleVersion - 9.0.6.0 + 9.0.14.1 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 58cdb65c40e9..92d9339a2451 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -11,9 +11,9 @@ CFBundleName $(PRODUCT_NAME) CFBundleShortVersionString - 9.0.6 + 9.0.14 CFBundleVersion - 9.0.6.0 + 9.0.14.1 NSExtension NSExtensionPointIdentifier diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 29ab90c4b7db..a2d1e0617a1d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -303,7 +303,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - Plaid (5.2.1) + - Plaid (5.6.0) - PromisesObjC (2.4.0) - RCT-Folly (2022.05.16.00): - boost @@ -1257,7 +1257,7 @@ PODS: - React-Codegen - React-Core - ReactCommon/turbomodule/core - - react-native-geolocation (3.2.1): + - react-native-geolocation (3.3.0): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -1400,10 +1400,10 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-plaid-link-sdk (11.5.0): + - react-native-plaid-link-sdk (11.11.0): - glog - hermes-engine - - Plaid (~> 5.2.0) + - Plaid (~> 5.6.0) - RCT-Folly (= 2022.05.16.00) - RCTRequired - RCTTypeSafety @@ -1439,7 +1439,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-release-profiler (0.1.6): + - react-native-release-profiler (0.2.1): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -1871,7 +1871,7 @@ PODS: - RNGoogleSignin (10.0.1): - GoogleSignIn (~> 7.0) - React-Core - - RNLiveMarkdown (0.1.91): + - RNLiveMarkdown (0.1.107): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -1889,9 +1889,9 @@ PODS: - React-utils - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNLiveMarkdown/common (= 0.1.91) + - RNLiveMarkdown/common (= 0.1.107) - Yoga - - RNLiveMarkdown/common (0.1.91): + - RNLiveMarkdown/common (0.1.107): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -1935,7 +1935,7 @@ PODS: - ReactCommon/turbomodule/core - Turf - Yoga - - RNPermissions (3.9.3): + - RNPermissions (3.10.1): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -2034,7 +2034,7 @@ PODS: - RNSound/Core (= 0.11.2) - RNSound/Core (0.11.2): - React-Core - - RNSVG (14.1.0): + - RNSVG (15.4.0): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -2052,9 +2052,9 @@ PODS: - React-utils - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - - RNSVG/common (= 14.1.0) + - RNSVG/common (= 15.4.0) - Yoga - - RNSVG/common (14.1.0): + - RNSVG/common (15.4.0): - glog - hermes-engine - RCT-Folly (= 2022.05.16.00) @@ -2533,7 +2533,7 @@ SPEC CHECKSUMS: nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 Onfido: f3af62ea1c9a419589c133e3e511e5d2c4f3f8af onfido-react-native-sdk: 3e3b0dd70afa97410fb318d54c6a415137968ef2 - Plaid: 7829e84db6d766a751c91a402702946d2977ddcb + Plaid: c32f22ffce5ec67c9e6147eaf6c4d7d5f8086d89 PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 RCT-Folly: 7169b2b1c44399c76a47b5deaaba715eeeb476c0 RCTRequired: ab7f915c15569f04a49669e573e6e319a53f9faa @@ -2562,7 +2562,7 @@ SPEC CHECKSUMS: react-native-cameraroll: f373bebbe9f6b7c3fd2a6f97c5171cda574cf957 react-native-config: 5ce986133b07fc258828b20b9506de0e683efc1c react-native-document-picker: 8532b8af7c2c930f9e202aac484ac785b0f4f809 - react-native-geolocation: f9e92eb774cb30ac1e099f34b3a94f03b4db7eb3 + react-native-geolocation: 580c86eb531c0aaf7a14bc76fd2983ce47ca58aa react-native-image-picker: f8a13ff106bcc7eb00c71ce11fdc36aac2a44440 react-native-key-command: 28ccfa09520e7d7e30739480dea4df003493bfe8 react-native-keyboard-controller: 47c01b0741ae5fc84e53cf282e61cfa5c2edb19b @@ -2571,9 +2571,9 @@ SPEC CHECKSUMS: react-native-pager-view: ccd4bbf9fc7effaf8f91f8dae43389844d9ef9fa react-native-pdf: 762369633665ec02ac227aefe2f4558b92475c23 react-native-performance: fb21ff0c9bd7a10789c69d948f25b0067d29f7a9 - react-native-plaid-link-sdk: 2a91ef7e257ae16d180a1ca14ba3041ae0836fbf + react-native-plaid-link-sdk: ba40d1b13cca4b946974fafd9ae278e0fb697d87 react-native-quick-sqlite: e3ab3e0a29d8c705f47a60aaa6ceaa42eb6a9ec1 - react-native-release-profiler: 14ccdc0eeb03bedf625cf68d53d80275a81b19dd + react-native-release-profiler: a77d4f291b92e48d3d4a574deed19bd1b513ac98 react-native-render-html: 96c979fe7452a0a41559685d2f83b12b93edac8c react-native-safe-area-context: 9d79895b60b8be151fdf6faef9d2d0591eeecc63 react-native-view-shot: 6b7ed61d77d88580fed10954d45fad0eb2d47688 @@ -2614,16 +2614,16 @@ SPEC CHECKSUMS: RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 RNGestureHandler: 74b7b3d06d667ba0bbf41da7718f2607ae0dfe8f RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 - RNLiveMarkdown: 24fbb7370eefee2f325fb64cfe904b111ffcd81b + RNLiveMarkdown: f0c641a0bcf5fdea3ec1bb52a64b30ff88d25c1f RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 rnmapbox-maps: df8fe93dbd251f25022f4023d31bc04160d4d65c - RNPermissions: 0b61d30d21acbeafe25baaa47d9bae40a0c65216 + RNPermissions: d2392b754e67bc14491f5b12588bef2864e783f3 RNReactNativeHapticFeedback: 616c35bdec7d20d4c524a7949ca9829c09e35f37 RNReanimated: 323436b1a5364dca3b5f8b1a13458455e0de9efe RNScreens: abd354e98519ed267600b7ee64fdcb8e060b1218 RNShare: 2a4cdfc0626ad56b0ef583d424f2038f772afe58 RNSound: 6c156f925295bdc83e8e422e7d8b38d33bc71852 - RNSVG: 18f1381e046be2f1c30b4724db8d0c966238089f + RNSVG: 8c067e7203053d4c82f456cbeab1fe509ac797dd SDWebImage: 750adf017a315a280c60fde706ab1e552a3ae4e9 SDWebImageAVIFCoder: 8348fef6d0ec69e129c66c9fe4d74fbfbf366112 SDWebImageSVGCoder: 15a300a97ec1c8ac958f009c02220ac0402e936c @@ -2635,4 +2635,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: d5e281e5370cb0211a104efd90eb5fa7af936e14 -COCOAPODS: 1.15.2 +COCOAPODS: 1.15.2 \ No newline at end of file diff --git a/ios/link-assets-manifest.json b/ios/link-assets-manifest.json index a3ac1c2332f9..1c59d667fca1 100644 --- a/ios/link-assets-manifest.json +++ b/ios/link-assets-manifest.json @@ -1,5 +1,5 @@ { - "migIndex": 1, + "migIndex": 2, "data": [ { "path": "assets/fonts/native/ExpensifyMono-Bold.otf", diff --git a/package-lock.json b/package-lock.json index 64f5f7a6a94d..85781fff1528 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "new.expensify", - "version": "9.0.6-0", + "version": "9.0.14-1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.6-0", + "version": "9.0.14-1", "hasInstallScript": true, "license": "MIT", "dependencies": { "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.91", + "@expensify/react-native-live-markdown": "^0.1.107", "@expo/metro-runtime": "~3.1.1", "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-listformat": "^7.2.2", @@ -26,12 +26,12 @@ "@fullstory/react-native": "^1.4.2", "@gorhom/portal": "^1.0.14", "@invertase/react-native-apple-authentication": "^2.2.2", - "@kie/act-js": "^2.6.0", + "@kie/act-js": "^2.6.2", "@kie/mock-github": "2.0.1", "@onfido/react-native-sdk": "10.6.0", "@react-native-camera-roll/camera-roll": "7.4.0", "@react-native-clipboard/clipboard": "^1.13.2", - "@react-native-community/geolocation": "3.2.1", + "@react-native-community/geolocation": "3.3.0", "@react-native-community/netinfo": "11.2.1", "@react-native-firebase/analytics": "^12.3.0", "@react-native-firebase/app": "^12.3.0", @@ -55,7 +55,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "2.0.26", + "expensify-common": "2.0.57", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", @@ -102,23 +102,23 @@ "react-native-linear-gradient": "^2.8.1", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-onyx": "2.0.56", + "react-native-onyx": "2.0.57", "react-native-pager-view": "6.2.3", "react-native-pdf": "6.7.3", "react-native-performance": "^5.1.0", - "react-native-permissions": "^3.9.3", + "react-native-permissions": "^3.10.0", "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#da50d2c5c54e268499047f9cc98b8df4196c1ddf", - "react-native-plaid-link-sdk": "11.5.0", - "react-native-qrcode-svg": "^6.2.0", + "react-native-plaid-link-sdk": "11.11.0", + "react-native-qrcode-svg": "git+https://github.com/Expensify/react-native-qrcode-svg", "react-native-quick-sqlite": "git+https://github.com/margelo/react-native-quick-sqlite#abc91857d4b3efb2020ec43abd2a508563b64316", "react-native-reanimated": "^3.8.0", - "react-native-release-profiler": "^0.1.6", + "react-native-release-profiler": "^0.2.1", "react-native-render-html": "6.3.1", "react-native-safe-area-context": "4.8.2", "react-native-screens": "3.32.0", "react-native-share": "^10.0.2", "react-native-sound": "^0.11.2", - "react-native-svg": "14.1.0", + "react-native-svg": "15.4.0", "react-native-tab-view": "^3.5.2", "react-native-url-polyfill": "^2.0.0", "react-native-view-shot": "3.8.0", @@ -155,6 +155,7 @@ "@octokit/core": "4.0.4", "@octokit/plugin-paginate-rest": "3.1.0", "@octokit/plugin-throttling": "4.1.0", + "@octokit/webhooks-types": "^7.5.1", "@perf-profiler/profiler": "^0.10.10", "@perf-profiler/reporter": "^0.9.0", "@perf-profiler/types": "^0.8.0", @@ -212,7 +213,7 @@ "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", "electron": "^29.4.1", - "electron-builder": "24.13.2", + "electron-builder": "25.0.0", "eslint": "^8.57.0", "eslint-config-airbnb-typescript": "^18.0.0", "eslint-config-expensify": "^2.0.52", @@ -232,7 +233,9 @@ "jest-transformer-svg": "^2.0.1", "memfs": "^4.6.0", "onchange": "^7.1.0", + "openai": "^4.47.2", "patch-package": "^8.0.0", + "peggy": "^4.0.3", "portfinder": "^1.0.28", "prettier": "^2.8.8", "pusher-js-mock": "^0.3.3", @@ -2981,8 +2984,9 @@ }, "node_modules/@develar/schema-utils": { "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.0", "ajv-keywords": "^3.4.1" @@ -2997,8 +3001,9 @@ }, "node_modules/@develar/schema-utils/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3012,16 +3017,18 @@ }, "node_modules/@develar/schema-utils/node_modules/ajv-keywords": { "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, - "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } }, "node_modules/@develar/schema-utils/node_modules/json-schema-traverse": { "version": "0.4.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", @@ -3106,9 +3113,10 @@ } }, "node_modules/@electron/asar": { - "version": "3.2.8", + "version": "3.2.10", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.10.tgz", + "integrity": "sha512-mvBSwIBUeiRscrCeJE1LwctAriBj65eUDm0Pc11iE5gRwzkmsdbS7FnZ1XUWjpSeQWL1L5g12Fc/SchPM9DUOw==", "dev": true, - "license": "MIT", "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", @@ -3123,8 +3131,9 @@ }, "node_modules/@electron/asar/node_modules/commander": { "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6" } @@ -3187,9 +3196,10 @@ } }, "node_modules/@electron/notarize": { - "version": "2.2.1", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.3.2.tgz", + "integrity": "sha512-zfayxCe19euNwRycCty1C7lF7snk9YwfRpB5M8GLr1a4ICH63znxaPNAubrMvj0yDvVozqfgsdYpXVUnpWBDpg==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.1", @@ -3200,9 +3210,10 @@ } }, "node_modules/@electron/osx-sign": { - "version": "1.0.5", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.0.tgz", + "integrity": "sha512-TEXhxlYSDRr9JWK5nWdOv5MtuUdaZ412uxIIEQ0hLt80o0HYWtQJBlW5QmrQDMtebzATaOjKG9UfCzLyA90zWQ==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", @@ -3221,8 +3232,9 @@ }, "node_modules/@electron/osx-sign/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -3234,8 +3246,9 @@ }, "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", "dev": true, - "license": "MIT", "engines": { "node": ">= 8.0.0" }, @@ -3243,21 +3256,172 @@ "url": "https://github.com/sponsors/gjtorikian/" } }, + "node_modules/@electron/rebuild": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.6.0.tgz", + "integrity": "sha512-zF4x3QupRU3uNGaP5X1wjpmcjfw1H87kyqZ00Tc3HvriV+4gmOGuvQjGNkrJuXdsApssdNyVwLsy+TaeTGGcVw==", + "dev": true, + "dependencies": { + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "detect-libc": "^2.0.1", + "fs-extra": "^10.0.0", + "got": "^11.7.0", + "node-abi": "^3.45.0", + "node-api-version": "^0.2.0", + "node-gyp": "^9.0.0", + "ora": "^5.1.0", + "read-binary-file-arch": "^1.0.6", + "semver": "^7.3.5", + "tar": "^6.0.5", + "yargs": "^17.0.1" + }, + "bin": { + "electron-rebuild": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/@electron/rebuild/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@electron/rebuild/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@electron/rebuild/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@electron/rebuild/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@electron/rebuild/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/rebuild/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@electron/rebuild/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@electron/universal": { - "version": "1.5.1", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", + "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", "dev": true, - "license": "MIT", "dependencies": { - "@electron/asar": "^3.2.1", - "@malept/cross-spawn-promise": "^1.1.0", + "@electron/asar": "^3.2.7", + "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", - "dir-compare": "^3.0.0", - "fs-extra": "^9.0.1", - "minimatch": "^3.0.4", - "plist": "^3.0.4" + "dir-compare": "^4.2.0", + "fs-extra": "^11.1.1", + "minimatch": "^9.0.3", + "plist": "^3.1.0" }, "engines": { - "node": ">=8.6" + "node": ">=16.4" + } + }, + "node_modules/@electron/universal/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/@electron/universal/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@electron/universal/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { @@ -3784,9 +3948,9 @@ } }, "node_modules/@expensify/react-native-live-markdown": { - "version": "0.1.91", - "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.91.tgz", - "integrity": "sha512-6uQTgwhpvLqQKdtNqSgh45sRuQRXzv/WwyhdvQNge6EYtulyGFqT82GIP+LIGW8Xnl73nzFZTuMKwWxFFR/Cow==", + "version": "0.1.107", + "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.107.tgz", + "integrity": "sha512-0Yhqo1azCu3cTmzv/KkILZX2yPiyFUZNRx+AdMdT18pMxpqTAuBtFV4HM44rlimmpT3vgwQ1F/0C0AfRAk5dZA==", "workspaces": [ "parser", "example", @@ -6123,28 +6287,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/console/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/console/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/@jest/console/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -6248,28 +6390,6 @@ } } }, - "node_modules/@jest/core/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/core/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/@jest/core/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -6338,86 +6458,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/create-cache-key-function/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/@types/yargs": { - "version": "17.0.31", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/@jest/create-cache-key-function/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/create-cache-key-function/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/environment": { "version": "29.7.0", "license": "MIT", @@ -6431,86 +6471,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/environment/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/environment/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@jest/environment/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/environment/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/environment/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/environment/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/@jest/environment/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/environment/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/expect": { "version": "29.6.2", "license": "MIT", @@ -6547,86 +6507,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/fake-timers/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/fake-timers/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@jest/fake-timers/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/fake-timers/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/fake-timers/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/fake-timers/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/@jest/fake-timers/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/fake-timers/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/globals": { "version": "29.5.0", "license": "MIT", @@ -6640,86 +6520,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/globals/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/globals/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@jest/globals/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/globals/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/globals/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/globals/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/@jest/globals/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/globals/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/reporters": { "version": "29.4.1", "license": "MIT", @@ -6761,28 +6561,6 @@ } } }, - "node_modules/@jest/reporters/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/reporters/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/@jest/reporters/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -6902,86 +6680,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/test-result/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@jest/test-result/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@jest/test-result/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/test-result/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@jest/test-result/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/@jest/test-result/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/test-result/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/test-sequencer": { "version": "29.4.1", "license": "MIT", @@ -7019,28 +6717,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/@jest/transform/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -7118,10 +6794,7 @@ "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "@jest/schemas": "^29.6.3", "@types/istanbul-lib-coverage": "^2.0.0", @@ -7136,10 +6809,7 @@ }, "node_modules/@jest/types/node_modules/ansi-styles": { "version": "4.3.0", - "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -7152,10 +6822,7 @@ }, "node_modules/@jest/types/node_modules/chalk": { "version": "4.1.2", - "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -7169,10 +6836,7 @@ }, "node_modules/@jest/types/node_modules/color-convert": { "version": "2.0.1", - "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "color-name": "~1.1.4" }, @@ -7182,27 +6846,18 @@ }, "node_modules/@jest/types/node_modules/color-name": { "version": "1.1.4", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true + "license": "MIT" }, "node_modules/@jest/types/node_modules/has-flag": { "version": "4.0.0", - "dev": true, "license": "MIT", - "optional": true, - "peer": true, "engines": { "node": ">=8" } }, "node_modules/@jest/types/node_modules/supports-color": { "version": "7.2.0", - "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -7284,9 +6939,10 @@ } }, "node_modules/@kie/act-js": { - "version": "2.6.0", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@kie/act-js/-/act-js-2.6.2.tgz", + "integrity": "sha512-i366cfWluUi55rPZ6e9/aWH4tnw3Q6W1CKh9Gz6QjTvbAtS4KnUUy33I9aMXS6uwa0haw6MSahMM37vmuFCVpQ==", "hasInstallScript": true, - "license": "SEE LICENSE IN LICENSE", "dependencies": { "@kie/mock-github": "^2.0.0", "adm-zip": "^0.5.10", @@ -7416,7 +7072,9 @@ } }, "node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", + "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", "dev": true, "funding": [ { @@ -7428,18 +7086,18 @@ "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" } ], - "license": "Apache-2.0", "dependencies": { "cross-spawn": "^7.0.1" }, "engines": { - "node": ">= 10" + "node": ">= 12.13.0" } }, "node_modules/@malept/flatpak-bundler": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.0", @@ -7865,6 +7523,12 @@ "@octokit/openapi-types": "^12.11.0" } }, + "node_modules/@octokit/webhooks-types": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.5.1.tgz", + "integrity": "sha512-1dozxWEP8lKGbtEu7HkRbK1F/nIPuJXNfT0gd96y6d3LcHZTtRtlf8xz3nicSJfesADxJyDh+mWBOsdLkqgzYw==", + "dev": true + }, "node_modules/@onfido/react-native-sdk": { "version": "10.6.0", "license": "MIT", @@ -7879,14 +7543,41 @@ "react-native": ">=0.70.0 <1.0.x" } }, + "node_modules/@peggyjs/from-mem": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@peggyjs/from-mem/-/from-mem-1.3.0.tgz", + "integrity": "sha512-kzGoIRJjkg3KuGI4bopz9UvF3KguzfxalHRDEIdqEZUe45xezsQ6cx30e0RKuxPUexojQRBfu89Okn7f4/QXsw==", + "dev": true, + "dependencies": { + "semver": "7.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@peggyjs/from-mem/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@perf-profiler/android": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@perf-profiler/android/-/android-0.12.1.tgz", - "integrity": "sha512-t4E2tfj9UdJw5JjhFPLMzrsu3NkKSyiZyeIyd70HX9d3anWqNK47XuQV+qkDPMjWaoU+CTlj1SuNnIOqEkCpSA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@perf-profiler/android/-/android-0.13.0.tgz", + "integrity": "sha512-4lUQjJNHFAYB5npts5JLrPaPNpIOEAAjfpeTQOOgBNLT1NW50WWSGuvV2pAdnMi7T28cXs3aUziJJ30cNrSvNg==", "dev": true, "dependencies": { "@perf-profiler/logger": "^0.3.3", - "@perf-profiler/profiler": "^0.10.10", + "@perf-profiler/profiler": "^0.10.11", "@perf-profiler/types": "^0.8.0", "commander": "^12.0.0", "lodash": "^4.17.21" @@ -7905,24 +7596,24 @@ } }, "node_modules/@perf-profiler/ios": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@perf-profiler/ios/-/ios-0.3.2.tgz", - "integrity": "sha512-2jYyHXFO3xe5BdvU1Ttt+Uw2nAf10B3/mcx4FauJwSdJ+nlOAKIvxmZDvMcipCZZ63uc+HWsYndhziJZVQ7VUw==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@perf-profiler/ios/-/ios-0.3.3.tgz", + "integrity": "sha512-dbb9lVKOyj1VjinuxrnbfI3FT0+uhH3xclqLQH7rQFA4d93dusjC/s3RzlnCXRNPFPDy5TTmkiIg3xM/6P3/2g==", "dev": true, "dependencies": { - "@perf-profiler/ios-instruments": "^0.3.2", + "@perf-profiler/ios-instruments": "^0.3.3", "@perf-profiler/logger": "^0.3.3", "@perf-profiler/types": "^0.8.0" } }, "node_modules/@perf-profiler/ios-instruments": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@perf-profiler/ios-instruments/-/ios-instruments-0.3.2.tgz", - "integrity": "sha512-uox5arQscpRuGWfzBrTpsn6eJq0ErdjPlU0FMbN4Cv5akQC11ejKWmgV6y4FR/0YIET9uiiXMtnwyEBgUunYGQ==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@perf-profiler/ios-instruments/-/ios-instruments-0.3.3.tgz", + "integrity": "sha512-e3UmlWuNUOuNbJPWg6aLOVd9wRKe3RYCqwwUgxMNIAwa5QBxaVYBf2pt3+HRsYReh2qm1yvqW7LU9zP+AJ7/7g==", "dev": true, "dependencies": { "@perf-profiler/logger": "^0.3.3", - "@perf-profiler/profiler": "^0.10.10", + "@perf-profiler/profiler": "^0.10.11", "@perf-profiler/types": "^0.8.0", "commander": "^12.0.0", "fast-xml-parser": "^4.2.7" @@ -7963,13 +7654,13 @@ } }, "node_modules/@perf-profiler/profiler": { - "version": "0.10.10", - "resolved": "https://registry.npmjs.org/@perf-profiler/profiler/-/profiler-0.10.10.tgz", - "integrity": "sha512-kvVC6VQ7pBdthcWEcLTua+iDj0ZkcmYYL9gXHa9Dl7jYkZI4cOeslJZ1vuGfIcC168JwAVrB8UYhgoSgss/MWQ==", + "version": "0.10.11", + "resolved": "https://registry.npmjs.org/@perf-profiler/profiler/-/profiler-0.10.11.tgz", + "integrity": "sha512-nu/zakhG5wRi0tCw4SjTCZJh9e/x9YABAOChh3lGI6CESsFzc1Gi2Vrr+2sytN8dpiTDYCCbECC2EalD7ZKvtg==", "dev": true, "dependencies": { - "@perf-profiler/android": "^0.12.1", - "@perf-profiler/ios": "^0.3.2", + "@perf-profiler/android": "^0.13.0", + "@perf-profiler/ios": "^0.3.3", "@perf-profiler/types": "^0.8.0" } }, @@ -9044,9 +8735,9 @@ } }, "node_modules/@react-native-community/cli-server-api/node_modules/ws": { - "version": "7.5.9", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "engines": { "node": ">=8.3.0" }, @@ -9554,9 +9245,9 @@ "license": "MIT" }, "node_modules/@react-native-community/geolocation": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@react-native-community/geolocation/-/geolocation-3.2.1.tgz", - "integrity": "sha512-/+HNzuRl4UCMma7KK+KYL8k2nxAGuW+DGxqmqfpiqKBlCkCUbuFHaZZdqVD6jpsn9r/ghe583ECLmd9SV9I4Bw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@react-native-community/geolocation/-/geolocation-3.3.0.tgz", + "integrity": "sha512-7DFeuotH7m7ImoXffN3TmlGSFn1XjvsaphPort0XZKipssYbdHiKhVVWG+jzisvDhcXikUc6nbUJgddVBL6RDg==", "engines": { "node": ">=18.0.0" }, @@ -17626,8 +17317,9 @@ }, "node_modules/@types/debug": { "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/ms": "*" } @@ -17714,8 +17406,9 @@ }, "node_modules/@types/fs-extra": { "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*" } @@ -17902,8 +17595,9 @@ }, "node_modules/@types/ms": { "version": "0.7.34", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "dev": true }, "node_modules/@types/node": { "version": "20.11.5", @@ -17912,6 +17606,30 @@ "undici-types": "~5.26.4" } }, + "node_modules/@types/node-fetch": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "dev": true, + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/@types/node-forge": { "version": "1.3.11", "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", @@ -17934,8 +17652,9 @@ }, "node_modules/@types/plist": { "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "@types/node": "*", @@ -18143,9 +17862,10 @@ "dev": true }, "node_modules/@types/verror": { - "version": "1.10.9", + "version": "1.10.10", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.10.tgz", + "integrity": "sha512-l4MM0Jppn18hb9xmM6wwD1uTdShpf9Pn80aXTStnK1C94gtPvJcV2FrDmbOQUAQfJ1cKZHktkQUDwEqaAKXMMg==", "dev": true, - "license": "MIT", "optional": true }, "node_modules/@types/webpack": { @@ -18181,10 +17901,7 @@ "version": "17.0.32", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", - "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "@types/yargs-parser": "*" } @@ -18918,8 +18635,9 @@ }, "node_modules/7zip-bin": { "version": "5.2.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true }, "node_modules/abab": { "version": "2.0.6", @@ -18927,8 +18645,8 @@ }, "node_modules/abbrev": { "version": "1.1.1", - "license": "ISC", - "optional": true + "devOptional": true, + "license": "ISC" }, "node_modules/abort-controller": { "version": "3.0.0", @@ -19046,6 +18764,18 @@ "node": ">= 6.0.0" } }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/aggregate-error": { "version": "3.1.0", "license": "MIT", @@ -19266,29 +18996,32 @@ } }, "node_modules/app-builder-bin": { - "version": "4.0.0", - "dev": true, - "license": "MIT" + "version": "5.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.4.tgz", + "integrity": "sha512-4MitKmOtfTdMONrtRoiaqJ6HtlVZXgrNX1PNdEzEHSAoXU85x7s+mo0IhAS9K9qgjyTVuLrM1E/HAMp5qGyoOA==", + "dev": true }, "node_modules/app-builder-lib": { - "version": "24.13.2", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-25.0.0.tgz", + "integrity": "sha512-GIx0n/QvbeObY8rQTTp08UPn4pS9xSGZLq6cPRy/CyX/mTNN9pO/uU28MWgqjnYXk0bf/595vzDdAijuDyz5Zw==", "dev": true, - "license": "MIT", "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/notarize": "2.2.1", - "@electron/osx-sign": "1.0.5", - "@electron/universal": "1.5.1", + "@electron/notarize": "2.3.2", + "@electron/osx-sign": "1.3.0", + "@electron/rebuild": "3.6.0", + "@electron/universal": "2.0.1", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "builder-util": "25.0.0", + "builder-util-runtime": "9.2.5", "chromium-pickle-js": "^0.2.0", "debug": "^4.3.4", "ejs": "^3.1.8", - "electron-publish": "24.13.1", + "electron-publish": "25.0.0", "form-data": "^4.0.0", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", @@ -19296,8 +19029,9 @@ "isbinaryfile": "^5.0.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", - "minimatch": "^5.1.1", - "read-config-file": "6.3.2", + "minimatch": "^10.0.0", + "read-config-file": "6.4.0", + "resedit": "^1.7.0", "sanitize-filename": "^1.6.3", "semver": "^7.3.8", "tar": "^6.1.12", @@ -19307,27 +19041,30 @@ "node": ">=14.0.0" }, "peerDependencies": { - "dmg-builder": "24.13.2", - "electron-builder-squirrel-windows": "24.13.2" + "dmg-builder": "25.0.0", + "electron-builder-squirrel-windows": "25.0.0" } }, "node_modules/app-builder-lib/node_modules/argparse": { "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/app-builder-lib/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/app-builder-lib/node_modules/form-data": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, - "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -19339,8 +19076,9 @@ }, "node_modules/app-builder-lib/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -19352,8 +19090,9 @@ }, "node_modules/app-builder-lib/node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -19362,14 +19101,18 @@ } }, "node_modules/app-builder-lib/node_modules/minimatch": { - "version": "5.1.6", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", + "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/app-root-dir": { @@ -19389,13 +19132,14 @@ }, "node_modules/aproba": { "version": "1.2.0", - "license": "ISC", - "optional": true + "devOptional": true, + "license": "ISC" }, "node_modules/archiver": { "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^2.1.0", @@ -19412,8 +19156,9 @@ }, "node_modules/archiver-utils": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "glob": "^7.1.4", @@ -19433,8 +19178,9 @@ }, "node_modules/archiver/node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "inherits": "^2.0.3", @@ -19706,8 +19452,9 @@ }, "node_modules/assert-plus": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "dev": true, - "license": "MIT", "optional": true, "engines": { "node": ">=0.8" @@ -19750,8 +19497,9 @@ }, "node_modules/astral-regex": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, - "license": "MIT", "optional": true, "engines": { "node": ">=8" @@ -19771,8 +19519,9 @@ }, "node_modules/async-exit-hook": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -20913,13 +20662,15 @@ }, "node_modules/bluebird": { "version": "3.7.2", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true }, "node_modules/bluebird-lst": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", "dev": true, - "license": "MIT", "dependencies": { "bluebird": "^3.5.5" } @@ -21239,17 +20990,6 @@ "node": "*" } }, - "node_modules/buffer-equal": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/buffer-fill": { "version": "1.0.0", "license": "MIT" @@ -21263,15 +21003,16 @@ "license": "MIT" }, "node_modules/builder-util": { - "version": "24.13.1", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-25.0.0.tgz", + "integrity": "sha512-cI8zIsipo/gciZ5jGEA1qYL5Em1N6cWoNMpeJWZAfOs3H9s5zQWKnAS7rTdlJpsJ88gEmL5/32yeXUF2Uzxw6w==", "dev": true, - "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", "7zip-bin": "~5.2.0", - "app-builder-bin": "4.0.0", + "app-builder-bin": "v5.0.0-alpha.4", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.2.4", + "builder-util-runtime": "9.2.5", "chalk": "^4.1.2", "cross-spawn": "^7.0.3", "debug": "^4.3.4", @@ -21286,9 +21027,10 @@ } }, "node_modules/builder-util-runtime": { - "version": "9.2.4", + "version": "9.2.5", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.2.5.tgz", + "integrity": "sha512-HjIDfhvqx/8B3TDN4GbABQcgpewTU4LMRTQPkVpKYV3lsuxEJoIfvg09GyWTNmfVNSUAYf+fbTN//JX4TH20pg==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" @@ -21299,8 +21041,9 @@ }, "node_modules/builder-util/node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -21313,13 +21056,15 @@ }, "node_modules/builder-util/node_modules/argparse": { "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/builder-util/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -21333,8 +21078,9 @@ }, "node_modules/builder-util/node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -21344,13 +21090,15 @@ }, "node_modules/builder-util/node_modules/color-name": { "version": "1.1.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/builder-util/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -21362,16 +21110,18 @@ }, "node_modules/builder-util/node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/builder-util/node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -21381,8 +21131,9 @@ }, "node_modules/builder-util/node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -21775,8 +21526,9 @@ }, "node_modules/chromium-pickle-js": { "version": "0.2.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true }, "node_modules/ci-info": { "version": "3.8.0", @@ -21982,8 +21734,9 @@ }, "node_modules/cli-truncate": { "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "slice-ansi": "^3.0.0", @@ -22136,8 +21889,8 @@ }, "node_modules/color-support": { "version": "1.1.3", + "devOptional": true, "license": "ISC", - "optional": true, "bin": { "color-support": "bin.js" } @@ -22202,8 +21955,9 @@ }, "node_modules/compare-version": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -22234,8 +21988,9 @@ }, "node_modules/compress-commons": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "buffer-crc32": "^0.2.13", @@ -22249,8 +22004,9 @@ }, "node_modules/compress-commons/node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "inherits": "^2.0.3", @@ -22415,47 +22171,64 @@ } }, "node_modules/config-file-ts": { - "version": "0.2.6", + "version": "0.2.8-rc1", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", + "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", "dev": true, - "license": "MIT", "dependencies": { - "glob": "^10.3.10", - "typescript": "^5.3.3" + "glob": "^10.3.12", + "typescript": "^5.4.3" } }, "node_modules/config-file-ts/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/config-file-ts/node_modules/glob": { - "version": "10.3.10", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" }, "funding": { "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/config-file-ts/node_modules/minimatch": { - "version": "9.0.3", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -22467,9 +22240,10 @@ } }, "node_modules/config-file-ts/node_modules/minipass": { - "version": "7.0.4", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } @@ -22558,8 +22332,8 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", - "license": "ISC", - "optional": true + "devOptional": true, + "license": "ISC" }, "node_modules/constants-browserify": { "version": "1.0.0", @@ -22777,8 +22551,9 @@ }, "node_modules/crc": { "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "buffer": "^5.1.0" @@ -22786,8 +22561,9 @@ }, "node_modules/crc-32": { "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "dev": true, - "license": "Apache-2.0", "peer": true, "bin": { "crc32": "bin/crc32.njs" @@ -22798,8 +22574,9 @@ }, "node_modules/crc32-stream": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "crc-32": "^1.2.0", @@ -22811,8 +22588,9 @@ }, "node_modules/crc32-stream/node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "inherits": "^2.0.3", @@ -23552,8 +23330,8 @@ }, "node_modules/delegates": { "version": "1.0.0", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/denodeify": { "version": "1.2.1", @@ -23614,8 +23392,8 @@ }, "node_modules/detect-libc": { "version": "2.0.1", + "devOptional": true, "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=8" } @@ -23708,12 +23486,13 @@ "license": "MIT" }, "node_modules/dir-compare": { - "version": "3.3.0", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", + "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", "dev": true, - "license": "MIT", "dependencies": { - "buffer-equal": "^1.0.0", - "minimatch": "^3.0.4" + "minimatch": "^3.0.5", + "p-limit": "^3.1.0 " } }, "node_modules/dir-glob": { @@ -23727,13 +23506,14 @@ } }, "node_modules/dmg-builder": { - "version": "24.13.2", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-25.0.0.tgz", + "integrity": "sha512-kXETWCy/JIXS8PHYc8Y0EdSWO02gpf4jleW74hkIp6o9WWTjAdBRw2fAcRBNIEBUJtVHFrgCYsEWh0wKFUB0+A==", "dev": true, - "license": "MIT", "dependencies": { - "app-builder-lib": "24.13.2", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "app-builder-lib": "25.0.0", + "builder-util": "25.0.0", + "builder-util-runtime": "9.2.5", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" @@ -23744,13 +23524,15 @@ }, "node_modules/dmg-builder/node_modules/argparse": { "version": "2.0.1", - "dev": true, - "license": "Python-2.0" + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/dmg-builder/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -23762,8 +23544,9 @@ }, "node_modules/dmg-builder/node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -23773,8 +23556,9 @@ }, "node_modules/dmg-license": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", "dev": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -23798,8 +23582,9 @@ }, "node_modules/dmg-license/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -23814,8 +23599,9 @@ }, "node_modules/dmg-license/node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", "optional": true }, "node_modules/dns-packet": { @@ -23930,20 +23716,31 @@ } }, "node_modules/dotenv": { - "version": "16.3.1", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "url": "https://dotenvx.com" } }, "node_modules/dotenv-expand": { - "version": "5.1.0", + "version": "11.0.6", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.6.tgz", + "integrity": "sha512-8NHi73otpWsZGBSZwwknTXS5pqMOrk9+Ssrna8xCaxkzEpU9OTf9R5ArQGVw03//Zmk9MOwLPng9WwndvpAJ5g==", "dev": true, - "license": "BSD-2-Clause" + "dependencies": { + "dotenv": "^16.4.4" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } }, "node_modules/duplexer": { "version": "0.1.2", @@ -24011,19 +23808,20 @@ } }, "node_modules/electron-builder": { - "version": "24.13.2", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-25.0.0.tgz", + "integrity": "sha512-3nEqF6KnoM206mLz1C70VXWCzXmH2boL82wkpgLB1GXgK3dly6ay/cepI+2BmQT4iWkIHeG8qH9bPjPj0hn+1A==", "dev": true, - "license": "MIT", "dependencies": { - "app-builder-lib": "24.13.2", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "app-builder-lib": "25.0.0", + "builder-util": "25.0.0", + "builder-util-runtime": "9.2.5", "chalk": "^4.1.2", - "dmg-builder": "24.13.2", + "dmg-builder": "25.0.0", "fs-extra": "^10.1.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", - "read-config-file": "6.3.2", + "read-config-file": "6.4.0", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, @@ -24036,21 +23834,23 @@ } }, "node_modules/electron-builder-squirrel-windows": { - "version": "24.13.2", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-25.0.0.tgz", + "integrity": "sha512-bfARwAdye1UkFQZ7NedHZBcOek2lvDDeg/pCaXT4Nrki7gdwrvVY/Be/QJm7Smc6IR/mviozbL9ykUHQ/FSsbw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { - "app-builder-lib": "24.13.2", + "app-builder-lib": "25.0.0", "archiver": "^5.3.1", - "builder-util": "24.13.1", + "builder-util": "25.0.0", "fs-extra": "^10.1.0" } }, "node_modules/electron-builder-squirrel-windows/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -24139,13 +23939,14 @@ } }, "node_modules/electron-publish": { - "version": "24.13.1", + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-25.0.0.tgz", + "integrity": "sha512-8wq3pVLq9bpd/jNKJGIXbeL8B8AovLojtCDkVSuSgrLtxEndqy5JfuadUKPAgbmh1zjholNAHsfHH9FS5yeYAg==", "dev": true, - "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "24.13.1", - "builder-util-runtime": "9.2.4", + "builder-util": "25.0.0", + "builder-util-runtime": "9.2.5", "chalk": "^4.1.2", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", @@ -24154,8 +23955,9 @@ }, "node_modules/electron-publish/node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -24168,8 +23970,9 @@ }, "node_modules/electron-publish/node_modules/chalk": { "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -24183,8 +23986,9 @@ }, "node_modules/electron-publish/node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -24194,13 +23998,15 @@ }, "node_modules/electron-publish/node_modules/color-name": { "version": "1.1.4", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/electron-publish/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -24212,16 +24018,18 @@ }, "node_modules/electron-publish/node_modules/has-flag": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/electron-publish/node_modules/supports-color": { "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, - "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -24284,6 +24092,15 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "license": "MIT", @@ -25974,9 +25791,9 @@ } }, "node_modules/expensify-common": { - "version": "2.0.26", - "resolved": "https://registry.npmjs.org/expensify-common/-/expensify-common-2.0.26.tgz", - "integrity": "sha512-3GORs2xfx78SoKLDh4lXpk4Bx61sAVNnlo23VB803zs7qZz8/Oq3neKedtEJuRAmUps0C1Y5y9xZE8nrPO31nQ==", + "version": "2.0.57", + "resolved": "https://registry.npmjs.org/expensify-common/-/expensify-common-2.0.57.tgz", + "integrity": "sha512-ORAnuvMC4NZRgCTjOrxwW9SjigIP6/TlGGUV4DkCqTaiBriq8Mb2ypzv9LR1jcxDlbt19MuRsW66xMI3sAYLwA==", "dependencies": { "awesome-phonenumber": "^5.4.0", "classnames": "2.5.0", @@ -25990,7 +25807,7 @@ "react-dom": "16.12.0", "semver": "^7.6.2", "simply-deferred": "git+https://github.com/Expensify/simply-deferred.git#77a08a95754660c7bd6e0b6979fdf84e8e831bf5", - "ua-parser-js": "^1.0.37" + "ua-parser-js": "^1.0.38" } }, "node_modules/expensify-common/node_modules/react": { @@ -26027,9 +25844,9 @@ } }, "node_modules/expensify-common/node_modules/ua-parser-js": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", - "integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==", + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", + "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", "funding": [ { "type": "opencollective", @@ -26352,6 +26169,12 @@ "node": ">=8" } }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, "node_modules/express": { "version": "4.18.1", "license": "MIT", @@ -26515,11 +26338,12 @@ }, "node_modules/extsprintf": { "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", "dev": true, "engines": [ "node >=0.6.0" ], - "license": "MIT", "optional": true }, "node_modules/fast-deep-equal": { @@ -26533,6 +26357,8 @@ }, "node_modules/fast-equals": { "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-4.0.3.tgz", + "integrity": "sha512-G3BSX9cfKttjr+2o1O22tYMLq0DPluZnYtq1rXumE1SpL/F/SLIfHx08WYQoWSIpeMYf8sRbJ8++71+v6Pnxfg==", "license": "MIT" }, "node_modules/fast-glob": { @@ -27149,6 +26975,34 @@ "node": ">= 6" } }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "dev": true + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "dev": true, + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, + "node_modules/formdata-node/node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/forwarded": { "version": "0.2.0", "license": "MIT", @@ -27768,8 +27622,8 @@ }, "node_modules/has-unicode": { "version": "2.0.1", - "license": "ISC", - "optional": true + "devOptional": true, + "license": "ISC" }, "node_modules/has-value": { "version": "1.0.0", @@ -27995,8 +27849,9 @@ }, "node_modules/hosted-git-info": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -28256,6 +28111,15 @@ "node": ">=10.17.0" } }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, "node_modules/husky": { "version": "1.3.1", "dev": true, @@ -28531,8 +28395,9 @@ }, "node_modules/iconv-corefoundation": { "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", "dev": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -28901,6 +28766,25 @@ "node": ">=0.10.0" } }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true + }, "node_modules/ip-regex": { "version": "2.1.0", "license": "MIT", @@ -29048,8 +28932,9 @@ }, "node_modules/is-ci": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, - "license": "MIT", "dependencies": { "ci-info": "^3.2.0" }, @@ -29284,6 +29169,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, "node_modules/is-map": { "version": "2.0.2", "dev": true, @@ -29560,8 +29451,9 @@ }, "node_modules/isbinaryfile": { "version": "5.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.2.tgz", + "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 18.0.0" }, @@ -29858,28 +29750,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-circus/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-circus/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-circus/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -29970,28 +29840,6 @@ } } }, - "node_modules/jest-cli/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-cli/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-cli/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -30093,28 +29941,6 @@ } } }, - "node_modules/jest-config/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-config/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-config/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -30268,28 +30094,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-each/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-each/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-each/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -30373,28 +30177,6 @@ } } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-jsdom/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-environment-jsdom/node_modules/acorn": { "version": "8.11.3", "license": "MIT", @@ -30405,47 +30187,6 @@ "node": ">=0.4.0" } }, - "node_modules/jest-environment-jsdom/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-environment-jsdom/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-environment-jsdom/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-environment-jsdom/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, "node_modules/jest-environment-jsdom/node_modules/cssstyle": { "version": "2.3.0", "license": "MIT", @@ -30494,13 +30235,6 @@ "node": ">= 6" } }, - "node_modules/jest-environment-jsdom/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/jest-environment-jsdom/node_modules/html-encoding-sniffer": { "version": "3.0.0", "license": "MIT", @@ -30564,16 +30298,6 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, - "node_modules/jest-environment-jsdom/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-environment-jsdom/node_modules/tr46": { "version": "3.0.0", "license": "MIT", @@ -30644,86 +30368,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-environment-node/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-environment-node/node_modules/@types/yargs": { - "version": "17.0.31", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/jest-environment-node/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-environment-node/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-environment-node/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-environment-node/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/jest-environment-node/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-environment-node/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-expo": { "version": "50.0.1", "license": "MIT", @@ -30791,69 +30435,6 @@ "fsevents": "^2.3.2" } }, - "node_modules/jest-haste-map/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-haste-map/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/jest-haste-map/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-haste-map/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-haste-map/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-haste-map/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, "node_modules/jest-haste-map/node_modules/has-flag": { "version": "4.0.0", "license": "MIT", @@ -30887,16 +30468,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest-haste-map/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-leak-detector": { "version": "29.4.1", "license": "MIT", @@ -30997,28 +30568,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-message-util/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-message-util/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-message-util/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -31089,86 +30638,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-mock/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-mock/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/jest-mock/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest-mock/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-mock/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest-mock/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/jest-mock/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-mock/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-pnp-resolver": { "version": "1.2.3", "license": "MIT", @@ -31308,28 +30777,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runner/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runner/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-runner/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -31454,28 +30901,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-runtime/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -31563,28 +30988,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-snapshot/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-snapshot/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -31667,28 +31070,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-util/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-util/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-util/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -31762,28 +31143,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-validate/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-validate/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -32077,28 +31436,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-watcher/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-watcher/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, "node_modules/jest-watcher/node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -32199,86 +31536,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/jest/node_modules/@jest/types": { - "version": "29.6.3", - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest/node_modules/@types/yargs": { - "version": "17.0.24", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/jest/node_modules/ansi-styles": { - "version": "4.3.0", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/jest/node_modules/chalk": { - "version": "4.1.2", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest/node_modules/color-convert": { - "version": "2.0.1", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/jest/node_modules/color-name": { - "version": "1.1.4", - "license": "MIT" - }, - "node_modules/jest/node_modules/has-flag": { - "version": "4.0.0", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/jest/node_modules/supports-color": { - "version": "7.2.0", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jimp-compact": { "version": "0.16.1", "license": "MIT" @@ -32330,6 +31587,12 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, "node_modules/jsc-android": { "version": "250231.0.0", "license": "BSD-2-Clause" @@ -32678,13 +31941,15 @@ }, "node_modules/lazy-val": { "version": "1.0.5", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "dev": true }, "node_modules/lazystream": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "readable-stream": "^2.0.5" @@ -32903,20 +32168,23 @@ }, "node_modules/lodash.defaults": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/lodash.difference": { "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/lodash.flatten": { "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/lodash.isequal": { @@ -32925,8 +32193,9 @@ }, "node_modules/lodash.isplainobject": { "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/lodash.memoize": { @@ -32946,8 +32215,9 @@ }, "node_modules/lodash.union": { "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", "dev": true, - "license": "MIT", "peer": true }, "node_modules/log-symbols": { @@ -33315,6 +32585,175 @@ "url": "https://github.com/wojtekmaj/make-event-props?sponsor=1" } }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/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/make-fetch-happen/node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-fetch-happen/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-fetch-happen/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/makeerror": { "version": "1.0.12", "license": "BSD-3-Clause", @@ -34072,8 +33511,9 @@ } }, "node_modules/metro/node_modules/ws": { - "version": "7.5.9", - "license": "MIT", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "engines": { "node": ">=8.3.0" }, @@ -34211,6 +33651,23 @@ "node": ">= 8" } }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, "node_modules/minipass-flush": { "version": "1.0.5", "license": "ISC", @@ -34231,6 +33688,18 @@ "node": ">=8" } }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/minizlib": { "version": "2.1.2", "license": "MIT", @@ -34487,16 +33956,38 @@ "node": ">= 10.13" } }, + "node_modules/node-abi": { + "version": "3.65.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz", + "integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-abort-controller": { "version": "3.1.1", "license": "MIT" }, "node_modules/node-addon-api": { "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", "dev": true, - "license": "MIT", "optional": true }, + "node_modules/node-api-version": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.0.tgz", + "integrity": "sha512-fthTTsi8CxaBXMaBAD7ST2uylwvsnYxh2PfaScwpMhos6KlSFajXQPcM4ogNE1q2s3Lbz9GCGqeIHC+C6OZnKg==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + } + }, "node_modules/node-dir": { "version": "0.1.17", "license": "MIT", @@ -34507,6 +33998,25 @@ "node": ">= 0.10.5" } }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, "node_modules/node-fetch": { "version": "2.6.7", "license": "MIT", @@ -34554,6 +34064,95 @@ "node": ">= 6.13.0" } }, + "node_modules/node-gyp": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", + "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/node-int64": { "version": "0.4.0", "license": "MIT" @@ -34621,6 +34220,21 @@ "url": "https://github.com/sponsors/antelle" } }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/normalize-package-data": { "version": "2.5.0", "license": "BSD-2-Clause", @@ -35216,6 +34830,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/openai": { + "version": "4.47.2", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.47.2.tgz", + "integrity": "sha512-E3Wq9mYdDSLajmcJm9RO/lCegTKrQ7ilAkMbhob4UgGhTjHwIHI+mXNDNPl5+sGIUp2iVUkpoi772FjYa7JlqA==", + "dev": true, + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7", + "web-streams-polyfill": "^3.2.1" + }, + "bin": { + "openai": "bin/cli" + } + }, + "node_modules/openai/node_modules/@types/node": { + "version": "18.19.31", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.31.tgz", + "integrity": "sha512-ArgCD39YpyyrtFKIqMDvjz79jto5fcI/SVUs2HwB+f0dAzq68yqOdyaSivLiLugSziTpNXLQrVb7RZFmdZzbhA==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/opencollective-postinstall": { "version": "2.0.3", "license": "MIT", @@ -35847,6 +35489,16 @@ "path2d-polyfill": "^2.0.1" } }, + "node_modules/pe-library": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.0.tgz", + "integrity": "sha512-JAmVv2jGxmczplhHO7UoFGJ+pM/yMBpny3vNjwNFuaeQfzKlekQidZ8Ss8EJ0qee8wEQN4lY2IwtWx2oRfMsag==", + "dev": true, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, "node_modules/peek-stream": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", @@ -35858,6 +35510,32 @@ "through2": "^2.0.3" } }, + "node_modules/peggy": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/peggy/-/peggy-4.0.3.tgz", + "integrity": "sha512-v7/Pt6kGYsfXsCrfb52q7/yg5jaAwiVaUMAPLPvy4DJJU6Wwr72t6nDIqIDkGfzd1B4zeVuTnQT0RGeOhe/uSA==", + "dev": true, + "dependencies": { + "@peggyjs/from-mem": "1.3.0", + "commander": "^12.1.0", + "source-map-generator": "0.8.0" + }, + "bin": { + "peggy": "bin/peggy.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/peggy/node_modules/commander": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", + "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", + "dev": true, + "engines": { + "node": ">=18" + } + }, "node_modules/pend": { "version": "1.2.0", "dev": true, @@ -35990,14 +35668,24 @@ } }, "node_modules/plist": { - "version": "3.0.6", - "license": "MIT", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dependencies": { + "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" }, "engines": { - "node": ">=6" + "node": ">=10.4.0" + } + }, + "node_modules/plist/node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "engines": { + "node": ">=10.0.0" } }, "node_modules/plist/node_modules/xmlbuilder": { @@ -37370,9 +37058,9 @@ } }, "node_modules/react-native-onyx": { - "version": "2.0.56", - "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-2.0.56.tgz", - "integrity": "sha512-3rn1+J4tli9zPS9w5x6tOAUz01wVHkiTFgtHoIwjD7HdLUO/9nk6H8JX6Oqb9Vzq2XQOSavUFRepIHnGvzNtgg==", + "version": "2.0.57", + "resolved": "https://registry.npmjs.org/react-native-onyx/-/react-native-onyx-2.0.57.tgz", + "integrity": "sha512-+/XndOz9kjCvUAYltq6wJbTsPcof+FZz6eFx0cpu/cDEHaYpjNoPWRKhWgWewg5wTYwu7SWl9aYSShRGVUsZWg==", "dependencies": { "ascii-table": "0.0.9", "fast-equals": "^4.0.3", @@ -37435,8 +37123,9 @@ } }, "node_modules/react-native-permissions": { - "version": "3.9.3", - "license": "MIT", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-3.10.1.tgz", + "integrity": "sha512-Gc5BxxpjZn4QNUDiVeHOO0vXh3AH7ToolmwTJozqC6DsxV7NAf3ttap+8BSmzDR8WxuAM3Cror+YNiBhHJx7/w==", "peerDependencies": { "react": ">=16.13.1", "react-native": ">=0.63.3", @@ -37461,17 +37150,17 @@ } }, "node_modules/react-native-plaid-link-sdk": { - "version": "11.5.0", - "resolved": "https://registry.npmjs.org/react-native-plaid-link-sdk/-/react-native-plaid-link-sdk-11.5.0.tgz", - "integrity": "sha512-B3fwujxBS9nZwadXFcseU3nrYG7Ptob6p9eG/gXde65cqwErMaq2k1rVv3R17s/rpKnmU5Cx5pKOMmkxPUn08w==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/react-native-plaid-link-sdk/-/react-native-plaid-link-sdk-11.11.0.tgz", + "integrity": "sha512-Kmimhr6iOwCtIzsW7gygz48TzaZsdjnpgstJ2PM1q+THulOnx+BnkFu8UpLIGGkVe19E4wkxOAYL8kJ8vefNSQ==", "peerDependencies": { "react": "*", "react-native": "*" } }, "node_modules/react-native-qrcode-svg": { - "version": "6.2.0", - "license": "MIT", + "version": "6.3.0", + "resolved": "git+ssh://git@github.com/Expensify/react-native-qrcode-svg.git#295f87d45c0f10d9b50838ad28fa70e47d054c3b", "dependencies": { "prop-types": "^15.8.0", "qrcode": "^1.5.1" @@ -37479,7 +37168,7 @@ "peerDependencies": { "react": "*", "react-native": ">=0.63.4", - "react-native-svg": "^13.2.0" + "react-native-svg": ">=13.2.0" } }, "node_modules/react-native-quick-sqlite": { @@ -37522,14 +37211,15 @@ "license": "MIT" }, "node_modules/react-native-release-profiler": { - "version": "0.1.6", - "license": "MIT", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/react-native-release-profiler/-/react-native-release-profiler-0.2.1.tgz", + "integrity": "sha512-gDOwEXypd4Gu++nlKyaVLHPfwrVkkdBrsjMrQORYTTDqcrD/OfuNZ8YK7p+u5LUNjnPD4WmBF88C5dEW7iM1lg==", "workspaces": [ "example" ], "dependencies": { - "@react-native-community/cli": "^12.2.1", - "commander": "^11.1.0" + "commander": "^11.1.0", + "hermes-profile-transformer": "^0.0.9" }, "bin": { "react-native-release-profiler": "lib/commonjs/cli.js" @@ -37549,6 +37239,25 @@ "node": ">=16" } }, + "node_modules/react-native-release-profiler/node_modules/hermes-profile-transformer": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.9.tgz", + "integrity": "sha512-JYPUE9zA+W/hpTIGBV+t2ODvntataLLMfntoEcpEpKFDwdR6+Quk9SwLnWX9y2A3ZII6N4T8w3TUBC2ejsEGBw==", + "dependencies": { + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/react-native-release-profiler/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, "node_modules/react-native-render-html": { "version": "6.3.1", "license": "BSD-2-Clause", @@ -37626,11 +37335,13 @@ } }, "node_modules/react-native-svg": { - "version": "14.1.0", - "license": "MIT", + "version": "15.4.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.4.0.tgz", + "integrity": "sha512-zkBEbme/Dba4yqreg/oI2P6/6LrLywWY7HhaSwpU7Pb5COpTd2fV6/ShsgZz8GRFFdidUPwWmx01FITUsjhkmw==", "dependencies": { "css-select": "^5.1.0", - "css-tree": "^1.1.3" + "css-tree": "^1.1.3", + "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", @@ -37902,8 +37613,9 @@ } }, "node_modules/react-native/node_modules/ws": { - "version": "6.2.2", - "license": "MIT", + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", "dependencies": { "async-limiter": "~1.0.0" } @@ -38077,10 +37789,6 @@ "react": "^18.2.0" } }, - "node_modules/react-test-renderer/node_modules/react-is": { - "version": "18.2.0", - "license": "MIT" - }, "node_modules/react-test-renderer/node_modules/scheduler": { "version": "0.23.0", "license": "MIT", @@ -38509,6 +38217,18 @@ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/read-binary-file-arch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", + "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4" + }, + "bin": { + "read-binary-file-arch": "cli.js" + } + }, "node_modules/read-cmd-shim": { "version": "4.0.0", "license": "ISC", @@ -38517,16 +38237,17 @@ } }, "node_modules/read-config-file": { - "version": "6.3.2", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.4.0.tgz", + "integrity": "sha512-uB5QOBeF84PT61GlV11OTV4jUGHAO3iDEOP6v9ygxhG6Bs9PLg7WsjNT6mtIX2G+x8lJTr4ZWNeG6LDTKkNf2Q==", "dev": true, - "license": "MIT", "dependencies": { - "config-file-ts": "^0.2.4", - "dotenv": "^9.0.2", - "dotenv-expand": "^5.1.0", + "config-file-ts": "0.2.8-rc1", + "dotenv": "^16.4.5", + "dotenv-expand": "^11.0.6", "js-yaml": "^4.1.0", - "json5": "^2.2.0", - "lazy-val": "^1.0.4" + "json5": "^2.2.3", + "lazy-val": "^1.0.5" }, "engines": { "node": ">=12.0.0" @@ -38534,21 +38255,15 @@ }, "node_modules/read-config-file/node_modules/argparse": { "version": "2.0.1", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/read-config-file/node_modules/dotenv": { - "version": "9.0.2", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=10" - } + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true }, "node_modules/read-config-file/node_modules/js-yaml": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -38719,8 +38434,9 @@ }, "node_modules/readdir-glob": { "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", "dev": true, - "license": "Apache-2.0", "peer": true, "dependencies": { "minimatch": "^5.1.0" @@ -38728,8 +38444,9 @@ }, "node_modules/readdir-glob/node_modules/brace-expansion": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0" @@ -38737,8 +38454,9 @@ }, "node_modules/readdir-glob/node_modules/minimatch": { "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", "dev": true, - "license": "ISC", "peer": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -39104,6 +38822,19 @@ "version": "1.0.0", "license": "MIT" }, + "node_modules/resedit": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.0.tgz", + "integrity": "sha512-dbsZ0gk5opWPFlKMqvxCrLCuMZUVmsW3yTPT0tT4mYwo5fjQM8c4HMN9ZJt6dRDqDV/78m9SU4rv24PN4NiYaA==", + "dev": true, + "dependencies": { + "pe-library": "^0.4.0" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, "node_modules/reselect": { "version": "4.1.7", "dev": true, @@ -39376,8 +39107,9 @@ }, "node_modules/sanitize-filename": { "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", "dev": true, - "license": "WTFPL OR ISC", "dependencies": { "truncate-utf8-bytes": "^1.0.0" } @@ -39917,8 +39649,9 @@ }, "node_modules/slice-ansi": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -39931,8 +39664,9 @@ }, "node_modules/slice-ansi/node_modules/ansi-styles": { "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "color-convert": "^2.0.1" @@ -39946,8 +39680,9 @@ }, "node_modules/slice-ansi/node_modules/color-convert": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "color-name": "~1.1.4" @@ -39958,8 +39693,9 @@ }, "node_modules/slice-ansi/node_modules/color-name": { "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "license": "MIT", "optional": true }, "node_modules/slugify": { @@ -39971,9 +39707,9 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, - "license": "MIT", - "optional": true, "engines": { "node": ">= 6.0.0", "npm": ">= 3.0.0" @@ -40179,6 +39915,34 @@ "websocket-driver": "^0.7.4" } }, + "node_modules/socks": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", + "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==", + "dev": true, + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/sort-asc": { "version": "0.2.0", "license": "MIT", @@ -40226,6 +39990,15 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-generator": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/source-map-generator/-/source-map-generator-0.8.0.tgz", + "integrity": "sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "license": "BSD-3-Clause", @@ -40456,8 +40229,9 @@ }, "node_modules/stat-mode": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6" } @@ -41198,8 +40972,9 @@ }, "node_modules/temp-file": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", "dev": true, - "license": "MIT", "dependencies": { "async-exit-hook": "^2.0.1", "fs-extra": "^10.0.0" @@ -41207,8 +40982,9 @@ }, "node_modules/temp-file/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -41550,16 +41326,18 @@ }, "node_modules/tmp": { "version": "0.2.3", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", + "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", "dev": true, - "license": "MIT", "engines": { "node": ">=14.14" } }, "node_modules/tmp-promise": { "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", "dev": true, - "license": "MIT", "dependencies": { "tmp": "^0.2.0" } @@ -41700,8 +41478,9 @@ }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", "dev": true, - "license": "WTFPL", "dependencies": { "utf8-byte-length": "^1.0.1" } @@ -42506,9 +42285,10 @@ "license": "MIT" }, "node_modules/utf8-byte-length": { - "version": "1.0.4", - "dev": true, - "license": "WTFPL" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true }, "node_modules/util": { "version": "0.11.1", @@ -42594,8 +42374,9 @@ }, "node_modules/verror": { "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "assert-plus": "^1.0.0", @@ -42932,6 +42713,15 @@ "defaults": "^1.0.3" } }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/webidl-conversions": { "version": "7.0.0", "license": "BSD-2-Clause", @@ -43098,9 +42888,10 @@ } }, "node_modules/webpack-bundle-analyzer/node_modules/ws": { - "version": "7.5.9", + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.3.0" }, @@ -43723,8 +43514,8 @@ }, "node_modules/wide-align": { "version": "1.1.5", + "devOptional": true, "license": "ISC", - "optional": true, "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" } @@ -43862,8 +43653,9 @@ } }, "node_modules/ws": { - "version": "8.16.0", - "license": "MIT", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, @@ -44011,8 +43803,9 @@ }, "node_modules/zip-stream": { "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "archiver-utils": "^3.0.4", @@ -44025,8 +43818,9 @@ }, "node_modules/zip-stream/node_modules/archiver-utils": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "glob": "^7.2.3", @@ -44046,8 +43840,10 @@ }, "node_modules/zip-stream/node_modules/glob": { "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "license": "ISC", "peer": true, "dependencies": { "fs.realpath": "^1.0.0", @@ -44066,8 +43862,9 @@ }, "node_modules/zip-stream/node_modules/readable-stream": { "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, - "license": "MIT", "peer": true, "dependencies": { "inherits": "^2.0.3", diff --git a/package.json b/package.json index 9f1c3ffca7a7..79111bb6f478 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.6-0", + "version": "9.0.14-1", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", @@ -61,13 +61,14 @@ "workflow-test:generate": "ts-node workflow_tests/utils/preGenerateTest.ts", "setup-https": "mkcert -install && mkcert -cert-file config/webpack/certificate.pem -key-file config/webpack/key.pem dev.new.expensify.com localhost 127.0.0.1", "e2e-test-runner-build": "ncc build tests/e2e/testRunner.ts -o tests/e2e/dist/", - "react-compiler-healthcheck": "react-compiler-healthcheck --verbose" + "react-compiler-healthcheck": "react-compiler-healthcheck --verbose", + "generate-search-parser": "peggy --format es -o src/libs/SearchParser/searchParser.js src/libs/SearchParser/searchParser.peggy " }, "dependencies": { "@babel/plugin-proposal-private-methods": "^7.18.6", "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.91", + "@expensify/react-native-live-markdown": "^0.1.107", "@expo/metro-runtime": "~3.1.1", "@formatjs/intl-datetimeformat": "^6.10.0", "@formatjs/intl-listformat": "^7.2.2", @@ -80,12 +81,12 @@ "@fullstory/react-native": "^1.4.2", "@gorhom/portal": "^1.0.14", "@invertase/react-native-apple-authentication": "^2.2.2", - "@kie/act-js": "^2.6.0", + "@kie/act-js": "^2.6.2", "@kie/mock-github": "2.0.1", "@onfido/react-native-sdk": "10.6.0", "@react-native-camera-roll/camera-roll": "7.4.0", "@react-native-clipboard/clipboard": "^1.13.2", - "@react-native-community/geolocation": "3.2.1", + "@react-native-community/geolocation": "3.3.0", "@react-native-community/netinfo": "11.2.1", "@react-native-firebase/analytics": "^12.3.0", "@react-native-firebase/app": "^12.3.0", @@ -109,7 +110,7 @@ "date-fns-tz": "^2.0.0", "dom-serializer": "^0.2.2", "domhandler": "^4.3.0", - "expensify-common": "2.0.26", + "expensify-common": "2.0.57", "expo": "^50.0.3", "expo-av": "~13.10.4", "expo-image": "1.11.0", @@ -156,23 +157,23 @@ "react-native-linear-gradient": "^2.8.1", "react-native-localize": "^2.2.6", "react-native-modal": "^13.0.0", - "react-native-onyx": "2.0.56", + "react-native-onyx": "2.0.57", "react-native-pager-view": "6.2.3", "react-native-pdf": "6.7.3", "react-native-performance": "^5.1.0", - "react-native-permissions": "^3.9.3", + "react-native-permissions": "^3.10.0", "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#da50d2c5c54e268499047f9cc98b8df4196c1ddf", - "react-native-plaid-link-sdk": "11.5.0", - "react-native-qrcode-svg": "^6.2.0", + "react-native-plaid-link-sdk": "11.11.0", + "react-native-qrcode-svg": "git+https://github.com/Expensify/react-native-qrcode-svg", "react-native-quick-sqlite": "git+https://github.com/margelo/react-native-quick-sqlite#abc91857d4b3efb2020ec43abd2a508563b64316", "react-native-reanimated": "^3.8.0", - "react-native-release-profiler": "^0.1.6", + "react-native-release-profiler": "^0.2.1", "react-native-render-html": "6.3.1", "react-native-safe-area-context": "4.8.2", "react-native-screens": "3.32.0", "react-native-share": "^10.0.2", "react-native-sound": "^0.11.2", - "react-native-svg": "14.1.0", + "react-native-svg": "15.4.0", "react-native-tab-view": "^3.5.2", "react-native-url-polyfill": "^2.0.0", "react-native-view-shot": "3.8.0", @@ -209,6 +210,7 @@ "@octokit/core": "4.0.4", "@octokit/plugin-paginate-rest": "3.1.0", "@octokit/plugin-throttling": "4.1.0", + "@octokit/webhooks-types": "^7.5.1", "@perf-profiler/profiler": "^0.10.10", "@perf-profiler/reporter": "^0.9.0", "@perf-profiler/types": "^0.8.0", @@ -266,7 +268,7 @@ "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", "electron": "^29.4.1", - "electron-builder": "24.13.2", + "electron-builder": "25.0.0", "eslint": "^8.57.0", "eslint-config-airbnb-typescript": "^18.0.0", "eslint-config-expensify": "^2.0.52", @@ -286,7 +288,9 @@ "jest-transformer-svg": "^2.0.1", "memfs": "^4.6.0", "onchange": "^7.1.0", + "openai": "^4.47.2", "patch-package": "^8.0.0", + "peggy": "^4.0.3", "portfinder": "^1.0.28", "prettier": "^2.8.8", "pusher-js-mock": "^0.3.3", diff --git a/patches/@expensify+react-native-live-markdown+0.1.91.patch b/patches/@expensify+react-native-live-markdown+0.1.91.patch deleted file mode 100644 index c77e46accae3..000000000000 --- a/patches/@expensify+react-native-live-markdown+0.1.91.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/node_modules/@expensify/react-native-live-markdown/src/web/cursorUtils.ts b/node_modules/@expensify/react-native-live-markdown/src/web/cursorUtils.ts -index 1cda659..ba5c3c3 100644 ---- a/node_modules/@expensify/react-native-live-markdown/src/web/cursorUtils.ts -+++ b/node_modules/@expensify/react-native-live-markdown/src/web/cursorUtils.ts -@@ -66,7 +66,7 @@ function setCursorPosition(target: HTMLElement, start: number, end: number | nul - // 3. Caret at the end of whole input, when pressing enter - // 4. All other placements - if (prevChar === '\n' && prevTextLength !== undefined && prevTextLength < textCharacters.length) { -- if (nextChar !== '\n') { -+ if (nextChar && nextChar !== '\n' && i !== n - 1) { - range.setStart(textNodes[i + 1] as Node, 0); - } else if (i !== textNodes.length - 1) { - range.setStart(textNodes[i] as Node, 1); diff --git a/patches/@perf-profiler+android+0.12.1.patch b/patches/@perf-profiler+android+0.12.1.patch deleted file mode 100644 index e6e4a90d6ab4..000000000000 --- a/patches/@perf-profiler+android+0.12.1.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/node_modules/@perf-profiler/android/dist/src/commands/platforms/UnixProfiler.js b/node_modules/@perf-profiler/android/dist/src/commands/platforms/UnixProfiler.js -index 59aeed9..ee1d8a6 100644 ---- a/node_modules/@perf-profiler/android/dist/src/commands/platforms/UnixProfiler.js -+++ b/node_modules/@perf-profiler/android/dist/src/commands/platforms/UnixProfiler.js -@@ -28,7 +28,7 @@ exports.CppProfilerName = `BAMPerfProfiler`; - // into the Flipper plugin directory - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error --const binaryFolder = global.Flipper -+const binaryFolder = (global.Flipper || process.env.AWS) - ? `${__dirname}/bin` - : `${__dirname}/../../..${__dirname.includes("dist") ? "/.." : ""}/cpp-profiler/bin`; - class UnixProfiler { -diff --git a/node_modules/@perf-profiler/android/src/commands/platforms/UnixProfiler.ts b/node_modules/@perf-profiler/android/src/commands/platforms/UnixProfiler.ts -index ccacf09..1eea659 100644 ---- a/node_modules/@perf-profiler/android/src/commands/platforms/UnixProfiler.ts -+++ b/node_modules/@perf-profiler/android/src/commands/platforms/UnixProfiler.ts -@@ -26,7 +26,7 @@ export const CppProfilerName = `BAMPerfProfiler`; - // into the Flipper plugin directory - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error --const binaryFolder = global.Flipper -+const binaryFolder = (global.Flipper || process.env.AWS) - ? `${__dirname}/bin` - : `${__dirname}/../../..${__dirname.includes("dist") ? "/.." : ""}/cpp-profiler/bin`; - diff --git a/patches/@react-native-community+netinfo+11.2.1+002+turbomodule.patch b/patches/@react-native-community+netinfo+11.2.1+002+turbomodule.patch index f8e171008e14..c679bdbf73b9 100644 --- a/patches/@react-native-community+netinfo+11.2.1+002+turbomodule.patch +++ b/patches/@react-native-community+netinfo+11.2.1+002+turbomodule.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/@react-native-community/netinfo/android/build.gradle b/node_modules/@react-native-community/netinfo/android/build.gradle -index 0d617ed..e93d64a 100644 +index 0d617ed..97439e6 100644 --- a/node_modules/@react-native-community/netinfo/android/build.gradle +++ b/node_modules/@react-native-community/netinfo/android/build.gradle @@ -3,9 +3,10 @@ buildscript { @@ -105,7 +105,6 @@ index 0d617ed..e93d64a 100644 + implementation 'com.facebook.react:react-native:+' + } } -\ No newline at end of file diff --git a/node_modules/@react-native-community/netinfo/android/src/main/java/com/reactnativecommunity/netinfo/NetInfoModuleImpl.java b/node_modules/@react-native-community/netinfo/android/src/main/java/com/reactnativecommunity/netinfo/NetInfoModuleImpl.java index 2c3280b..296bbfd 100644 --- a/node_modules/@react-native-community/netinfo/android/src/main/java/com/reactnativecommunity/netinfo/NetInfoModuleImpl.java @@ -1609,10 +1608,10 @@ index 095dd3b..596ace1 100644 +{"version":3,"names":["NetInfoStateType","exports","NetInfoCellularGeneration"],"sources":["types.ts"],"sourcesContent":["/**\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n * @format\n */\n\nexport enum NetInfoStateType {\n unknown = 'unknown',\n none = 'none',\n cellular = 'cellular',\n wifi = 'wifi',\n bluetooth = 'bluetooth',\n ethernet = 'ethernet',\n wimax = 'wimax',\n vpn = 'vpn',\n other = 'other',\n}\n\nexport type NetInfoMethodType = 'HEAD' | 'GET';\n\nexport enum NetInfoCellularGeneration {\n '2g' = '2g',\n '3g' = '3g',\n '4g' = '4g',\n '5g' = '5g',\n}\n\nexport interface NetInfoConnectedDetails {\n isConnectionExpensive: boolean;\n}\n\ninterface NetInfoConnectedState<\n T extends NetInfoStateType,\n D extends Record = Record,\n> {\n type: T;\n isConnected: true;\n isInternetReachable: boolean | null;\n details: D & NetInfoConnectedDetails;\n isWifiEnabled?: boolean;\n}\n\ninterface NetInfoDisconnectedState {\n type: T;\n isConnected: false;\n isInternetReachable: false;\n details: null;\n isWifiEnabled?: boolean;\n}\n\nexport interface NetInfoUnknownState {\n type: NetInfoStateType.unknown;\n isConnected: boolean | null;\n isInternetReachable: null;\n details: null;\n isWifiEnabled?: boolean;\n}\n\nexport type NetInfoNoConnectionState =\n NetInfoDisconnectedState;\nexport type NetInfoDisconnectedStates =\n | NetInfoUnknownState\n | NetInfoNoConnectionState;\n\nexport type NetInfoCellularState = NetInfoConnectedState<\n NetInfoStateType.cellular,\n {\n cellularGeneration: NetInfoCellularGeneration | null;\n carrier: string | null;\n }\n>;\nexport type NetInfoWifiState = NetInfoConnectedState<\n NetInfoStateType.wifi,\n {\n ssid: string | null;\n bssid: string | null;\n strength: number | null;\n ipAddress: string | null;\n subnet: string | null;\n frequency: number | null;\n linkSpeed: number | null;\n rxLinkSpeed: number | null;\n txLinkSpeed: number | null;\n }\n>;\nexport type NetInfoBluetoothState =\n NetInfoConnectedState;\nexport type NetInfoEthernetState = NetInfoConnectedState<\n NetInfoStateType.ethernet,\n {\n ipAddress: string | null;\n subnet: string | null;\n }\n>;\nexport type NetInfoWimaxState = NetInfoConnectedState;\nexport type NetInfoVpnState = NetInfoConnectedState;\nexport type NetInfoOtherState = NetInfoConnectedState;\nexport type NetInfoConnectedStates =\n | NetInfoCellularState\n | NetInfoWifiState\n | NetInfoBluetoothState\n | NetInfoEthernetState\n | NetInfoWimaxState\n | NetInfoVpnState\n | NetInfoOtherState;\n\nexport type NetInfoState = NetInfoDisconnectedStates | NetInfoConnectedStates;\n\nexport type NetInfoChangeHandler = (state: NetInfoState) => void;\nexport type NetInfoSubscription = () => void;\n\nexport interface NetInfoConfiguration {\n reachabilityUrl: string;\n reachabilityMethod?: NetInfoMethodType;\n reachabilityHeaders?: Record;\n reachabilityTest: (response: Response) => Promise;\n reachabilityLongTimeout: number;\n reachabilityShortTimeout: number;\n reachabilityRequestTimeout: number;\n reachabilityShouldRun: () => boolean;\n shouldFetchWiFiSSID: boolean;\n useNativeReachability: boolean;\n}\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAPA,IASYA,gBAAgB,GAAAC,OAAA,CAAAD,gBAAA,0BAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAhBA,gBAAgB;EAAA,OAAhBA,gBAAgB;AAAA;AAAA,IAchBE,yBAAyB,GAAAD,OAAA,CAAAC,yBAAA,0BAAzBA,yBAAyB;EAAzBA,yBAAyB;EAAzBA,yBAAyB;EAAzBA,yBAAyB;EAAzBA,yBAAyB;EAAA,OAAzBA,yBAAyB;AAAA"} \ No newline at end of file diff --git a/node_modules/@react-native-community/netinfo/lib/module/index.js b/node_modules/@react-native-community/netinfo/lib/module/index.js -index 147c72e..02aa0db 100644 +index 147c72e..5de4e7c 100644 --- a/node_modules/@react-native-community/netinfo/lib/module/index.js +++ b/node_modules/@react-native-community/netinfo/lib/module/index.js -@@ -6,20 +6,23 @@ +@@ -6,20 +6,26 @@ * * @format */ @@ -1635,11 +1634,14 @@ index 147c72e..02aa0db 100644 const createState = () => { return new State(_configuration); }; ++ ++// Track ongoing requests ++let isRequestInProgress = false; + /** * Configures the library with the given configuration. Note that calling this will stop all * previously added listeners from being called again. It is best to call this right when your -@@ -27,23 +30,20 @@ const createState = () => { +@@ -27,23 +33,20 @@ const createState = () => { * * @param configuration The new configuration to set. */ @@ -1666,7 +1668,7 @@ index 147c72e..02aa0db 100644 /** * Returns a `Promise` that resolves to a `NetInfoState` object. * This function operates on the global singleton instance configured using `configure()` -@@ -52,27 +52,25 @@ export function configure(configuration) { +@@ -52,27 +55,33 @@ export function configure(configuration) { * * @returns A Promise which contains the current connection state. */ @@ -1689,14 +1691,22 @@ index 147c72e..02aa0db 100644 if (!_state) { _state = createState(); } -- - return _state._fetchCurrentState(); + +- return _state._fetchCurrentState(); ++ if (isRequestInProgress) { ++ return _state.latest(); // Return the latest state if a request is already in progress ++ } ++ ++ isRequestInProgress = true; ++ return _state._fetchCurrentState().finally(() => { ++ isRequestInProgress = false; ++ }); } + /** * Subscribe to the global singleton's connection information. The callback is called with a parameter of type * [`NetInfoState`](README.md#netinfostate) whenever the connection state changes. Your listener -@@ -84,18 +82,16 @@ export function refresh() { +@@ -84,18 +93,16 @@ export function refresh() { * * @returns A function which can be called to unsubscribe. */ @@ -1716,7 +1726,7 @@ index 147c72e..02aa0db 100644 /** * A React Hook into this library's singleton which updates when the connection state changes. * -@@ -103,12 +99,10 @@ export function addEventListener(listener) { +@@ -103,12 +110,10 @@ export function addEventListener(listener) { * * @returns The connection state. */ @@ -1729,7 +1739,7 @@ index 147c72e..02aa0db 100644 const [netInfo, setNetInfo] = useState({ type: Types.NetInfoStateType.unknown, isConnected: null, -@@ -120,6 +114,7 @@ export function useNetInfo(configuration) { +@@ -120,6 +125,7 @@ export function useNetInfo(configuration) { }, []); return netInfo; } @@ -1737,7 +1747,7 @@ index 147c72e..02aa0db 100644 /** * A React Hook which manages an isolated instance of the network info manager. * This is not a hook into a singleton shared state. NetInfo.configure, NetInfo.addEventListener, -@@ -129,7 +124,6 @@ export function useNetInfo(configuration) { +@@ -129,7 +135,6 @@ export function useNetInfo(configuration) { * * @returns the netInfo state and a refresh function */ @@ -1745,7 +1755,7 @@ index 147c72e..02aa0db 100644 export function useNetInfoInstance(isPaused = false, configuration) { const [networkInfoManager, setNetworkInfoManager] = useState(); const [netInfo, setNetInfo] = useState({ -@@ -142,8 +136,8 @@ export function useNetInfoInstance(isPaused = false, configuration) { +@@ -142,8 +147,8 @@ export function useNetInfoInstance(isPaused = false, configuration) { if (isPaused) { return; } @@ -2610,22 +2620,13 @@ index 6982220..b515270 100644 }; export default _default; diff --git a/node_modules/@react-native-community/netinfo/package.json b/node_modules/@react-native-community/netinfo/package.json -index 3c80db2..61e6564 100644 +index 3c80db2..15d214d 100644 --- a/node_modules/@react-native-community/netinfo/package.json +++ b/node_modules/@react-native-community/netinfo/package.json -@@ -48,6 +48,7 @@ - "network info" - ], - "peerDependencies": { -+ "react": "*", - "react-native": ">=0.59" +@@ -97,6 +97,14 @@ + "webpack-cli": "^3.3.10", + "webpack-dev-server": "^3.11.3" }, - "dependencies": {}, -@@ -121,5 +122,13 @@ - "yarn eslint --fix", - "git add" - ] -+ }, + "codegenConfig": { + "name": "RNCNetInfoSpec", + "type": "modules", @@ -2633,8 +2634,10 @@ index 3c80db2..61e6564 100644 + "android": { + "javaPackageName": "com.reactnativecommunity.netinfo" + } - } - } ++ }, + "repository": { + "type": "git", + "url": "https://github.com/react-native-netinfo/react-native-netinfo.git" diff --git a/node_modules/@react-native-community/netinfo/react-native-netinfo.podspec b/node_modules/@react-native-community/netinfo/react-native-netinfo.podspec index e34e728..9090eb1 100644 --- a/node_modules/@react-native-community/netinfo/react-native-netinfo.podspec @@ -3062,4 +3065,4 @@ index 878f7ba..0000000 - -#Files generated by the VS build -**/Generated Files/** -- +- \ No newline at end of file diff --git a/patches/focus-trap+7.5.4.patch b/patches/focus-trap+7.5.4.patch new file mode 100644 index 000000000000..c7b2aef2b51f --- /dev/null +++ b/patches/focus-trap+7.5.4.patch @@ -0,0 +1,106 @@ +diff --git a/node_modules/focus-trap/dist/focus-trap.esm.js b/node_modules/focus-trap/dist/focus-trap.esm.js +index 10d56db..a6d76d8 100644 +--- a/node_modules/focus-trap/dist/focus-trap.esm.js ++++ b/node_modules/focus-trap/dist/focus-trap.esm.js +@@ -100,8 +100,8 @@ var isKeyForward = function isKeyForward(e) { + var isKeyBackward = function isKeyBackward(e) { + return isTabEvent(e) && e.shiftKey; + }; +-var delay = function delay(fn) { +- return setTimeout(fn, 0); ++var delay = function delay(fn, delayTime = 0) { ++ return setTimeout(() => setTimeout(fn, delayTime), 0); + }; + + // Array.find/findIndex() are not supported on IE; this replicates enough +@@ -283,7 +283,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) { + return node; + }; + var getInitialFocusNode = function getInitialFocusNode() { +- var node = getNodeForOption('initialFocus'); ++ var node = getNodeForOption('initialFocus', state.containers); + + // false explicitly indicates we want no initialFocus at all + if (node === false) { +@@ -744,7 +744,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) { + // that caused the focus trap activation. + state.delayInitialFocusTimer = config.delayInitialFocus ? delay(function () { + tryFocus(getInitialFocusNode()); +- }) : tryFocus(getInitialFocusNode()); ++ }, typeof config.delayInitialFocus === 'number' ? config.delayInitialFocus : undefined) : tryFocus(getInitialFocusNode()); + doc.addEventListener('focusin', checkFocusIn, true); + doc.addEventListener('mousedown', checkPointerDown, { + capture: true, +@@ -880,7 +880,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) { + tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)); + } + onPostDeactivate === null || onPostDeactivate === void 0 || onPostDeactivate(); +- }); ++ }, typeof config.delayInitialFocus === 'number' ? config.delayInitialFocus : undefined); + }; + if (returnFocus && checkCanReturnFocus) { + checkCanReturnFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation); +diff --git a/node_modules/focus-trap/index.d.ts b/node_modules/focus-trap/index.d.ts +index 400db1b..69f4b94 100644 +--- a/node_modules/focus-trap/index.d.ts ++++ b/node_modules/focus-trap/index.d.ts +@@ -16,7 +16,7 @@ declare module 'focus-trap' { + * `document.querySelector()` to find the DOM node), `false` to explicitly indicate + * an opt-out, or a function that returns a DOM node or `false`. + */ +- export type FocusTargetOrFalse = FocusTargetValueOrFalse | (() => FocusTargetValueOrFalse); ++ export type FocusTargetOrFalse = FocusTargetValueOrFalse | ((containers?: HTMLElement[]) => FocusTargetValueOrFalse | undefined); + + type MouseEventToBoolean = (event: MouseEvent | TouchEvent) => boolean; + type KeyboardEventToBoolean = (event: KeyboardEvent) => boolean; +@@ -185,7 +185,7 @@ declare module 'focus-trap' { + * This prevents elements within the focusable element from capturing + * the event that triggered the focus trap activation. + */ +- delayInitialFocus?: boolean; ++ delayInitialFocus?: boolean | number; + /** + * Default: `window.document`. Document where the focus trap will be active. + * This allows to use FocusTrap in an iFrame context. +diff --git a/node_modules/focus-trap/index.js b/node_modules/focus-trap/index.js +index de8e46a..bfc8b63 100644 +--- a/node_modules/focus-trap/index.js ++++ b/node_modules/focus-trap/index.js +@@ -63,8 +63,8 @@ const isKeyBackward = function (e) { + return isTabEvent(e) && e.shiftKey; + }; + +-const delay = function (fn) { +- return setTimeout(fn, 0); ++const delay = function (fn, delayTime = 0) { ++ return setTimeout(() => setTimeout(fn, delayTime), 0); + }; + + // Array.find/findIndex() are not supported on IE; this replicates enough +@@ -267,7 +267,7 @@ const createFocusTrap = function (elements, userOptions) { + }; + + const getInitialFocusNode = function () { +- let node = getNodeForOption('initialFocus'); ++ let node = getNodeForOption('initialFocus', state.containers); + + // false explicitly indicates we want no initialFocus at all + if (node === false) { +@@ -817,7 +817,7 @@ const createFocusTrap = function (elements, userOptions) { + state.delayInitialFocusTimer = config.delayInitialFocus + ? delay(function () { + tryFocus(getInitialFocusNode()); +- }) ++ }, typeof config.delayInitialFocus === 'number' ? config.delayInitialFocus : undefined) + : tryFocus(getInitialFocusNode()); + + doc.addEventListener('focusin', checkFocusIn, true); +@@ -989,7 +989,7 @@ const createFocusTrap = function (elements, userOptions) { + tryFocus(getReturnFocusNode(state.nodeFocusedBeforeActivation)); + } + onPostDeactivate?.(); +- }); ++ }, typeof config.delayInitialFocus === 'number' ? config.delayInitialFocus : undefined); + }; + + if (returnFocus && checkCanReturnFocus) { diff --git a/patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625.patch b/patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625+001+initial.patch similarity index 100% rename from patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625.patch rename to patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625+001+initial.patch diff --git a/patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625+002+enable-ref-identifiers.patch b/patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625+002+enable-ref-identifiers.patch new file mode 100644 index 000000000000..6caa4ad4c373 --- /dev/null +++ b/patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625+002+enable-ref-identifiers.patch @@ -0,0 +1,28 @@ +diff --git a/node_modules/react-compiler-healthcheck/dist/index.js b/node_modules/react-compiler-healthcheck/dist/index.js +index 4bf23db..fa2ab22 100755 +--- a/node_modules/react-compiler-healthcheck/dist/index.js ++++ b/node_modules/react-compiler-healthcheck/dist/index.js +@@ -69088,6 +69088,9 @@ const COMPILER_OPTIONS = { + compilationMode: "infer", + panicThreshold: "critical_errors", + logger: logger, ++ environment: { ++ enableTreatRefLikeIdentifiersAsRefs: true, ++ }, + }; + function isActionableDiagnostic(detail) { + switch (detail.severity) { +diff --git a/node_modules/react-compiler-healthcheck/src/checks/reactCompiler.ts b/node_modules/react-compiler-healthcheck/src/checks/reactCompiler.ts +index 09c9b9b..d2418e0 100644 +--- a/node_modules/react-compiler-healthcheck/src/checks/reactCompiler.ts ++++ b/node_modules/react-compiler-healthcheck/src/checks/reactCompiler.ts +@@ -51,6 +51,9 @@ const COMPILER_OPTIONS: Partial = { + compilationMode: "infer", + panicThreshold: "critical_errors", + logger, ++ environment: { ++ enableTreatRefLikeIdentifiersAsRefs: true, ++ }, + }; + + function isActionableDiagnostic(detail: CompilerErrorDetailOptions) { diff --git a/patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625+003+json.patch b/patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625+003+json.patch new file mode 100644 index 000000000000..a3de7a365889 --- /dev/null +++ b/patches/react-compiler-healthcheck+0.0.0-experimental-b130d5f-20240625+003+json.patch @@ -0,0 +1,73 @@ +diff --git a/node_modules/react-compiler-healthcheck/dist/index.js b/node_modules/react-compiler-healthcheck/dist/index.js +index fa2ab22..93be1fb 100755 +--- a/node_modules/react-compiler-healthcheck/dist/index.js ++++ b/node_modules/react-compiler-healthcheck/dist/index.js +@@ -69157,16 +69157,28 @@ var reactCompilerCheck = { + compile(source, path); + } + }, +- report(verbose) { ++ report(verbose, json) { + const totalComponents = + SucessfulCompilation.length + + countUniqueLocInEvents(OtherFailures) + + countUniqueLocInEvents(ActionableFailures); +- console.log( +- chalk.green( +- `Successfully compiled ${SucessfulCompilation.length} out of ${totalComponents} components.` +- ) +- ); ++ if (!json) { ++ console.log( ++ chalk.green( ++ `Successfully compiled ${SucessfulCompilation.length} out of ${totalComponents} components.` ++ ) ++ ); ++ } ++ ++ if (json) { ++ const extractFileName = (output) => output.fnLoc.filename; ++ const successfulFiles = SucessfulCompilation.map(extractFileName); ++ const unsuccessfulFiles = [...new Set([...OtherFailures, ...ActionableFailures].map(extractFileName))]; ++ console.log(JSON.stringify({ ++ success: successfulFiles, ++ failure: unsuccessfulFiles, ++ })); ++ } + + if (verbose) { + for (const compilation of [...SucessfulCompilation, ...ActionableFailures, ...OtherFailures]) { +@@ -69253,10 +69265,17 @@ function main() { + default: false, + alias: 'v', + }) ++ .option('json', { ++ description: 'print a list of compiled/not-compiled files as JSON', ++ type: 'boolean', ++ default: false, ++ alias: 'j', ++ }) + .parseSync(); + const spinner = ora("Checking").start(); + let src = argv.src; + let verbose = argv.verbose; ++ let json = argv.json; + const globOptions = { + onlyFiles: true, + ignore: [ +@@ -69276,9 +69295,12 @@ function main() { + libraryCompatCheck.run(source, path); + } + spinner.stop(); +- reactCompilerCheck.report(verbose); +- strictModeCheck.report(); +- libraryCompatCheck.report(); ++ reactCompilerCheck.report(verbose, json); ++ // using json option we only want to get list of files ++ if (!json) { ++ strictModeCheck.report(); ++ libraryCompatCheck.report(); ++ } + }); + } + main(); diff --git a/patches/react-native+0.73.4+014+fixPath.patch b/patches/react-native+0.73.4+015+fixPath.patch similarity index 100% rename from patches/react-native+0.73.4+014+fixPath.patch rename to patches/react-native+0.73.4+015+fixPath.patch diff --git a/patches/react-native+0.73.4+014+iOSCoreAnimationBorderRendering.patch b/patches/react-native+0.73.4+016+iOSCoreAnimationBorderRendering.patch similarity index 100% rename from patches/react-native+0.73.4+014+iOSCoreAnimationBorderRendering.patch rename to patches/react-native+0.73.4+016+iOSCoreAnimationBorderRendering.patch diff --git a/patches/react-native+0.73.4+015+copyStateOnClone.patch b/patches/react-native+0.73.4+017+copyStateOnClone.patch similarity index 100% rename from patches/react-native+0.73.4+015+copyStateOnClone.patch rename to patches/react-native+0.73.4+017+copyStateOnClone.patch diff --git a/patches/react-native+0.73.4+015+fixIOSWebViewCrash.patch b/patches/react-native+0.73.4+018+fixIOSWebViewCrash.patch similarity index 100% rename from patches/react-native+0.73.4+015+fixIOSWebViewCrash.patch rename to patches/react-native+0.73.4+018+fixIOSWebViewCrash.patch diff --git a/patches/react-native+0.73.4+016+fixClippedEmojis.patch b/patches/react-native+0.73.4+019+fixClippedEmojis.patch similarity index 100% rename from patches/react-native+0.73.4+016+fixClippedEmojis.patch rename to patches/react-native+0.73.4+019+fixClippedEmojis.patch diff --git a/patches/react-native+0.73.4+016+iOS-textinput-onscroll-event.patch b/patches/react-native+0.73.4+020+iOS-textinput-onscroll-event.patch similarity index 100% rename from patches/react-native+0.73.4+016+iOS-textinput-onscroll-event.patch rename to patches/react-native+0.73.4+020+iOS-textinput-onscroll-event.patch diff --git a/patches/react-native+0.73.4+017+iOS-fix-whitespace-support-sourcemap.patch b/patches/react-native+0.73.4+021+iOS-fix-whitespace-support-sourcemap.patch similarity index 100% rename from patches/react-native+0.73.4+017+iOS-fix-whitespace-support-sourcemap.patch rename to patches/react-native+0.73.4+021+iOS-fix-whitespace-support-sourcemap.patch diff --git a/patches/react-native+0.73.4+022+textInputClear.patch b/patches/react-native+0.73.4+022+textInputClear.patch new file mode 100644 index 000000000000..1cadce6a0783 --- /dev/null +++ b/patches/react-native+0.73.4+022+textInputClear.patch @@ -0,0 +1,66 @@ +diff --git a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +index 7ce04da..123968f 100644 +--- a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm ++++ b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +@@ -452,6 +452,12 @@ - (void)blur + [_backedTextInputView resignFirstResponder]; + } + ++- (void)clear ++{ ++ [self setTextAndSelection:_mostRecentEventCount value:@"" start:0 end:0]; ++ _mostRecentEventCount++; ++} ++ + - (void)setTextAndSelection:(NSInteger)eventCount + value:(NSString *__nullable)value + start:(NSInteger)start +diff --git a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputNativeCommands.h b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputNativeCommands.h +index fe3376a..6a9a45f 100644 +--- a/node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputNativeCommands.h ++++ b/node_modules/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputNativeCommands.h +@@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN + @protocol RCTTextInputViewProtocol + - (void)focus; + - (void)blur; ++- (void)clear; + - (void)setTextAndSelection:(NSInteger)eventCount + value:(NSString *__nullable)value + start:(NSInteger)start +@@ -49,6 +50,19 @@ RCTTextInputHandleCommand(id componentView, const NSSt + return; + } + ++ if ([commandName isEqualToString:@"clear"]) { ++#if RCT_DEBUG ++ if ([args count] != 0) { ++ RCTLogError( ++ @"%@ command %@ received %d arguments, expected %d.", @"TextInput", commandName, (int)[args count], 0); ++ return; ++ } ++#endif ++ ++ [componentView clear]; ++ return; ++ } ++ + if ([commandName isEqualToString:@"setTextAndSelection"]) { + #if RCT_DEBUG + if ([args count] != 4) { +diff --git a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +index 8496a7d..e6bcfc4 100644 +--- a/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java ++++ b/node_modules/react-native/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactTextInputManager.java +@@ -331,6 +331,12 @@ public class ReactTextInputManager extends BaseViewManager + #import +-#import + #import + #import + #import +@@ -32,7 +31,7 @@ + #endif // RCT_NEW_ARCH_ENABLED + + #ifdef RCT_NEW_ARCH_ENABLED +-@interface RNGestureHandlerModule () ++@interface RNGestureHandlerModule () + + @end + #else +@@ -66,9 +65,7 @@ - (void)invalidate + + _manager = nil; + +-#ifdef RCT_NEW_ARCH_ENABLED +- [self.bridge.surfacePresenter removeObserver:self]; +-#else ++#ifndef RCT_NEW_ARCH_ENABLED + [self.bridge.uiManager.observerCoordinator removeObserver:self]; + #endif // RCT_NEW_ARCH_ENABLED + } +@@ -113,9 +110,7 @@ - (void)setBridge:(RCTBridge *)bridge + eventDispatcher:bridge.eventDispatcher]; + _operations = [NSMutableArray new]; + +-#ifdef RCT_NEW_ARCH_ENABLED +- [bridge.surfacePresenter addObserver:self]; +-#else ++#ifndef RCT_NEW_ARCH_ENABLED + [bridge.uiManager.observerCoordinator addObserver:self]; + #endif // RCT_NEW_ARCH_ENABLED + } +@@ -241,27 +236,7 @@ - (void)addOperationBlock:(GestureHandlerOperation)operation + [_operations addObject:operation]; + } + +-#pragma mark - RCTSurfacePresenterObserver +- +-#ifdef RCT_NEW_ARCH_ENABLED +- +-- (void)didMountComponentsWithRootTag:(NSInteger)rootTag +-{ +- RCTAssertMainQueue(); +- +- if (_operations.count == 0) { +- return; +- } +- +- NSArray *operations = _operations; +- _operations = [NSMutableArray new]; +- +- for (GestureHandlerOperation operation in operations) { +- operation(self->_manager); +- } +-} +- +-#else ++#ifndef RCT_NEW_ARCH_ENABLED + + #pragma mark - RCTUIManagerObserver + diff --git a/patches/react-native-plaid-link-sdk+11.11.0.patch b/patches/react-native-plaid-link-sdk+11.11.0.patch new file mode 100644 index 000000000000..28e492f6999f --- /dev/null +++ b/patches/react-native-plaid-link-sdk+11.11.0.patch @@ -0,0 +1,35 @@ +diff --git a/node_modules/react-native-plaid-link-sdk/ios/PLKFabricHelpers.h b/node_modules/react-native-plaid-link-sdk/ios/PLKFabricHelpers.h +index cf70d5e..4e34cd2 100644 +--- a/node_modules/react-native-plaid-link-sdk/ios/PLKFabricHelpers.h ++++ b/node_modules/react-native-plaid-link-sdk/ios/PLKFabricHelpers.h +@@ -5,8 +5,12 @@ + #if __has_include() + #import + #else ++#ifdef USE_FRAMEWORKS ++#import ++#else + #import + #endif ++#endif + + // copied from RCTFollyConvert + folly::dynamic PLKConvertIdToFollyDynamic(id json) +diff --git a/node_modules/react-native-plaid-link-sdk/react-native-plaid-link-sdk.podspec b/node_modules/react-native-plaid-link-sdk/react-native-plaid-link-sdk.podspec +index 7c60081..4a13a3c 100644 +--- a/node_modules/react-native-plaid-link-sdk/react-native-plaid-link-sdk.podspec ++++ b/node_modules/react-native-plaid-link-sdk/react-native-plaid-link-sdk.podspec +@@ -21,6 +21,13 @@ Pod::Spec.new do |s| + # we don't want this to be seen by Swift + s.private_header_files = 'ios/PLKFabricHelpers.h' + ++ if ENV['USE_FRAMEWORKS'] == '1' ++ s.pod_target_xcconfig = { ++ "OTHER_CFLAGS" => "$(inherited) -DUSE_FRAMEWORKS", ++ "OTHER_CPLUSPLUSFLAGS" => "$(inherited) -DUSE_FRAMEWORKS", ++ } ++ end ++ + if fabric_enabled + install_modules_dependencies(s) + else diff --git a/patches/react-native-plaid-link-sdk+11.5.0+001+initial.patch b/patches/react-native-plaid-link-sdk+11.5.0+001+initial.patch deleted file mode 100644 index 6035477256b7..000000000000 --- a/patches/react-native-plaid-link-sdk+11.5.0+001+initial.patch +++ /dev/null @@ -1,4 +0,0 @@ -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.m b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.mm -similarity index 100% -rename from node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.m -rename to node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.mm diff --git a/patches/react-native-plaid-link-sdk+11.5.0+002+turbomodule.patch b/patches/react-native-plaid-link-sdk+11.5.0+002+turbomodule.patch deleted file mode 100644 index 7d5aab6c84cf..000000000000 --- a/patches/react-native-plaid-link-sdk+11.5.0+002+turbomodule.patch +++ /dev/null @@ -1,3287 +0,0 @@ -diff --git a/node_modules/react-native-plaid-link-sdk/README.md b/node_modules/react-native-plaid-link-sdk/README.md -index 93ebca6..7bea608 100644 ---- a/node_modules/react-native-plaid-link-sdk/README.md -+++ b/node_modules/react-native-plaid-link-sdk/README.md -@@ -49,7 +49,6 @@ cd ios && bundle install && bundle exec pod install - - AutoLinking should handle all of the Android setup. - -- - ### React Native Setup - - - To initialize `PlaidLink`, you will need to first create a `link_token` at [/link/token/create](https://plaid.com/docs/#create-link-token). Check out our [QuickStart guide](https://plaid.com/docs/quickstart/#introduction) for additional API information. -@@ -58,7 +57,13 @@ AutoLinking should handle all of the Android setup. - - ```javascript - import { Text } from 'react-native'; --import { PlaidLink, LinkSuccess, LinkExit, LinkLogLevel, LinkIOSPresentationStyle } from 'react-native-plaid-link-sdk'; -+import { -+ PlaidLink, -+ LinkSuccess, -+ LinkExit, -+ LinkLogLevel, -+ LinkIOSPresentationStyle, -+} from 'react-native-plaid-link-sdk'; - - const MyPlaidComponent = () => { - return ( -@@ -77,7 +82,7 @@ const MyPlaidComponent = () => { - // UI is always presented in full screen on Android. - iOSPresentationStyle={LinkIOSPresentationStyle.MODAL} - > -- Add Account -+ Add Account - - ); - }; -@@ -92,6 +97,7 @@ const MyPlaidComponent = () => { - ##### Android OAuth Requirements - - ###### Register your app package name -+ - 1. Log into your [Plaid Dashboard](https://dashboard.plaid.com/developers/api) and navigate to the API page under the Developers tab. - 2. Next to Allowed Android package names click "Configure" then "Add New Android Package Name". - 3. Enter your package name, for example `com.plaid.example`. -@@ -100,17 +106,16 @@ const MyPlaidComponent = () => { - ##### iOS OAuth Requirements - - For iOS OAuth to work, specific requirements must be met. -+ - 1. Redirect URIs must be [registered](https://plaid.com/docs/link/ios/#register-your-redirect-uri), and set up as [universal links](https://developer.apple.com/documentation/xcode/supporting-associated-domains). - 2. Your native iOS application, must be configured with your associated domain. See your iOS [set up universal links](https://plaid.com/docs/link/ios/#set-up-universal-links) for more information. - -- - ##### Link Token OAuth Requirements - - - On iOS you must configure your `link_token` with a [redirect_uri](https://plaid.com/docs/api/tokens/#link-token-create-request-redirect-uri) to support OAuth. When creating a `link_token` for initializing Link on Android, `android_package_name` must be specified and `redirect_uri` must be left blank. - - - On Android you must configure your `link_token` with an [android_package_name](https://plaid.com/docs/api/tokens/#link-token-create-request-android-package-name) to support OAuth. When creating a `link_token` for initializing Link on iOS, `android_package_name` must be left blank and `redirect_uri` should be used instead. - -- - #### To receive onEvent callbacks: - - The React Native Plaid module emits `onEvent` events throughout the account linking process ā€” see [details here](https://plaid.com/docs/link/react-native/#onevent). To receive these events in your React Native app, wrap the `PlaidLink` react component with the following in order to listen for those events: -@@ -139,9 +144,9 @@ class PlaidEventContainer extends React.Component { - You can also use the `usePlaidEmitter` hook in react functional components: - - ```javascript -- usePlaidEmitter((event: LinkEvent) => { -- console.log(event) -- }) -+usePlaidEmitter((event: LinkEvent) => { -+ console.log(event); -+}); - ``` - - ## Upgrading -@@ -165,6 +170,8 @@ While these older versions are expected to continue to work without disruption, - | 11.0.2 | * | [4.0.0+] | 21 | 33 | >=5.0.0 | 14.0 | Active, supports Xcode 15.0.1 | - | 11.0.1 | * | [4.0.0+] | 21 | 33 | >=5.0.0 | 14.0 | Active, supports Xcode 15.0.1 | - | 11.0.0 | * | [4.0.0+] | 21 | 33 | >=5.0.0 | 14.0 | Active, supports Xcode 15.0.1 | -+| 10.13.0 | >= 0.66.0 | [3.14.3+] | 21 | 33 | >=4.7.2 | 11.0 | Active, supports Xcode 14 | -+| 10.12.0 | >= 0.66.0 | [3.14.3+] | 21 | 33 | >=4.7.1 | 11.0 | Active, supports Xcode 14 | - | 10.11.0 | >= 0.66.0 | [3.14.1+] | 21 | 33 | >=4.7.1 | 11.0 | Active, supports Xcode 14 | - | ~10.10.0~ | >= 0.66.0 | [3.14.2+] | 21 | 33 | >=4.7.1 | 11.0 | **Deprecated** | - | 10.9.1 | >= 0.66.0 | [3.14.1+] | 21 | 33 | >=4.7.0 | 11.0 | Active, supports Xcode 14 | -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/checksums.lock b/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/checksums.lock -deleted file mode 100644 -index b5da584..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/checksums.lock and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/md5-checksums.bin b/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/md5-checksums.bin -deleted file mode 100644 -index ef608b4..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/md5-checksums.bin and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/sha1-checksums.bin b/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/sha1-checksums.bin -deleted file mode 100644 -index 0856ae4..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/checksums/sha1-checksums.bin and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/dependencies-accessors/dependencies-accessors.lock b/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/dependencies-accessors/dependencies-accessors.lock -deleted file mode 100644 -index 12aea68..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/dependencies-accessors/dependencies-accessors.lock and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/dependencies-accessors/gc.properties b/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/dependencies-accessors/gc.properties -deleted file mode 100644 -index e69de29..0000000 -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/fileChanges/last-build.bin b/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/fileChanges/last-build.bin -deleted file mode 100644 -index f76dd23..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/fileChanges/last-build.bin and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/fileHashes/fileHashes.lock b/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/fileHashes/fileHashes.lock -deleted file mode 100644 -index 752a252..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/fileHashes/fileHashes.lock and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/gc.properties b/node_modules/react-native-plaid-link-sdk/android/.gradle/7.4.2/gc.properties -deleted file mode 100644 -index e69de29..0000000 -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/node_modules/react-native-plaid-link-sdk/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock -deleted file mode 100644 -index 470ca89..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/buildOutputCleanup/cache.properties b/node_modules/react-native-plaid-link-sdk/android/.gradle/buildOutputCleanup/cache.properties -deleted file mode 100644 -index 1439672..0000000 ---- a/node_modules/react-native-plaid-link-sdk/android/.gradle/buildOutputCleanup/cache.properties -+++ /dev/null -@@ -1,2 +0,0 @@ --#Thu Nov 09 09:41:17 PST 2023 --gradle.version=7.4.2 -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/checksums.lock b/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/checksums.lock -deleted file mode 100644 -index 34602e1..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/checksums.lock and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/md5-checksums.bin b/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/md5-checksums.bin -deleted file mode 100644 -index 2420123..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/md5-checksums.bin and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/sha1-checksums.bin b/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/sha1-checksums.bin -deleted file mode 100644 -index 1081852..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/android/.gradle/checksums/sha1-checksums.bin and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/android/.gradle/vcs-1/gc.properties b/node_modules/react-native-plaid-link-sdk/android/.gradle/vcs-1/gc.properties -deleted file mode 100644 -index e69de29..0000000 -diff --git a/node_modules/react-native-plaid-link-sdk/android/.idea/gradle.xml b/node_modules/react-native-plaid-link-sdk/android/.idea/gradle.xml -deleted file mode 100644 -index 0364d75..0000000 ---- a/node_modules/react-native-plaid-link-sdk/android/.idea/gradle.xml -+++ /dev/null -@@ -1,14 +0,0 @@ -- -- -- -- -- -- -- -\ No newline at end of file -diff --git a/node_modules/react-native-plaid-link-sdk/android/.idea/misc.xml b/node_modules/react-native-plaid-link-sdk/android/.idea/misc.xml -deleted file mode 100644 -index a318cae..0000000 ---- a/node_modules/react-native-plaid-link-sdk/android/.idea/misc.xml -+++ /dev/null -@@ -1,9 +0,0 @@ -- -- -- -- -- -- -- -- -\ No newline at end of file -diff --git a/node_modules/react-native-plaid-link-sdk/android/.idea/vcs.xml b/node_modules/react-native-plaid-link-sdk/android/.idea/vcs.xml -deleted file mode 100644 -index 6c0b863..0000000 ---- a/node_modules/react-native-plaid-link-sdk/android/.idea/vcs.xml -+++ /dev/null -@@ -1,6 +0,0 @@ -- -- -- -- -- -- -\ No newline at end of file -diff --git a/node_modules/react-native-plaid-link-sdk/android/build.gradle b/node_modules/react-native-plaid-link-sdk/android/build.gradle -index 2d9e2ce..e88208b 100644 ---- a/node_modules/react-native-plaid-link-sdk/android/build.gradle -+++ b/node_modules/react-native-plaid-link-sdk/android/build.gradle -@@ -12,7 +12,12 @@ allprojects { - - - buildscript { -- ext.kotlin_version = '1.8.22' -+ ext { -+ kotlin_version = '1.8.22' -+ } -+ ext.safeExtGet = {prop, fallback -> -+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback -+ } - repositories { - google() - mavenCentral() -@@ -25,10 +30,32 @@ buildscript { - } - } - -+def isNewArchitectureEnabled() { -+ // To opt-in for the New Architecture, you can either: -+ // - Set `newArchEnabled` to true inside the `gradle.properties` file -+ // - Invoke gradle with `-newArchEnabled=true` -+ // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` -+ return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" -+} -+ -+if (isNewArchitectureEnabled()) { -+ apply plugin: "com.facebook.react" -+} -+ - apply plugin: 'com.android.library' - apply plugin: "kotlin-android" - - android { -+ -+ // Used to override the NDK path/version on internal CI or by allowing -+ // users to customize the NDK path/version from their root project (e.g. for M1 support) -+ if (rootProject.hasProperty("ndkPath")) { -+ ndkPath rootProject.ext.ndkPath -+ } -+ if (rootProject.hasProperty("ndkVersion")) { -+ ndkVersion rootProject.ext.ndkVersion -+ } -+ - def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger() - if (agpVersion >= 7) { - namespace 'com.plaid' -@@ -52,6 +79,14 @@ android { - } - } - -+ sourceSets.main { -+ java { -+ if (!isNewArchitectureEnabled()) { -+ srcDirs += 'src/paper/java' -+ } -+ } -+ } -+ - buildTypes { - release { - debuggable = false -diff --git a/node_modules/react-native-plaid-link-sdk/android/local.properties b/node_modules/react-native-plaid-link-sdk/android/local.properties -deleted file mode 100644 -index 0b4e321..0000000 ---- a/node_modules/react-native-plaid-link-sdk/android/local.properties -+++ /dev/null -@@ -1,8 +0,0 @@ --## This file must *NOT* be checked into Version Control Systems, --# as it contains information specific to your local configuration. --# --# Location of the SDK. This is only used by Gradle. --# For customization when using a Version Control System, please read the --# header note. --#Fri Aug 11 13:58:32 PDT 2023 --sdk.dir=/Users/dtroupe/Library/Android/sdk -diff --git a/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PLKEmbeddedViewManager.kt b/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PLKEmbeddedViewManager.kt -index c73011f..66fd266 100644 ---- a/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PLKEmbeddedViewManager.kt -+++ b/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PLKEmbeddedViewManager.kt -@@ -19,9 +19,9 @@ class PLKEmbeddedViewManager : SimpleViewManager() { - } - - override fun getExportedCustomBubblingEventTypeConstants(): Map { -- return mapOf( -- EVENT_NAME to mapOf( -- "phasedRegistrationNames" to mapOf( -+ return mutableMapOf( -+ EVENT_NAME to mutableMapOf( -+ "phasedRegistrationNames" to mutableMapOf( - "bubbled" to EVENT_NAME - ) - )) -diff --git a/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PlaidModule.kt b/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PlaidModule.kt -index 293374a..b79352e 100644 ---- a/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PlaidModule.kt -+++ b/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PlaidModule.kt -@@ -24,9 +24,9 @@ import org.json.JSONException - import org.json.JSONObject - import java.util.ArrayList - --@ReactModule(name = PlaidModule.TAG) -+@ReactModule(name = PlaidModule.NAME) - class PlaidModule internal constructor(reactContext: ReactApplicationContext) : -- ReactContextBaseJavaModule(reactContext), ActivityEventListener { -+ NativePlaidLinkModuleAndroidSpec(reactContext), ActivityEventListener { - - val mActivityResultManager by lazy { ActivityResultManager() } - -@@ -38,11 +38,11 @@ class PlaidModule internal constructor(reactContext: ReactApplicationContext) : - companion object { - private const val LINK_TOKEN_PREFIX = "link" - -- const val TAG = "PlaidAndroid" -+ const val NAME = "PlaidAndroid" - } - - override fun getName(): String { -- return PlaidModule.TAG -+ return NAME - } - - override fun initialize() { -@@ -78,7 +78,7 @@ class PlaidModule internal constructor(reactContext: ReactApplicationContext) : - - @ReactMethod - @Suppress("unused") -- fun startLinkActivityForResult( -+ override fun startLinkActivityForResult( - token: String, - noLoadingState: Boolean, - logLevel: String, -@@ -113,6 +113,10 @@ class PlaidModule internal constructor(reactContext: ReactApplicationContext) : - } - } - -+ override fun addListener(eventName: String?) = Unit -+ -+ override fun removeListeners(count: Double) = Unit -+ - private fun maybeGetStringField(obj: JSONObject, fieldName: String): String? { - if (obj.has(fieldName) && !TextUtils.isEmpty(obj.getString(fieldName))) { - return obj.getString(fieldName) -diff --git a/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PlaidPackage.java b/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PlaidPackage.java -index c59299e..d6b310e 100644 ---- a/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PlaidPackage.java -+++ b/node_modules/react-native-plaid-link-sdk/android/src/main/java/com/plaid/PlaidPackage.java -@@ -6,19 +6,54 @@ import java.util.List; - import java.util.Map; - - import com.facebook.react.TurboReactPackage; -+import com.facebook.react.ViewManagerOnDemandReactPackage; -+import com.facebook.react.bridge.ModuleSpec; - import com.facebook.react.bridge.NativeModule; - import com.facebook.react.bridge.ReactApplicationContext; -+import com.facebook.react.module.annotations.ReactModule; -+import com.facebook.react.module.annotations.ReactModuleList; - import com.facebook.react.module.model.ReactModuleInfo; - import com.facebook.react.module.model.ReactModuleInfoProvider; -+import com.facebook.react.turbomodule.core.interfaces.TurboModule; - import com.facebook.react.uimanager.ViewManager; - --@SuppressWarnings("unused") --public class PlaidPackage extends TurboReactPackage { -+import javax.annotation.Nonnull; -+import javax.annotation.Nullable; - -+@ReactModuleList(nativeModules = {PlaidModule.class}) -+public class PlaidPackage extends TurboReactPackage implements ViewManagerOnDemandReactPackage { -+ -+ /** -+ * {@inheritDoc} -+ */ -+ @Override -+ public List getViewManagerNames(ReactApplicationContext reactContext) { -+ return null; -+ } -+ -+ @Override -+ protected List getViewManagers(ReactApplicationContext reactContext) { -+ return null; -+ } -+ -+ /** -+ * {@inheritDoc} -+ */ - @Override -- public NativeModule getModule( -- String name, ReactApplicationContext reactContext) { -- return new PlaidModule(reactContext); -+ public @Nullable -+ ViewManager createViewManager( -+ ReactApplicationContext reactContext, String viewManagerName) { -+ return null; -+ } -+ -+ @Override -+ public NativeModule getModule(String name, @Nonnull ReactApplicationContext reactContext) { -+ switch (name) { -+ case PlaidModule.NAME: -+ return new PlaidModule(reactContext); -+ default: -+ return null; -+ } - } - - @Override -@@ -28,19 +63,44 @@ public class PlaidPackage extends TurboReactPackage { - - @Override - public ReactModuleInfoProvider getReactModuleInfoProvider() { -- return () -> { -- Map map = new HashMap<>(); -- map.put( -- "PlaidAndroid", -- new ReactModuleInfo( -- "PlaidAndroid", -- "com.reactlibrary.PlaidModule", -- false, -- false, -- true, -- false, -- false)); -- return map; -- }; -+ try { -+ Class reactModuleInfoProviderClass = -+ Class.forName("com.plaid.PlaidPackage$$ReactModuleInfoProvider"); -+ return (ReactModuleInfoProvider) reactModuleInfoProviderClass.newInstance(); -+ } catch (ClassNotFoundException e) { -+ // ReactModuleSpecProcessor does not run at build-time. Create this ReactModuleInfoProvider by -+ // hand. -+ return new ReactModuleInfoProvider() { -+ @Override -+ public Map getReactModuleInfos() { -+ final Map reactModuleInfoMap = new HashMap<>(); -+ -+ Class[] moduleList = -+ new Class[]{ -+ PlaidModule.class, -+ }; -+ -+ for (Class moduleClass : moduleList) { -+ ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class); -+ -+ reactModuleInfoMap.put( -+ reactModule.name(), -+ new ReactModuleInfo( -+ reactModule.name(), -+ moduleClass.getName(), -+ reactModule.canOverrideExistingModule(), -+ reactModule.needsEagerInit(), -+ reactModule.hasConstants(), -+ reactModule.isCxxModule(), -+ TurboModule.class.isAssignableFrom(moduleClass))); -+ } -+ -+ return reactModuleInfoMap; -+ } -+ }; -+ } catch (InstantiationException | IllegalAccessException e) { -+ throw new RuntimeException( -+ "No ReactModuleInfoProvider for com.plaid.PlaidPackage$$ReactModuleInfoProvider", e); -+ } - } - } -diff --git a/node_modules/react-native-plaid-link-sdk/android/src/paper/java/com/plaid/NativePlaidLinkModuleAndroidSpec.java b/node_modules/react-native-plaid-link-sdk/android/src/paper/java/com/plaid/NativePlaidLinkModuleAndroidSpec.java -new file mode 100644 -index 0000000..fee5a11 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/android/src/paper/java/com/plaid/NativePlaidLinkModuleAndroidSpec.java -@@ -0,0 +1,46 @@ -+ -+/** -+ * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). -+ * -+ * Do not edit this file as changes may cause incorrect behavior and will be lost -+ * once the code is regenerated. -+ * -+ * @generated by codegen project: GenerateModuleJavaSpec.js -+ * -+ * @nolint -+ */ -+ -+package com.plaid; -+ -+import com.facebook.proguard.annotations.DoNotStrip; -+import com.facebook.react.bridge.Callback; -+import com.facebook.react.bridge.ReactApplicationContext; -+import com.facebook.react.bridge.ReactContextBaseJavaModule; -+import com.facebook.react.bridge.ReactMethod; -+import com.facebook.react.turbomodule.core.interfaces.TurboModule; -+import javax.annotation.Nonnull; -+ -+public abstract class NativePlaidLinkModuleAndroidSpec extends ReactContextBaseJavaModule implements TurboModule { -+ public static final String NAME = "PlaidAndroid"; -+ -+ public NativePlaidLinkModuleAndroidSpec(ReactApplicationContext reactContext) { -+ super(reactContext); -+ } -+ -+ @Override -+ public @Nonnull String getName() { -+ return NAME; -+ } -+ -+ @ReactMethod -+ @DoNotStrip -+ public abstract void startLinkActivityForResult(String token, boolean noLoadingState, String logLevel, Callback onSuccessCallback, Callback onExitCallback); -+ -+ @ReactMethod -+ @DoNotStrip -+ public abstract void addListener(String eventName); -+ -+ @ReactMethod -+ @DoNotStrip -+ public abstract void removeListeners(double count); -+} -diff --git a/node_modules/react-native-plaid-link-sdk/dist/EmbeddedLink/EmbeddedLinkView.js b/node_modules/react-native-plaid-link-sdk/dist/EmbeddedLink/EmbeddedLinkView.js -index c7b1e96..c429da7 100644 ---- a/node_modules/react-native-plaid-link-sdk/dist/EmbeddedLink/EmbeddedLinkView.js -+++ b/node_modules/react-native-plaid-link-sdk/dist/EmbeddedLink/EmbeddedLinkView.js -@@ -1,55 +1,69 @@ - import React from 'react'; - import NativeEmbeddedLinkView from './NativeEmbeddedLinkView'; - class EmbeddedEvent { -- constructor(event) { -- this.eventName = event.eventName; -- this.metadata = event.metadata; -- } -+ constructor(event) { -+ this.eventName = event.eventName; -+ this.metadata = event.metadata; -+ } - } - class EmbeddedExit { -- constructor(event) { -- this.error = event.error; -- this.metadata = event.metadata; -- } -+ constructor(event) { -+ this.error = event.error; -+ this.metadata = event.metadata; -+ } - } - class EmbeddedSuccess { -- constructor(event) { -- this.publicToken = event.publicToken; -- this.metadata = event.metadata; -- } -+ constructor(event) { -+ this.publicToken = event.publicToken; -+ this.metadata = event.metadata; -+ } - } --export const EmbeddedLinkView = (props) => { -- const { token, iOSPresentationStyle, onEvent, onSuccess, onExit, style } = props; -- const onEmbeddedEvent = (event) => { -- switch (event.nativeEvent.embeddedEventName) { -- case 'onSuccess': { -- if (!onSuccess) { -- return; -- } -- const embeddedSuccess = new EmbeddedSuccess(event.nativeEvent); -- onSuccess(embeddedSuccess); -- break; -- } -- case 'onExit': { -- if (!onExit) { -- return; -- } -- const embeddedExit = new EmbeddedExit(event.nativeEvent); -- onExit(embeddedExit); -- break; -- } -- case 'onEvent': { -- if (!onEvent) { -- return; -- } -- const embeddedEvent = new EmbeddedEvent(event.nativeEvent); -- onEvent(embeddedEvent); -- break; -- } -- default: { -- return; -- } -+export const EmbeddedLinkView = props => { -+ const { -+ token, -+ iOSPresentationStyle, -+ onEvent, -+ onSuccess, -+ onExit, -+ style, -+ } = props; -+ const onEmbeddedEvent = event => { -+ switch (event.nativeEvent.embeddedEventName) { -+ case 'onSuccess': { -+ if (!onSuccess) { -+ return; - } -- }; -- return ; -+ const embeddedSuccess = new EmbeddedSuccess(event.nativeEvent); -+ onSuccess(embeddedSuccess); -+ break; -+ } -+ case 'onExit': { -+ if (!onExit) { -+ return; -+ } -+ const embeddedExit = new EmbeddedExit(event.nativeEvent); -+ onExit(embeddedExit); -+ break; -+ } -+ case 'onEvent': { -+ if (!onEvent) { -+ return; -+ } -+ const embeddedEvent = new EmbeddedEvent(event.nativeEvent); -+ onEvent(embeddedEvent); -+ break; -+ } -+ default: { -+ return; -+ } -+ } -+ }; -+ return ( -+ -+ ); - }; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/PlaidLink.d.ts b/node_modules/react-native-plaid-link-sdk/dist/PlaidLink.d.ts -index a48b319..43205dd 100644 ---- a/node_modules/react-native-plaid-link-sdk/dist/PlaidLink.d.ts -+++ b/node_modules/react-native-plaid-link-sdk/dist/PlaidLink.d.ts -@@ -4,9 +4,9 @@ import { LinkEventListener, PlaidLinkComponentProps, PlaidLinkProps } from './Ty - * A hook that registers a listener on the Plaid emitter for the 'onEvent' type. - * The listener is cleaned up when this view is unmounted - * -- * @param LinkEventListener the listener to call -+ * @param linkEventListener the listener to call - */ --export declare const usePlaidEmitter: (LinkEventListener: LinkEventListener) => void; -+export declare const usePlaidEmitter: (linkEventListener: LinkEventListener) => void; - export declare const openLink: (props: PlaidLinkProps) => Promise; - export declare const dismissLink: () => void; - export declare const PlaidLink: (props: PlaidLinkComponentProps) => React.JSX.Element; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/PlaidLink.js b/node_modules/react-native-plaid-link-sdk/dist/PlaidLink.js -index 21da2bc..6c43633 100644 ---- a/node_modules/react-native-plaid-link-sdk/dist/PlaidLink.js -+++ b/node_modules/react-native-plaid-link-sdk/dist/PlaidLink.js -@@ -1,83 +1,146 @@ --var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { -- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } -- return new (P || (P = Promise))(function (resolve, reject) { -- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } -- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } -- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } -- step((generator = generator.apply(thisArg, _arguments || [])).next()); -+var __awaiter = -+ (this && this.__awaiter) || -+ function(thisArg, _arguments, P, generator) { -+ function adopt(value) { -+ return value instanceof P -+ ? value -+ : new P(function(resolve) { -+ resolve(value); -+ }); -+ } -+ return new (P || (P = Promise))(function(resolve, reject) { -+ function fulfilled(value) { -+ try { -+ step(generator.next(value)); -+ } catch (e) { -+ reject(e); -+ } -+ } -+ function rejected(value) { -+ try { -+ step(generator['throw'](value)); -+ } catch (e) { -+ reject(e); -+ } -+ } -+ function step(result) { -+ result.done -+ ? resolve(result.value) -+ : adopt(result.value).then(fulfilled, rejected); -+ } -+ step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); --}; -+ }; -+var _a; - import React, { useEffect } from 'react'; --import { NativeEventEmitter, NativeModules, Platform, TouchableOpacity, } from 'react-native'; --import { LinkIOSPresentationStyle, LinkLogLevel, } from './Types'; -+import { NativeEventEmitter, Platform, TouchableOpacity } from 'react-native'; -+import { LinkIOSPresentationStyle, LinkLogLevel } from './Types'; -+import RNLinksdkAndroid from './fabric/NativePlaidLinkModuleAndroid'; -+import RNLinksdkiOS from './fabric/NativePlaidLinkModuleiOS'; -+const RNLinksdk = -+ (_a = Platform.OS === 'android' ? RNLinksdkAndroid : RNLinksdkiOS) !== null && -+ _a !== void 0 -+ ? _a -+ : undefined; - /** - * A hook that registers a listener on the Plaid emitter for the 'onEvent' type. - * The listener is cleaned up when this view is unmounted - * -- * @param LinkEventListener the listener to call -+ * @param linkEventListener the listener to call - */ --export const usePlaidEmitter = (LinkEventListener) => { -- useEffect(() => { -- const emitter = new NativeEventEmitter(Platform.OS === 'ios' -- ? NativeModules.RNLinksdk -- : NativeModules.PlaidAndroid); -- const listener = emitter.addListener('onEvent', LinkEventListener); -- // Clean up after this effect: -- return function cleanup() { -- listener.remove(); -- }; -- }, []); -+export const usePlaidEmitter = linkEventListener => { -+ useEffect(() => { -+ const emitter = new NativeEventEmitter(RNLinksdk); -+ const listener = emitter.addListener('onEvent', linkEventListener); -+ // Clean up after this effect: -+ return function cleanup() { -+ listener.remove(); -+ }; -+ }, []); - }; --export const openLink = (props) => __awaiter(void 0, void 0, void 0, function* () { -- var _a, _b; -+export const openLink = props => -+ __awaiter(void 0, void 0, void 0, function*() { -+ var _b, _c; - let config = props.tokenConfig; -- let noLoadingState = (_a = config.noLoadingState) !== null && _a !== void 0 ? _a : false; -+ let noLoadingState = -+ (_b = config.noLoadingState) !== null && _b !== void 0 ? _b : false; - if (Platform.OS === 'android') { -- NativeModules.PlaidAndroid.startLinkActivityForResult(config.token, noLoadingState, (_b = config.logLevel) !== null && _b !== void 0 ? _b : LinkLogLevel.ERROR, (result) => { -- if (props.onSuccess != null) { -- props.onSuccess(result); -- } -- }, (result) => { -- if (props.onExit != null) { -- if (result.error != null && result.error.displayMessage != null) { -- //TODO(RNSDK-118): Remove errorDisplayMessage field in next major update. -- result.error.errorDisplayMessage = result.error.displayMessage; -- } -- props.onExit(result); -+ if (RNLinksdkAndroid === null) { -+ throw new Error( -+ '[react-native-plaid-link-sdk] RNLinksdkAndroid is not defined', -+ ); -+ } -+ RNLinksdkAndroid.startLinkActivityForResult( -+ config.token, -+ noLoadingState, -+ (_c = config.logLevel) !== null && _c !== void 0 -+ ? _c -+ : LinkLogLevel.ERROR, -+ // @ts-ignore we use Object type in the spec file as it maps to NSDictionary and ReadableMap -+ result => { -+ if (props.onSuccess != null) { -+ props.onSuccess(result); -+ } -+ }, -+ result => { -+ if (props.onExit != null) { -+ if (result.error != null && result.error.displayMessage != null) { -+ //TODO(RNSDK-118): Remove errorDisplayMessage field in next major update. -+ result.error.errorDisplayMessage = result.error.displayMessage; - } -- }); -- } -- else { -- NativeModules.RNLinksdk.create(config.token, noLoadingState); -- let presentFullScreen = props.iOSPresentationStyle == LinkIOSPresentationStyle.FULL_SCREEN; -- NativeModules.RNLinksdk.open(presentFullScreen, (result) => { -- if (props.onSuccess != null) { -- props.onSuccess(result); -- } -- }, (error, result) => { -- if (props.onExit != null) { -- if (error) { -- var data = result || {}; -- data.error = error; -- props.onExit(data); -- } -- else { -- props.onExit(result); -- } -+ props.onExit(result); -+ } -+ }, -+ ); -+ } else { -+ if (RNLinksdkiOS === null) { -+ throw new Error( -+ '[react-native-plaid-link-sdk] RNLinksdkiOS is not defined', -+ ); -+ } -+ RNLinksdkiOS.create(config.token, noLoadingState); -+ let presentFullScreen = -+ props.iOSPresentationStyle == LinkIOSPresentationStyle.FULL_SCREEN; -+ RNLinksdkiOS.open( -+ presentFullScreen, -+ // @ts-ignore we use Object type in the spec file as it maps to NSDictionary and ReadableMap -+ result => { -+ if (props.onSuccess != null) { -+ props.onSuccess(result); -+ } -+ }, -+ (error, result) => { -+ if (props.onExit != null) { -+ if (error) { -+ var data = result || {}; -+ data.error = error; -+ props.onExit(data); -+ } else { -+ props.onExit(result); - } -- }); -+ } -+ }, -+ ); - } --}); -+ }); - export const dismissLink = () => { -- if (Platform.OS === 'ios') { -- NativeModules.RNLinksdk.dismiss(); -+ if (Platform.OS === 'ios') { -+ if (RNLinksdkiOS === null) { -+ throw new Error( -+ '[react-native-plaid-link-sdk] RNLinksdkiOS is not defined', -+ ); - } -+ RNLinksdkiOS.dismiss(); -+ } - }; --export const PlaidLink = (props) => { -- function onPress() { -- var _a; -- (_a = props.onPress) === null || _a === void 0 ? void 0 : _a.call(props); -- openLink(props); -- } -- return {props.children}; -+export const PlaidLink = props => { -+ function onPress() { -+ var _a; -+ (_a = props.onPress) === null || _a === void 0 ? void 0 : _a.call(props); -+ openLink(props); -+ } -+ return ( -+ // @ts-ignore some types directories misconfiguration -+ {props.children} -+ ); - }; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/Types.js b/node_modules/react-native-plaid-link-sdk/dist/Types.js -index 184adad..11b34e3 100644 ---- a/node_modules/react-native-plaid-link-sdk/dist/Types.js -+++ b/node_modules/react-native-plaid-link-sdk/dist/Types.js -@@ -1,430 +1,681 @@ - export var LinkLogLevel; --(function (LinkLogLevel) { -- LinkLogLevel["DEBUG"] = "debug"; -- LinkLogLevel["INFO"] = "info"; -- LinkLogLevel["WARN"] = "warn"; -- LinkLogLevel["ERROR"] = "error"; -+(function(LinkLogLevel) { -+ LinkLogLevel['DEBUG'] = 'debug'; -+ LinkLogLevel['INFO'] = 'info'; -+ LinkLogLevel['WARN'] = 'warn'; -+ LinkLogLevel['ERROR'] = 'error'; - })(LinkLogLevel || (LinkLogLevel = {})); - export var PlaidEnvironment; --(function (PlaidEnvironment) { -- PlaidEnvironment["PRODUCTION"] = "production"; -- PlaidEnvironment["DEVELOPMENT"] = "development"; -- PlaidEnvironment["SANDBOX"] = "sandbox"; -+(function(PlaidEnvironment) { -+ PlaidEnvironment['PRODUCTION'] = 'production'; -+ PlaidEnvironment['DEVELOPMENT'] = 'development'; -+ PlaidEnvironment['SANDBOX'] = 'sandbox'; - })(PlaidEnvironment || (PlaidEnvironment = {})); - export var PlaidProduct; --(function (PlaidProduct) { -- PlaidProduct["ASSETS"] = "assets"; -- PlaidProduct["AUTH"] = "auth"; -- PlaidProduct["DEPOSIT_SWITCH"] = "deposit_switch"; -- PlaidProduct["IDENTITY"] = "identity"; -- PlaidProduct["INCOME"] = "income"; -- PlaidProduct["INVESTMENTS"] = "investments"; -- PlaidProduct["LIABILITIES"] = "liabilities"; -- PlaidProduct["LIABILITIES_REPORT"] = "liabilities_report"; -- PlaidProduct["PAYMENT_INITIATION"] = "payment_initiation"; -- PlaidProduct["TRANSACTIONS"] = "transactions"; -+(function(PlaidProduct) { -+ PlaidProduct['ASSETS'] = 'assets'; -+ PlaidProduct['AUTH'] = 'auth'; -+ PlaidProduct['DEPOSIT_SWITCH'] = 'deposit_switch'; -+ PlaidProduct['IDENTITY'] = 'identity'; -+ PlaidProduct['INCOME'] = 'income'; -+ PlaidProduct['INVESTMENTS'] = 'investments'; -+ PlaidProduct['LIABILITIES'] = 'liabilities'; -+ PlaidProduct['LIABILITIES_REPORT'] = 'liabilities_report'; -+ PlaidProduct['PAYMENT_INITIATION'] = 'payment_initiation'; -+ PlaidProduct['TRANSACTIONS'] = 'transactions'; - })(PlaidProduct || (PlaidProduct = {})); - export var LinkAccountType; --(function (LinkAccountType) { -- LinkAccountType["CREDIT"] = "credit"; -- LinkAccountType["DEPOSITORY"] = "depository"; -- LinkAccountType["INVESTMENT"] = "investment"; -- LinkAccountType["LOAN"] = "loan"; -- LinkAccountType["OTHER"] = "other"; -+(function(LinkAccountType) { -+ LinkAccountType['CREDIT'] = 'credit'; -+ LinkAccountType['DEPOSITORY'] = 'depository'; -+ LinkAccountType['INVESTMENT'] = 'investment'; -+ LinkAccountType['LOAN'] = 'loan'; -+ LinkAccountType['OTHER'] = 'other'; - })(LinkAccountType || (LinkAccountType = {})); - export var LinkAccountSubtypes; --(function (LinkAccountSubtypes) { -- LinkAccountSubtypes["ALL"] = "all"; -- LinkAccountSubtypes["CREDIT_CARD"] = "credit card"; -- LinkAccountSubtypes["PAYPAL"] = "paypal"; -- LinkAccountSubtypes["AUTO"] = "auto"; -- LinkAccountSubtypes["BUSINESS"] = "business"; -- LinkAccountSubtypes["COMMERCIAL"] = "commercial"; -- LinkAccountSubtypes["CONSTRUCTION"] = "construction"; -- LinkAccountSubtypes["CONSUMER"] = "consumer"; -- LinkAccountSubtypes["HOME_EQUITY"] = "home equity"; -- LinkAccountSubtypes["LINE_OF_CREDIT"] = "line of credit"; -- LinkAccountSubtypes["LOAN"] = "loan"; -- LinkAccountSubtypes["MORTGAGE"] = "mortgage"; -- LinkAccountSubtypes["OVERDRAFT"] = "overdraft"; -- LinkAccountSubtypes["STUDENT"] = "student"; -- LinkAccountSubtypes["CASH_MANAGEMENT"] = "cash management"; -- LinkAccountSubtypes["CD"] = "cd"; -- LinkAccountSubtypes["CHECKING"] = "checking"; -- LinkAccountSubtypes["EBT"] = "ebt"; -- LinkAccountSubtypes["HSA"] = "hsa"; -- LinkAccountSubtypes["MONEY_MARKET"] = "money market"; -- LinkAccountSubtypes["PREPAID"] = "prepaid"; -- LinkAccountSubtypes["SAVINGS"] = "savings"; -- LinkAccountSubtypes["FOUR_0_1_A"] = "401a"; -- LinkAccountSubtypes["FOUR_0_1_K"] = "401k"; -- LinkAccountSubtypes["FOUR_0_3_B"] = "403B"; -- LinkAccountSubtypes["FOUR_5_7_B"] = "457b"; -- LinkAccountSubtypes["FIVE_2_9"] = "529"; -- LinkAccountSubtypes["BROKERAGE"] = "brokerage"; -- LinkAccountSubtypes["CASH_ISA"] = "cash isa"; -- LinkAccountSubtypes["EDUCATION_SAVINGS_ACCOUNT"] = "education savings account"; -- LinkAccountSubtypes["FIXED_ANNUNITY"] = "fixed annuity"; -- LinkAccountSubtypes["GIC"] = "gic"; -- LinkAccountSubtypes["HEALTH_REIMBURSEMENT_ARRANGEMENT"] = "health reimbursement arrangement"; -- LinkAccountSubtypes["IRA"] = "ira"; -- LinkAccountSubtypes["ISA"] = "isa"; -- LinkAccountSubtypes["KEOGH"] = "keogh"; -- LinkAccountSubtypes["LIF"] = "lif"; -- LinkAccountSubtypes["LIRA"] = "lira"; -- LinkAccountSubtypes["LRIF"] = "lrif"; -- LinkAccountSubtypes["LRSP"] = "lrsp"; -- LinkAccountSubtypes["MUTUAL_FUND"] = "mutual fund"; -- LinkAccountSubtypes["NON_TAXABLE_BROKERAGE_ACCOUNT"] = "non-taxable brokerage account"; -- LinkAccountSubtypes["PENSION"] = "pension"; -- LinkAccountSubtypes["PLAN"] = "plan"; -- LinkAccountSubtypes["PRIF"] = "prif"; -- LinkAccountSubtypes["PROFIT_SHARING_PLAN"] = "profit sharing plan"; -- LinkAccountSubtypes["RDSP"] = "rdsp"; -- LinkAccountSubtypes["RESP"] = "resp"; -- LinkAccountSubtypes["RETIREMENT"] = "retirement"; -- LinkAccountSubtypes["RLIF"] = "rlif"; -- LinkAccountSubtypes["ROTH_401K"] = "roth 401k"; -- LinkAccountSubtypes["ROTH"] = "roth"; -- LinkAccountSubtypes["RRIF"] = "rrif"; -- LinkAccountSubtypes["RRSP"] = "rrsp"; -- LinkAccountSubtypes["SARSEP"] = "sarsep"; -- LinkAccountSubtypes["SEP_IRA"] = "sep ira"; -- LinkAccountSubtypes["SIMPLE_IRA"] = "simple ira"; -- LinkAccountSubtypes["SIPP"] = "sipp"; -- LinkAccountSubtypes["STOCK_PLAN"] = "stock plan"; -- LinkAccountSubtypes["TFSA"] = "tfsa"; -- LinkAccountSubtypes["THRIFT_SAVINGS_PLAN"] = "thrift savings plan"; -- LinkAccountSubtypes["TRUST"] = "trust"; -- LinkAccountSubtypes["UGMA"] = "ugma"; -- LinkAccountSubtypes["UTMA"] = "utma"; -- LinkAccountSubtypes["VARIABLE_ANNUITY"] = "variable annuity"; -+(function(LinkAccountSubtypes) { -+ LinkAccountSubtypes['ALL'] = 'all'; -+ LinkAccountSubtypes['CREDIT_CARD'] = 'credit card'; -+ LinkAccountSubtypes['PAYPAL'] = 'paypal'; -+ LinkAccountSubtypes['AUTO'] = 'auto'; -+ LinkAccountSubtypes['BUSINESS'] = 'business'; -+ LinkAccountSubtypes['COMMERCIAL'] = 'commercial'; -+ LinkAccountSubtypes['CONSTRUCTION'] = 'construction'; -+ LinkAccountSubtypes['CONSUMER'] = 'consumer'; -+ LinkAccountSubtypes['HOME_EQUITY'] = 'home equity'; -+ LinkAccountSubtypes['LINE_OF_CREDIT'] = 'line of credit'; -+ LinkAccountSubtypes['LOAN'] = 'loan'; -+ LinkAccountSubtypes['MORTGAGE'] = 'mortgage'; -+ LinkAccountSubtypes['OVERDRAFT'] = 'overdraft'; -+ LinkAccountSubtypes['STUDENT'] = 'student'; -+ LinkAccountSubtypes['CASH_MANAGEMENT'] = 'cash management'; -+ LinkAccountSubtypes['CD'] = 'cd'; -+ LinkAccountSubtypes['CHECKING'] = 'checking'; -+ LinkAccountSubtypes['EBT'] = 'ebt'; -+ LinkAccountSubtypes['HSA'] = 'hsa'; -+ LinkAccountSubtypes['MONEY_MARKET'] = 'money market'; -+ LinkAccountSubtypes['PREPAID'] = 'prepaid'; -+ LinkAccountSubtypes['SAVINGS'] = 'savings'; -+ LinkAccountSubtypes['FOUR_0_1_A'] = '401a'; -+ LinkAccountSubtypes['FOUR_0_1_K'] = '401k'; -+ LinkAccountSubtypes['FOUR_0_3_B'] = '403B'; -+ LinkAccountSubtypes['FOUR_5_7_B'] = '457b'; -+ LinkAccountSubtypes['FIVE_2_9'] = '529'; -+ LinkAccountSubtypes['BROKERAGE'] = 'brokerage'; -+ LinkAccountSubtypes['CASH_ISA'] = 'cash isa'; -+ LinkAccountSubtypes['EDUCATION_SAVINGS_ACCOUNT'] = -+ 'education savings account'; -+ LinkAccountSubtypes['FIXED_ANNUNITY'] = 'fixed annuity'; -+ LinkAccountSubtypes['GIC'] = 'gic'; -+ LinkAccountSubtypes['HEALTH_REIMBURSEMENT_ARRANGEMENT'] = -+ 'health reimbursement arrangement'; -+ LinkAccountSubtypes['IRA'] = 'ira'; -+ LinkAccountSubtypes['ISA'] = 'isa'; -+ LinkAccountSubtypes['KEOGH'] = 'keogh'; -+ LinkAccountSubtypes['LIF'] = 'lif'; -+ LinkAccountSubtypes['LIRA'] = 'lira'; -+ LinkAccountSubtypes['LRIF'] = 'lrif'; -+ LinkAccountSubtypes['LRSP'] = 'lrsp'; -+ LinkAccountSubtypes['MUTUAL_FUND'] = 'mutual fund'; -+ LinkAccountSubtypes['NON_TAXABLE_BROKERAGE_ACCOUNT'] = -+ 'non-taxable brokerage account'; -+ LinkAccountSubtypes['PENSION'] = 'pension'; -+ LinkAccountSubtypes['PLAN'] = 'plan'; -+ LinkAccountSubtypes['PRIF'] = 'prif'; -+ LinkAccountSubtypes['PROFIT_SHARING_PLAN'] = 'profit sharing plan'; -+ LinkAccountSubtypes['RDSP'] = 'rdsp'; -+ LinkAccountSubtypes['RESP'] = 'resp'; -+ LinkAccountSubtypes['RETIREMENT'] = 'retirement'; -+ LinkAccountSubtypes['RLIF'] = 'rlif'; -+ LinkAccountSubtypes['ROTH_401K'] = 'roth 401k'; -+ LinkAccountSubtypes['ROTH'] = 'roth'; -+ LinkAccountSubtypes['RRIF'] = 'rrif'; -+ LinkAccountSubtypes['RRSP'] = 'rrsp'; -+ LinkAccountSubtypes['SARSEP'] = 'sarsep'; -+ LinkAccountSubtypes['SEP_IRA'] = 'sep ira'; -+ LinkAccountSubtypes['SIMPLE_IRA'] = 'simple ira'; -+ LinkAccountSubtypes['SIPP'] = 'sipp'; -+ LinkAccountSubtypes['STOCK_PLAN'] = 'stock plan'; -+ LinkAccountSubtypes['TFSA'] = 'tfsa'; -+ LinkAccountSubtypes['THRIFT_SAVINGS_PLAN'] = 'thrift savings plan'; -+ LinkAccountSubtypes['TRUST'] = 'trust'; -+ LinkAccountSubtypes['UGMA'] = 'ugma'; -+ LinkAccountSubtypes['UTMA'] = 'utma'; -+ LinkAccountSubtypes['VARIABLE_ANNUITY'] = 'variable annuity'; - })(LinkAccountSubtypes || (LinkAccountSubtypes = {})); - export class LinkAccountSubtypeCredit { -- constructor(type, subtype) { -- this.type = type; -- this.subtype = subtype; -- } -+ constructor(type, subtype) { -+ this.type = type; -+ this.subtype = subtype; -+ } - } --LinkAccountSubtypeCredit.ALL = new LinkAccountSubtypeCredit(LinkAccountType.CREDIT, LinkAccountSubtypes.ALL); --LinkAccountSubtypeCredit.CREDIT_CARD = new LinkAccountSubtypeCredit(LinkAccountType.CREDIT, LinkAccountSubtypes.CREDIT_CARD); --LinkAccountSubtypeCredit.PAYPAL = new LinkAccountSubtypeCredit(LinkAccountType.CREDIT, LinkAccountSubtypes.PAYPAL); -+LinkAccountSubtypeCredit.ALL = new LinkAccountSubtypeCredit( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.ALL, -+); -+LinkAccountSubtypeCredit.CREDIT_CARD = new LinkAccountSubtypeCredit( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.CREDIT_CARD, -+); -+LinkAccountSubtypeCredit.PAYPAL = new LinkAccountSubtypeCredit( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.PAYPAL, -+); - export class LinkAccountSubtypeDepository { -- constructor(type, subtype) { -- this.type = type; -- this.subtype = subtype; -- } -+ constructor(type, subtype) { -+ this.type = type; -+ this.subtype = subtype; -+ } - } --LinkAccountSubtypeDepository.ALL = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.ALL); --LinkAccountSubtypeDepository.CASH_MANAGEMENT = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.CASH_MANAGEMENT); --LinkAccountSubtypeDepository.CD = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.CD); --LinkAccountSubtypeDepository.CHECKING = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.CHECKING); --LinkAccountSubtypeDepository.EBT = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.EBT); --LinkAccountSubtypeDepository.HSA = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.HSA); --LinkAccountSubtypeDepository.MONEY_MARKET = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.MONEY_MARKET); --LinkAccountSubtypeDepository.PAYPAL = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.PAYPAL); --LinkAccountSubtypeDepository.PREPAID = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.PREPAID); --LinkAccountSubtypeDepository.SAVINGS = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.SAVINGS); -+LinkAccountSubtypeDepository.ALL = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.ALL, -+); -+LinkAccountSubtypeDepository.CASH_MANAGEMENT = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.CASH_MANAGEMENT, -+); -+LinkAccountSubtypeDepository.CD = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.CD, -+); -+LinkAccountSubtypeDepository.CHECKING = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.CHECKING, -+); -+LinkAccountSubtypeDepository.EBT = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.EBT, -+); -+LinkAccountSubtypeDepository.HSA = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.HSA, -+); -+LinkAccountSubtypeDepository.MONEY_MARKET = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.MONEY_MARKET, -+); -+LinkAccountSubtypeDepository.PAYPAL = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.PAYPAL, -+); -+LinkAccountSubtypeDepository.PREPAID = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.PREPAID, -+); -+LinkAccountSubtypeDepository.SAVINGS = new LinkAccountSubtypeDepository( -+ LinkAccountType.DEPOSITORY, -+ LinkAccountSubtypes.SAVINGS, -+); - export class LinkAccountSubtypeInvestment { -- constructor(type, subtype) { -- this.type = type; -- this.subtype = subtype; -- } -+ constructor(type, subtype) { -+ this.type = type; -+ this.subtype = subtype; -+ } - } --LinkAccountSubtypeInvestment.ALL = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.ALL); --LinkAccountSubtypeInvestment.BROKERAGE = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.BROKERAGE); --LinkAccountSubtypeInvestment.CASH_ISA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.CASH_ISA); --LinkAccountSubtypeInvestment.EDUCATION_SAVINGS_ACCOUNT = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.EDUCATION_SAVINGS_ACCOUNT); --LinkAccountSubtypeInvestment.FIXED_ANNUNITY = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FIXED_ANNUNITY); --LinkAccountSubtypeInvestment.GIC = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.GIC); --LinkAccountSubtypeInvestment.HEALTH_REIMBURSEMENT_ARRANGEMENT = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.HEALTH_REIMBURSEMENT_ARRANGEMENT); --LinkAccountSubtypeInvestment.HSA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.HSA); --LinkAccountSubtypeInvestment.INVESTMENT_401A = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FOUR_0_1_A); --LinkAccountSubtypeInvestment.INVESTMENT_401K = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FOUR_0_1_K); --LinkAccountSubtypeInvestment.INVESTMENT_403B = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FOUR_0_3_B); --LinkAccountSubtypeInvestment.INVESTMENT_457B = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FOUR_5_7_B); --LinkAccountSubtypeInvestment.INVESTMENT_529 = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FIVE_2_9); --LinkAccountSubtypeInvestment.IRA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.IRA); --LinkAccountSubtypeInvestment.ISA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.ISA); --LinkAccountSubtypeInvestment.KEOGH = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.KEOGH); --LinkAccountSubtypeInvestment.LIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.LIF); --LinkAccountSubtypeInvestment.LIRA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.LIRA); --LinkAccountSubtypeInvestment.LRIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.LRIF); --LinkAccountSubtypeInvestment.LRSP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.LRSP); --LinkAccountSubtypeInvestment.MUTUAL_FUND = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.MUTUAL_FUND); --LinkAccountSubtypeInvestment.NON_TAXABLE_BROKERAGE_ACCOUNT = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.NON_TAXABLE_BROKERAGE_ACCOUNT); --LinkAccountSubtypeInvestment.PENSION = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.PENSION); --LinkAccountSubtypeInvestment.PLAN = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.PLAN); --LinkAccountSubtypeInvestment.PRIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.PRIF); --LinkAccountSubtypeInvestment.PROFIT_SHARING_PLAN = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.PROFIT_SHARING_PLAN); --LinkAccountSubtypeInvestment.RDSP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RDSP); --LinkAccountSubtypeInvestment.RESP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RESP); --LinkAccountSubtypeInvestment.RETIREMENT = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RETIREMENT); --LinkAccountSubtypeInvestment.RLIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RLIF); --LinkAccountSubtypeInvestment.ROTH = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.ROTH); --LinkAccountSubtypeInvestment.ROTH_401K = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.ROTH_401K); --LinkAccountSubtypeInvestment.RRIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RRIF); --LinkAccountSubtypeInvestment.RRSP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RRSP); --LinkAccountSubtypeInvestment.SARSEP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.SARSEP); --LinkAccountSubtypeInvestment.SEP_IRA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.SEP_IRA); --LinkAccountSubtypeInvestment.SIMPLE_IRA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.SIMPLE_IRA); --LinkAccountSubtypeInvestment.SIIP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.SIPP); --LinkAccountSubtypeInvestment.STOCK_PLAN = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.STOCK_PLAN); --LinkAccountSubtypeInvestment.TFSA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.TFSA); --LinkAccountSubtypeInvestment.THRIFT_SAVINGS_PLAN = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.THRIFT_SAVINGS_PLAN); --LinkAccountSubtypeInvestment.TRUST = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.TRUST); --LinkAccountSubtypeInvestment.UGMA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.UGMA); --LinkAccountSubtypeInvestment.UTMA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.UTMA); --LinkAccountSubtypeInvestment.VARIABLE_ANNUITY = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.VARIABLE_ANNUITY); -+LinkAccountSubtypeInvestment.ALL = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.ALL, -+); -+LinkAccountSubtypeInvestment.BROKERAGE = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.BROKERAGE, -+); -+LinkAccountSubtypeInvestment.CASH_ISA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.CASH_ISA, -+); -+LinkAccountSubtypeInvestment.EDUCATION_SAVINGS_ACCOUNT = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.EDUCATION_SAVINGS_ACCOUNT, -+); -+LinkAccountSubtypeInvestment.FIXED_ANNUNITY = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.FIXED_ANNUNITY, -+); -+LinkAccountSubtypeInvestment.GIC = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.GIC, -+); -+LinkAccountSubtypeInvestment.HEALTH_REIMBURSEMENT_ARRANGEMENT = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.HEALTH_REIMBURSEMENT_ARRANGEMENT, -+); -+LinkAccountSubtypeInvestment.HSA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.HSA, -+); -+LinkAccountSubtypeInvestment.INVESTMENT_401A = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.FOUR_0_1_A, -+); -+LinkAccountSubtypeInvestment.INVESTMENT_401K = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.FOUR_0_1_K, -+); -+LinkAccountSubtypeInvestment.INVESTMENT_403B = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.FOUR_0_3_B, -+); -+LinkAccountSubtypeInvestment.INVESTMENT_457B = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.FOUR_5_7_B, -+); -+LinkAccountSubtypeInvestment.INVESTMENT_529 = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.FIVE_2_9, -+); -+LinkAccountSubtypeInvestment.IRA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.IRA, -+); -+LinkAccountSubtypeInvestment.ISA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.ISA, -+); -+LinkAccountSubtypeInvestment.KEOGH = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.KEOGH, -+); -+LinkAccountSubtypeInvestment.LIF = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.LIF, -+); -+LinkAccountSubtypeInvestment.LIRA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.LIRA, -+); -+LinkAccountSubtypeInvestment.LRIF = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.LRIF, -+); -+LinkAccountSubtypeInvestment.LRSP = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.LRSP, -+); -+LinkAccountSubtypeInvestment.MUTUAL_FUND = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.MUTUAL_FUND, -+); -+LinkAccountSubtypeInvestment.NON_TAXABLE_BROKERAGE_ACCOUNT = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.NON_TAXABLE_BROKERAGE_ACCOUNT, -+); -+LinkAccountSubtypeInvestment.PENSION = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.PENSION, -+); -+LinkAccountSubtypeInvestment.PLAN = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.PLAN, -+); -+LinkAccountSubtypeInvestment.PRIF = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.PRIF, -+); -+LinkAccountSubtypeInvestment.PROFIT_SHARING_PLAN = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.PROFIT_SHARING_PLAN, -+); -+LinkAccountSubtypeInvestment.RDSP = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.RDSP, -+); -+LinkAccountSubtypeInvestment.RESP = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.RESP, -+); -+LinkAccountSubtypeInvestment.RETIREMENT = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.RETIREMENT, -+); -+LinkAccountSubtypeInvestment.RLIF = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.RLIF, -+); -+LinkAccountSubtypeInvestment.ROTH = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.ROTH, -+); -+LinkAccountSubtypeInvestment.ROTH_401K = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.ROTH_401K, -+); -+LinkAccountSubtypeInvestment.RRIF = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.RRIF, -+); -+LinkAccountSubtypeInvestment.RRSP = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.RRSP, -+); -+LinkAccountSubtypeInvestment.SARSEP = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.SARSEP, -+); -+LinkAccountSubtypeInvestment.SEP_IRA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.SEP_IRA, -+); -+LinkAccountSubtypeInvestment.SIMPLE_IRA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.SIMPLE_IRA, -+); -+LinkAccountSubtypeInvestment.SIIP = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.SIPP, -+); -+LinkAccountSubtypeInvestment.STOCK_PLAN = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.STOCK_PLAN, -+); -+LinkAccountSubtypeInvestment.TFSA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.TFSA, -+); -+LinkAccountSubtypeInvestment.THRIFT_SAVINGS_PLAN = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.THRIFT_SAVINGS_PLAN, -+); -+LinkAccountSubtypeInvestment.TRUST = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.TRUST, -+); -+LinkAccountSubtypeInvestment.UGMA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.UGMA, -+); -+LinkAccountSubtypeInvestment.UTMA = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.UTMA, -+); -+LinkAccountSubtypeInvestment.VARIABLE_ANNUITY = new LinkAccountSubtypeInvestment( -+ LinkAccountType.INVESTMENT, -+ LinkAccountSubtypes.VARIABLE_ANNUITY, -+); - export class LinkAccountSubtypeLoan { -- constructor(type, subtype) { -- this.type = type; -- this.subtype = subtype; -- } -+ constructor(type, subtype) { -+ this.type = type; -+ this.subtype = subtype; -+ } - } --LinkAccountSubtypeLoan.ALL = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.ALL); --LinkAccountSubtypeLoan.AUTO = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.AUTO); --LinkAccountSubtypeLoan.BUSINESS = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.BUSINESS); --LinkAccountSubtypeLoan.COMMERCIAL = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.COMMERCIAL); --LinkAccountSubtypeLoan.CONSTRUCTION = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.CONSTRUCTION); --LinkAccountSubtypeLoan.CONSUMER = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.CONSUMER); --LinkAccountSubtypeLoan.HOME_EQUITY = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.HOME_EQUITY); --LinkAccountSubtypeLoan.LINE_OF_CREDIT = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.LINE_OF_CREDIT); --LinkAccountSubtypeLoan.LOAN = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.LOAN); --LinkAccountSubtypeLoan.MORTGAGE = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.MORTGAGE); --LinkAccountSubtypeLoan.OVERDRAFT = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.OVERDRAFT); --LinkAccountSubtypeLoan.STUDENT = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.STUDENT); -+LinkAccountSubtypeLoan.ALL = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.ALL, -+); -+LinkAccountSubtypeLoan.AUTO = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.AUTO, -+); -+LinkAccountSubtypeLoan.BUSINESS = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.BUSINESS, -+); -+LinkAccountSubtypeLoan.COMMERCIAL = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.COMMERCIAL, -+); -+LinkAccountSubtypeLoan.CONSTRUCTION = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.CONSTRUCTION, -+); -+LinkAccountSubtypeLoan.CONSUMER = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.CONSUMER, -+); -+LinkAccountSubtypeLoan.HOME_EQUITY = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.HOME_EQUITY, -+); -+LinkAccountSubtypeLoan.LINE_OF_CREDIT = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.LINE_OF_CREDIT, -+); -+LinkAccountSubtypeLoan.LOAN = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.LOAN, -+); -+LinkAccountSubtypeLoan.MORTGAGE = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.MORTGAGE, -+); -+LinkAccountSubtypeLoan.OVERDRAFT = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.OVERDRAFT, -+); -+LinkAccountSubtypeLoan.STUDENT = new LinkAccountSubtypeLoan( -+ LinkAccountType.CREDIT, -+ LinkAccountSubtypes.STUDENT, -+); - export class LinkAccountSubtypeUnknown { -- constructor(type, subtype) { -- this.type = type; -- this.subtype = subtype; -- } -+ constructor(type, subtype) { -+ this.type = type; -+ this.subtype = subtype; -+ } - } - export var LinkAccountVerificationStatus; --(function (LinkAccountVerificationStatus) { -- LinkAccountVerificationStatus["PENDING_AUTOMATIC_VERIFICATION"] = "pending_automatic_verification"; -- LinkAccountVerificationStatus["PENDING_MANUAL_VERIFICATION"] = "pending_manual_verification"; -- LinkAccountVerificationStatus["MANUALLY_VERIFIED"] = "manually_verified"; -+(function(LinkAccountVerificationStatus) { -+ LinkAccountVerificationStatus['PENDING_AUTOMATIC_VERIFICATION'] = -+ 'pending_automatic_verification'; -+ LinkAccountVerificationStatus['PENDING_MANUAL_VERIFICATION'] = -+ 'pending_manual_verification'; -+ LinkAccountVerificationStatus['MANUALLY_VERIFIED'] = 'manually_verified'; - })(LinkAccountVerificationStatus || (LinkAccountVerificationStatus = {})); - export var LinkExitMetadataStatus; --(function (LinkExitMetadataStatus) { -- LinkExitMetadataStatus["CONNECTED"] = "connected"; -- LinkExitMetadataStatus["CHOOSE_DEVICE"] = "choose_device"; -- LinkExitMetadataStatus["REQUIRES_ACCOUNT_SELECTION"] = "requires_account_selection"; -- LinkExitMetadataStatus["REQUIRES_CODE"] = "requires_code"; -- LinkExitMetadataStatus["REQUIRES_CREDENTIALS"] = "requires_credentials"; -- LinkExitMetadataStatus["REQUIRES_EXTERNAL_ACTION"] = "requires_external_action"; -- LinkExitMetadataStatus["REQUIRES_OAUTH"] = "requires_oauth"; -- LinkExitMetadataStatus["REQUIRES_QUESTIONS"] = "requires_questions"; -- LinkExitMetadataStatus["REQUIRES_RECAPTCHA"] = "requires_recaptcha"; -- LinkExitMetadataStatus["REQUIRES_SELECTIONS"] = "requires_selections"; -- LinkExitMetadataStatus["REQUIRES_DEPOSIT_SWITCH_ALLOCATION_CONFIGURATION"] = "requires_deposit_switch_allocation_configuration"; -- LinkExitMetadataStatus["REQUIRES_DEPOSIT_SWITCH_ALLOCATION_SELECTION"] = "requires_deposit_switch_allocation_selection"; -+(function(LinkExitMetadataStatus) { -+ LinkExitMetadataStatus['CONNECTED'] = 'connected'; -+ LinkExitMetadataStatus['CHOOSE_DEVICE'] = 'choose_device'; -+ LinkExitMetadataStatus['REQUIRES_ACCOUNT_SELECTION'] = -+ 'requires_account_selection'; -+ LinkExitMetadataStatus['REQUIRES_CODE'] = 'requires_code'; -+ LinkExitMetadataStatus['REQUIRES_CREDENTIALS'] = 'requires_credentials'; -+ LinkExitMetadataStatus['REQUIRES_EXTERNAL_ACTION'] = -+ 'requires_external_action'; -+ LinkExitMetadataStatus['REQUIRES_OAUTH'] = 'requires_oauth'; -+ LinkExitMetadataStatus['REQUIRES_QUESTIONS'] = 'requires_questions'; -+ LinkExitMetadataStatus['REQUIRES_RECAPTCHA'] = 'requires_recaptcha'; -+ LinkExitMetadataStatus['REQUIRES_SELECTIONS'] = 'requires_selections'; -+ LinkExitMetadataStatus['REQUIRES_DEPOSIT_SWITCH_ALLOCATION_CONFIGURATION'] = -+ 'requires_deposit_switch_allocation_configuration'; -+ LinkExitMetadataStatus['REQUIRES_DEPOSIT_SWITCH_ALLOCATION_SELECTION'] = -+ 'requires_deposit_switch_allocation_selection'; - })(LinkExitMetadataStatus || (LinkExitMetadataStatus = {})); - export var LinkErrorCode; --(function (LinkErrorCode) { -- // ITEM_ERROR -- LinkErrorCode["INVALID_CREDENTIALS"] = "INVALID_CREDENTIALS"; -- LinkErrorCode["INVALID_MFA"] = "INVALID_MFA"; -- LinkErrorCode["ITEM_LOGIN_REQUIRED"] = "ITEM_LOGIN_REQUIRED"; -- LinkErrorCode["INSUFFICIENT_CREDENTIALS"] = "INSUFFICIENT_CREDENTIALS"; -- LinkErrorCode["ITEM_LOCKED"] = "ITEM_LOCKED"; -- LinkErrorCode["USER_SETUP_REQUIRED"] = "USER_SETUP_REQUIRED"; -- LinkErrorCode["MFA_NOT_SUPPORTED"] = "MFA_NOT_SUPPORTED"; -- LinkErrorCode["INVALID_SEND_METHOD"] = "INVALID_SEND_METHOD"; -- LinkErrorCode["NO_ACCOUNTS"] = "NO_ACCOUNTS"; -- LinkErrorCode["ITEM_NOT_SUPPORTED"] = "ITEM_NOT_SUPPORTED"; -- LinkErrorCode["TOO_MANY_VERIFICATION_ATTEMPTS"] = "TOO_MANY_VERIFICATION_ATTEMPTS"; -- LinkErrorCode["INVALD_UPDATED_USERNAME"] = "INVALD_UPDATED_USERNAME"; -- LinkErrorCode["INVALID_UPDATED_USERNAME"] = "INVALID_UPDATED_USERNAME"; -- LinkErrorCode["ITEM_NO_ERROR"] = "ITEM_NO_ERROR"; -- LinkErrorCode["item_no_error"] = "item-no-error"; -- LinkErrorCode["NO_AUTH_ACCOUNTS"] = "NO_AUTH_ACCOUNTS"; -- LinkErrorCode["NO_INVESTMENT_ACCOUNTS"] = "NO_INVESTMENT_ACCOUNTS"; -- LinkErrorCode["NO_INVESTMENT_AUTH_ACCOUNTS"] = "NO_INVESTMENT_AUTH_ACCOUNTS"; -- LinkErrorCode["NO_LIABILITY_ACCOUNTS"] = "NO_LIABILITY_ACCOUNTS"; -- LinkErrorCode["PRODUCTS_NOT_SUPPORTED"] = "PRODUCTS_NOT_SUPPORTED"; -- LinkErrorCode["ITEM_NOT_FOUND"] = "ITEM_NOT_FOUND"; -- LinkErrorCode["ITEM_PRODUCT_NOT_READY"] = "ITEM_PRODUCT_NOT_READY"; -- // INSTITUTION_ERROR -- LinkErrorCode["INSTITUTION_DOWN"] = "INSTITUTION_DOWN"; -- LinkErrorCode["INSTITUTION_NOT_RESPONDING"] = "INSTITUTION_NOT_RESPONDING"; -- LinkErrorCode["INSTITUTION_NOT_AVAILABLE"] = "INSTITUTION_NOT_AVAILABLE"; -- LinkErrorCode["INSTITUTION_NO_LONGER_SUPPORTED"] = "INSTITUTION_NO_LONGER_SUPPORTED"; -- // API_ERROR -- LinkErrorCode["INTERNAL_SERVER_ERROR"] = "INTERNAL_SERVER_ERROR"; -- LinkErrorCode["PLANNED_MAINTENANCE"] = "PLANNED_MAINTENANCE"; -- // ASSET_REPORT_ERROR -- LinkErrorCode["PRODUCT_NOT_ENABLED"] = "PRODUCT_NOT_ENABLED"; -- LinkErrorCode["DATA_UNAVAILABLE"] = "DATA_UNAVAILABLE"; -- LinkErrorCode["ASSET_PRODUCT_NOT_READY"] = "ASSET_PRODUCT_NOT_READY"; -- LinkErrorCode["ASSET_REPORT_GENERATION_FAILED"] = "ASSET_REPORT_GENERATION_FAILED"; -- LinkErrorCode["INVALID_PARENT"] = "INVALID_PARENT"; -- LinkErrorCode["INSIGHTS_NOT_ENABLED"] = "INSIGHTS_NOT_ENABLED"; -- LinkErrorCode["INSIGHTS_PREVIOUSLY_NOT_ENABLED"] = "INSIGHTS_PREVIOUSLY_NOT_ENABLED"; -- // BANK_TRANSFER_ERROR -- LinkErrorCode["BANK_TRANSFER_LIMIT_EXCEEDED"] = "BANK_TRANSFER_LIMIT_EXCEEDED"; -- LinkErrorCode["BANK_TRANSFER_MISSING_ORIGINATION_ACCOUNT"] = "BANK_TRANSFER_MISSING_ORIGINATION_ACCOUNT"; -- LinkErrorCode["BANK_TRANSFER_INVALID_ORIGINATION_ACCOUNT"] = "BANK_TRANSFER_INVALID_ORIGINATION_ACCOUNT"; -- LinkErrorCode["BANK_TRANSFER_ACCOUNT_BLOCKED"] = "BANK_TRANSFER_ACCOUNT_BLOCKED"; -- LinkErrorCode["BANK_TRANSFER_INSUFFICIENT_FUNDS"] = "BANK_TRANSFER_INSUFFICIENT_FUNDS"; -- LinkErrorCode["BANK_TRANSFER_NOT_CANCELLABLE"] = "BANK_TRANSFER_NOT_CANCELLABLE"; -- LinkErrorCode["BANK_TRANSFER_UNSUPPORTED_ACCOUNT_TYPE"] = "BANK_TRANSFER_UNSUPPORTED_ACCOUNT_TYPE"; -- LinkErrorCode["BANK_TRANSFER_UNSUPPORTED_ENVIRONMENT"] = "BANK_TRANSFER_UNSUPPORTED_ENVIRONMENT"; -- // SANDBOX_ERROR -- LinkErrorCode["SANDBOX_PRODUCT_NOT_ENABLED"] = "SANDBOX_PRODUCT_NOT_ENABLED"; -- LinkErrorCode["SANDBOX_WEBHOOK_INVALID"] = "SANDBOX_WEBHOOK_INVALID"; -- LinkErrorCode["SANDBOX_BANK_TRANSFER_EVENT_TRANSITION_INVALID"] = "SANDBOX_BANK_TRANSFER_EVENT_TRANSITION_INVALID"; -- // INVALID_REQUEST -- LinkErrorCode["MISSING_FIELDS"] = "MISSING_FIELDS"; -- LinkErrorCode["UNKNOWN_FIELDS"] = "UNKNOWN_FIELDS"; -- LinkErrorCode["INVALID_FIELD"] = "INVALID_FIELD"; -- LinkErrorCode["INCOMPATIBLE_API_VERSION"] = "INCOMPATIBLE_API_VERSION"; -- LinkErrorCode["INVALID_BODY"] = "INVALID_BODY"; -- LinkErrorCode["INVALID_HEADERS"] = "INVALID_HEADERS"; -- LinkErrorCode["NOT_FOUND"] = "NOT_FOUND"; -- LinkErrorCode["NO_LONGER_AVAILABLE"] = "NO_LONGER_AVAILABLE"; -- LinkErrorCode["SANDBOX_ONLY"] = "SANDBOX_ONLY"; -- LinkErrorCode["INVALID_ACCOUNT_NUMBER"] = "INVALID_ACCOUNT_NUMBER"; -- // INVALID_INPUT -- // From above ITEM_LOGIN_REQUIRED = "INVALID_CREDENTIALS", -- LinkErrorCode["INCORRECT_DEPOSIT_AMOUNTS"] = "INCORRECT_DEPOSIT_AMOUNTS"; -- LinkErrorCode["UNAUTHORIZED_ENVIRONMENT"] = "UNAUTHORIZED_ENVIRONMENT"; -- LinkErrorCode["INVALID_PRODUCT"] = "INVALID_PRODUCT"; -- LinkErrorCode["UNAUTHORIZED_ROUTE_ACCESS"] = "UNAUTHORIZED_ROUTE_ACCESS"; -- LinkErrorCode["DIRECT_INTEGRATION_NOT_ENABLED"] = "DIRECT_INTEGRATION_NOT_ENABLED"; -- LinkErrorCode["INVALID_API_KEYS"] = "INVALID_API_KEYS"; -- LinkErrorCode["INVALID_ACCESS_TOKEN"] = "INVALID_ACCESS_TOKEN"; -- LinkErrorCode["INVALID_PUBLIC_TOKEN"] = "INVALID_PUBLIC_TOKEN"; -- LinkErrorCode["INVALID_LINK_TOKEN"] = "INVALID_LINK_TOKEN"; -- LinkErrorCode["INVALID_PROCESSOR_TOKEN"] = "INVALID_PROCESSOR_TOKEN"; -- LinkErrorCode["INVALID_AUDIT_COPY_TOKEN"] = "INVALID_AUDIT_COPY_TOKEN"; -- LinkErrorCode["INVALID_ACCOUNT_ID"] = "INVALID_ACCOUNT_ID"; -- LinkErrorCode["MICRODEPOSITS_ALREADY_VERIFIED"] = "MICRODEPOSITS_ALREADY_VERIFIED"; -- // INVALID_RESULT -- LinkErrorCode["PLAID_DIRECT_ITEM_IMPORT_RETURNED_INVALID_MFA"] = "PLAID_DIRECT_ITEM_IMPORT_RETURNED_INVALID_MFA"; -- // RATE_LIMIT_EXCEEDED -- LinkErrorCode["ACCOUNTS_LIMIT"] = "ACCOUNTS_LIMIT"; -- LinkErrorCode["ADDITION_LIMIT"] = "ADDITION_LIMIT"; -- LinkErrorCode["AUTH_LIMIT"] = "AUTH_LIMIT"; -- LinkErrorCode["BALANCE_LIMIT"] = "BALANCE_LIMIT"; -- LinkErrorCode["IDENTITY_LIMIT"] = "IDENTITY_LIMIT"; -- LinkErrorCode["ITEM_GET_LIMIT"] = "ITEM_GET_LIMIT"; -- LinkErrorCode["RATE_LIMIT"] = "RATE_LIMIT"; -- LinkErrorCode["TRANSACTIONS_LIMIT"] = "TRANSACTIONS_LIMIT"; -- // RECAPTCHA_ERROR -- LinkErrorCode["RECAPTCHA_REQUIRED"] = "RECAPTCHA_REQUIRED"; -- LinkErrorCode["RECAPTCHA_BAD"] = "RECAPTCHA_BAD"; -- // OAUTH_ERROR -- LinkErrorCode["INCORRECT_OAUTH_NONCE"] = "INCORRECT_OAUTH_NONCE"; -- LinkErrorCode["OAUTH_STATE_ID_ALREADY_PROCESSED"] = "OAUTH_STATE_ID_ALREADY_PROCESSED"; -+(function(LinkErrorCode) { -+ // ITEM_ERROR -+ LinkErrorCode['INVALID_CREDENTIALS'] = 'INVALID_CREDENTIALS'; -+ LinkErrorCode['INVALID_MFA'] = 'INVALID_MFA'; -+ LinkErrorCode['ITEM_LOGIN_REQUIRED'] = 'ITEM_LOGIN_REQUIRED'; -+ LinkErrorCode['INSUFFICIENT_CREDENTIALS'] = 'INSUFFICIENT_CREDENTIALS'; -+ LinkErrorCode['ITEM_LOCKED'] = 'ITEM_LOCKED'; -+ LinkErrorCode['USER_SETUP_REQUIRED'] = 'USER_SETUP_REQUIRED'; -+ LinkErrorCode['MFA_NOT_SUPPORTED'] = 'MFA_NOT_SUPPORTED'; -+ LinkErrorCode['INVALID_SEND_METHOD'] = 'INVALID_SEND_METHOD'; -+ LinkErrorCode['NO_ACCOUNTS'] = 'NO_ACCOUNTS'; -+ LinkErrorCode['ITEM_NOT_SUPPORTED'] = 'ITEM_NOT_SUPPORTED'; -+ LinkErrorCode['TOO_MANY_VERIFICATION_ATTEMPTS'] = -+ 'TOO_MANY_VERIFICATION_ATTEMPTS'; -+ LinkErrorCode['INVALD_UPDATED_USERNAME'] = 'INVALD_UPDATED_USERNAME'; -+ LinkErrorCode['INVALID_UPDATED_USERNAME'] = 'INVALID_UPDATED_USERNAME'; -+ LinkErrorCode['ITEM_NO_ERROR'] = 'ITEM_NO_ERROR'; -+ LinkErrorCode['item_no_error'] = 'item-no-error'; -+ LinkErrorCode['NO_AUTH_ACCOUNTS'] = 'NO_AUTH_ACCOUNTS'; -+ LinkErrorCode['NO_INVESTMENT_ACCOUNTS'] = 'NO_INVESTMENT_ACCOUNTS'; -+ LinkErrorCode['NO_INVESTMENT_AUTH_ACCOUNTS'] = 'NO_INVESTMENT_AUTH_ACCOUNTS'; -+ LinkErrorCode['NO_LIABILITY_ACCOUNTS'] = 'NO_LIABILITY_ACCOUNTS'; -+ LinkErrorCode['PRODUCTS_NOT_SUPPORTED'] = 'PRODUCTS_NOT_SUPPORTED'; -+ LinkErrorCode['ITEM_NOT_FOUND'] = 'ITEM_NOT_FOUND'; -+ LinkErrorCode['ITEM_PRODUCT_NOT_READY'] = 'ITEM_PRODUCT_NOT_READY'; -+ // INSTITUTION_ERROR -+ LinkErrorCode['INSTITUTION_DOWN'] = 'INSTITUTION_DOWN'; -+ LinkErrorCode['INSTITUTION_NOT_RESPONDING'] = 'INSTITUTION_NOT_RESPONDING'; -+ LinkErrorCode['INSTITUTION_NOT_AVAILABLE'] = 'INSTITUTION_NOT_AVAILABLE'; -+ LinkErrorCode['INSTITUTION_NO_LONGER_SUPPORTED'] = -+ 'INSTITUTION_NO_LONGER_SUPPORTED'; -+ // API_ERROR -+ LinkErrorCode['INTERNAL_SERVER_ERROR'] = 'INTERNAL_SERVER_ERROR'; -+ LinkErrorCode['PLANNED_MAINTENANCE'] = 'PLANNED_MAINTENANCE'; -+ // ASSET_REPORT_ERROR -+ LinkErrorCode['PRODUCT_NOT_ENABLED'] = 'PRODUCT_NOT_ENABLED'; -+ LinkErrorCode['DATA_UNAVAILABLE'] = 'DATA_UNAVAILABLE'; -+ LinkErrorCode['ASSET_PRODUCT_NOT_READY'] = 'ASSET_PRODUCT_NOT_READY'; -+ LinkErrorCode['ASSET_REPORT_GENERATION_FAILED'] = -+ 'ASSET_REPORT_GENERATION_FAILED'; -+ LinkErrorCode['INVALID_PARENT'] = 'INVALID_PARENT'; -+ LinkErrorCode['INSIGHTS_NOT_ENABLED'] = 'INSIGHTS_NOT_ENABLED'; -+ LinkErrorCode['INSIGHTS_PREVIOUSLY_NOT_ENABLED'] = -+ 'INSIGHTS_PREVIOUSLY_NOT_ENABLED'; -+ // BANK_TRANSFER_ERROR -+ LinkErrorCode['BANK_TRANSFER_LIMIT_EXCEEDED'] = -+ 'BANK_TRANSFER_LIMIT_EXCEEDED'; -+ LinkErrorCode['BANK_TRANSFER_MISSING_ORIGINATION_ACCOUNT'] = -+ 'BANK_TRANSFER_MISSING_ORIGINATION_ACCOUNT'; -+ LinkErrorCode['BANK_TRANSFER_INVALID_ORIGINATION_ACCOUNT'] = -+ 'BANK_TRANSFER_INVALID_ORIGINATION_ACCOUNT'; -+ LinkErrorCode['BANK_TRANSFER_ACCOUNT_BLOCKED'] = -+ 'BANK_TRANSFER_ACCOUNT_BLOCKED'; -+ LinkErrorCode['BANK_TRANSFER_INSUFFICIENT_FUNDS'] = -+ 'BANK_TRANSFER_INSUFFICIENT_FUNDS'; -+ LinkErrorCode['BANK_TRANSFER_NOT_CANCELLABLE'] = -+ 'BANK_TRANSFER_NOT_CANCELLABLE'; -+ LinkErrorCode['BANK_TRANSFER_UNSUPPORTED_ACCOUNT_TYPE'] = -+ 'BANK_TRANSFER_UNSUPPORTED_ACCOUNT_TYPE'; -+ LinkErrorCode['BANK_TRANSFER_UNSUPPORTED_ENVIRONMENT'] = -+ 'BANK_TRANSFER_UNSUPPORTED_ENVIRONMENT'; -+ // SANDBOX_ERROR -+ LinkErrorCode['SANDBOX_PRODUCT_NOT_ENABLED'] = 'SANDBOX_PRODUCT_NOT_ENABLED'; -+ LinkErrorCode['SANDBOX_WEBHOOK_INVALID'] = 'SANDBOX_WEBHOOK_INVALID'; -+ LinkErrorCode['SANDBOX_BANK_TRANSFER_EVENT_TRANSITION_INVALID'] = -+ 'SANDBOX_BANK_TRANSFER_EVENT_TRANSITION_INVALID'; -+ // INVALID_REQUEST -+ LinkErrorCode['MISSING_FIELDS'] = 'MISSING_FIELDS'; -+ LinkErrorCode['UNKNOWN_FIELDS'] = 'UNKNOWN_FIELDS'; -+ LinkErrorCode['INVALID_FIELD'] = 'INVALID_FIELD'; -+ LinkErrorCode['INCOMPATIBLE_API_VERSION'] = 'INCOMPATIBLE_API_VERSION'; -+ LinkErrorCode['INVALID_BODY'] = 'INVALID_BODY'; -+ LinkErrorCode['INVALID_HEADERS'] = 'INVALID_HEADERS'; -+ LinkErrorCode['NOT_FOUND'] = 'NOT_FOUND'; -+ LinkErrorCode['NO_LONGER_AVAILABLE'] = 'NO_LONGER_AVAILABLE'; -+ LinkErrorCode['SANDBOX_ONLY'] = 'SANDBOX_ONLY'; -+ LinkErrorCode['INVALID_ACCOUNT_NUMBER'] = 'INVALID_ACCOUNT_NUMBER'; -+ // INVALID_INPUT -+ // From above ITEM_LOGIN_REQUIRED = "INVALID_CREDENTIALS", -+ LinkErrorCode['INCORRECT_DEPOSIT_AMOUNTS'] = 'INCORRECT_DEPOSIT_AMOUNTS'; -+ LinkErrorCode['UNAUTHORIZED_ENVIRONMENT'] = 'UNAUTHORIZED_ENVIRONMENT'; -+ LinkErrorCode['INVALID_PRODUCT'] = 'INVALID_PRODUCT'; -+ LinkErrorCode['UNAUTHORIZED_ROUTE_ACCESS'] = 'UNAUTHORIZED_ROUTE_ACCESS'; -+ LinkErrorCode['DIRECT_INTEGRATION_NOT_ENABLED'] = -+ 'DIRECT_INTEGRATION_NOT_ENABLED'; -+ LinkErrorCode['INVALID_API_KEYS'] = 'INVALID_API_KEYS'; -+ LinkErrorCode['INVALID_ACCESS_TOKEN'] = 'INVALID_ACCESS_TOKEN'; -+ LinkErrorCode['INVALID_PUBLIC_TOKEN'] = 'INVALID_PUBLIC_TOKEN'; -+ LinkErrorCode['INVALID_LINK_TOKEN'] = 'INVALID_LINK_TOKEN'; -+ LinkErrorCode['INVALID_PROCESSOR_TOKEN'] = 'INVALID_PROCESSOR_TOKEN'; -+ LinkErrorCode['INVALID_AUDIT_COPY_TOKEN'] = 'INVALID_AUDIT_COPY_TOKEN'; -+ LinkErrorCode['INVALID_ACCOUNT_ID'] = 'INVALID_ACCOUNT_ID'; -+ LinkErrorCode['MICRODEPOSITS_ALREADY_VERIFIED'] = -+ 'MICRODEPOSITS_ALREADY_VERIFIED'; -+ // INVALID_RESULT -+ LinkErrorCode['PLAID_DIRECT_ITEM_IMPORT_RETURNED_INVALID_MFA'] = -+ 'PLAID_DIRECT_ITEM_IMPORT_RETURNED_INVALID_MFA'; -+ // RATE_LIMIT_EXCEEDED -+ LinkErrorCode['ACCOUNTS_LIMIT'] = 'ACCOUNTS_LIMIT'; -+ LinkErrorCode['ADDITION_LIMIT'] = 'ADDITION_LIMIT'; -+ LinkErrorCode['AUTH_LIMIT'] = 'AUTH_LIMIT'; -+ LinkErrorCode['BALANCE_LIMIT'] = 'BALANCE_LIMIT'; -+ LinkErrorCode['IDENTITY_LIMIT'] = 'IDENTITY_LIMIT'; -+ LinkErrorCode['ITEM_GET_LIMIT'] = 'ITEM_GET_LIMIT'; -+ LinkErrorCode['RATE_LIMIT'] = 'RATE_LIMIT'; -+ LinkErrorCode['TRANSACTIONS_LIMIT'] = 'TRANSACTIONS_LIMIT'; -+ // RECAPTCHA_ERROR -+ LinkErrorCode['RECAPTCHA_REQUIRED'] = 'RECAPTCHA_REQUIRED'; -+ LinkErrorCode['RECAPTCHA_BAD'] = 'RECAPTCHA_BAD'; -+ // OAUTH_ERROR -+ LinkErrorCode['INCORRECT_OAUTH_NONCE'] = 'INCORRECT_OAUTH_NONCE'; -+ LinkErrorCode['OAUTH_STATE_ID_ALREADY_PROCESSED'] = -+ 'OAUTH_STATE_ID_ALREADY_PROCESSED'; - })(LinkErrorCode || (LinkErrorCode = {})); - export var LinkErrorType; --(function (LinkErrorType) { -- LinkErrorType["BANK_TRANSFER"] = "BANK_TRANSFER_ERROR"; -- LinkErrorType["INVALID_REQUEST"] = "INVALID_REQUEST"; -- LinkErrorType["INVALID_RESULT"] = "INVALID_RESULT"; -- LinkErrorType["INVALID_INPUT"] = "INVALID_INPUT"; -- LinkErrorType["INSTITUTION_ERROR"] = "INSTITUTION_ERROR"; -- LinkErrorType["RATE_LIMIT_EXCEEDED"] = "RATE_LIMIT_EXCEEDED"; -- LinkErrorType["API_ERROR"] = "API_ERROR"; -- LinkErrorType["ITEM_ERROR"] = "ITEM_ERROR"; -- LinkErrorType["AUTH_ERROR"] = "AUTH_ERROR"; -- LinkErrorType["ASSET_REPORT_ERROR"] = "ASSET_REPORT_ERROR"; -- LinkErrorType["SANDBOX_ERROR"] = "SANDBOX_ERROR"; -- LinkErrorType["RECAPTCHA_ERROR"] = "RECAPTCHA_ERROR"; -- LinkErrorType["OAUTH_ERROR"] = "OAUTH_ERROR"; -+(function(LinkErrorType) { -+ LinkErrorType['BANK_TRANSFER'] = 'BANK_TRANSFER_ERROR'; -+ LinkErrorType['INVALID_REQUEST'] = 'INVALID_REQUEST'; -+ LinkErrorType['INVALID_RESULT'] = 'INVALID_RESULT'; -+ LinkErrorType['INVALID_INPUT'] = 'INVALID_INPUT'; -+ LinkErrorType['INSTITUTION_ERROR'] = 'INSTITUTION_ERROR'; -+ LinkErrorType['RATE_LIMIT_EXCEEDED'] = 'RATE_LIMIT_EXCEEDED'; -+ LinkErrorType['API_ERROR'] = 'API_ERROR'; -+ LinkErrorType['ITEM_ERROR'] = 'ITEM_ERROR'; -+ LinkErrorType['AUTH_ERROR'] = 'AUTH_ERROR'; -+ LinkErrorType['ASSET_REPORT_ERROR'] = 'ASSET_REPORT_ERROR'; -+ LinkErrorType['SANDBOX_ERROR'] = 'SANDBOX_ERROR'; -+ LinkErrorType['RECAPTCHA_ERROR'] = 'RECAPTCHA_ERROR'; -+ LinkErrorType['OAUTH_ERROR'] = 'OAUTH_ERROR'; - })(LinkErrorType || (LinkErrorType = {})); - export var LinkEventName; --(function (LinkEventName) { -- LinkEventName["BANK_INCOME_INSIGHTS_COMPLETED"] = "BANK_INCOME_INSIGHTS_COMPLETED"; -- LinkEventName["CLOSE_OAUTH"] = "CLOSE_OAUTH"; -- LinkEventName["ERROR"] = "ERROR"; -- LinkEventName["EXIT"] = "EXIT"; -- LinkEventName["FAIL_OAUTH"] = "FAIL_OAUTH"; -- LinkEventName["HANDOFF"] = "HANDOFF"; -- LinkEventName["IDENTITY_VERIFICATION_START_STEP"] = "IDENTITY_VERIFICATION_START_STEP"; -- LinkEventName["IDENTITY_VERIFICATION_PASS_STEP"] = "IDENTITY_VERIFICATION_PASS_STEP"; -- LinkEventName["IDENTITY_VERIFICATION_FAIL_STEP"] = "IDENTITY_VERIFICATION_FAIL_STEP"; -- LinkEventName["IDENTITY_VERIFICATION_PENDING_REVIEW_STEP"] = "IDENTITY_VERIFICATION_PENDING_REVIEW_STEP"; -- LinkEventName["IDENTITY_VERIFICATION_PENDING_REVIEW_SESSION"] = "IDENTITY_VERIFICATION_PENDING_REVIEW_SESSION"; -- LinkEventName["IDENTITY_VERIFICATION_CREATE_SESSION"] = "IDENTITY_VERIFICATION_CREATE_SESSION"; -- LinkEventName["IDENTITY_VERIFICATION_RESUME_SESSION"] = "IDENTITY_VERIFICATION_RESUME_SESSION"; -- LinkEventName["IDENTITY_VERIFICATION_PASS_SESSION"] = "IDENTITY_VERIFICATION_PASS_SESSION"; -- LinkEventName["IDENTITY_VERIFICATION_FAIL_SESSION"] = "IDENTITY_VERIFICATION_FAIL_SESSION"; -- LinkEventName["IDENTITY_VERIFICATION_OPEN_UI"] = "IDENTITY_VERIFICATION_OPEN_UI"; -- LinkEventName["IDENTITY_VERIFICATION_RESUME_UI"] = "IDENTITY_VERIFICATION_RESUME_UI"; -- LinkEventName["IDENTITY_VERIFICATION_CLOSE_UI"] = "IDENTITY_VERIFICATION_CLOSE_UI"; -- LinkEventName["MATCHED_CONSENT"] = "MATCHED_CONSENT"; -- LinkEventName["MATCHED_SELECT_INSTITUTION"] = "MATCHED_SELECT_INSTITUTION"; -- LinkEventName["MATCHED_SELECT_VERIFY_METHOD"] = "MATCHED_SELECT_VERIFY_METHOD"; -- LinkEventName["OPEN"] = "OPEN"; -- LinkEventName["OPEN_MY_PLAID"] = "OPEN_MY_PLAID"; -- LinkEventName["OPEN_OAUTH"] = "OPEN_OAUTH"; -- LinkEventName["SEARCH_INSTITUTION"] = "SEARCH_INSTITUTION"; -- LinkEventName["SELECT_DEGRADED_INSTITUTION"] = "SELECT_DEGRADED_INSTITUTION"; -- LinkEventName["SELECT_DOWN_INSTITUTION"] = "SELECT_DOWN_INSTITUTION"; -- LinkEventName["SELECT_FILTERED_INSTITUTION"] = "SELECT_FILTERED_INSTITUTION"; -- LinkEventName["SELECT_INSTITUTION"] = "SELECT_INSTITUTION"; -- LinkEventName["SELECT_BRAND"] = "SELECT_BRAND"; -- LinkEventName["SELECT_AUTH_TYPE"] = "SELECT_AUTH_TYPE"; -- LinkEventName["SUBMIT_ACCOUNT_NUMBER"] = "SUBMIT_ACCOUNT_NUMBER"; -- LinkEventName["SUBMIT_DOCUMENTS"] = "SUBMIT_DOCUMENTS"; -- LinkEventName["SUBMIT_DOCUMENTS_SUCCESS"] = "SUBMIT_DOCUMENTS_SUCCESS"; -- LinkEventName["SUBMIT_DOCUMENTS_ERROR"] = "SUBMIT_DOCUMENTS_ERROR"; -- LinkEventName["SUBMIT_ROUTING_NUMBER"] = "SUBMIT_ROUTING_NUMBER"; -- LinkEventName["VIEW_DATA_TYPES"] = "VIEW_DATA_TYPES"; -- LinkEventName["SUBMIT_PHONE"] = "SUBMIT_PHONE"; -- LinkEventName["SKIP_SUBMIT_PHONE"] = "SKIP_SUBMIT_PHONE"; -- LinkEventName["VERIFY_PHONE"] = "VERIFY_PHONE"; -- LinkEventName["SUBMIT_CREDENTIALS"] = "SUBMIT_CREDENTIALS"; -- LinkEventName["SUBMIT_MFA"] = "SUBMIT_MFA"; -- LinkEventName["TRANSITION_VIEW"] = "TRANSITION_VIEW"; -- LinkEventName["CONNECT_NEW_INSTITUTION"] = "CONNECT_NEW_INSTITUTION"; -+(function(LinkEventName) { -+ LinkEventName['BANK_INCOME_INSIGHTS_COMPLETED'] = -+ 'BANK_INCOME_INSIGHTS_COMPLETED'; -+ LinkEventName['CLOSE_OAUTH'] = 'CLOSE_OAUTH'; -+ LinkEventName['ERROR'] = 'ERROR'; -+ LinkEventName['EXIT'] = 'EXIT'; -+ LinkEventName['FAIL_OAUTH'] = 'FAIL_OAUTH'; -+ LinkEventName['HANDOFF'] = 'HANDOFF'; -+ LinkEventName['IDENTITY_VERIFICATION_START_STEP'] = -+ 'IDENTITY_VERIFICATION_START_STEP'; -+ LinkEventName['IDENTITY_VERIFICATION_PASS_STEP'] = -+ 'IDENTITY_VERIFICATION_PASS_STEP'; -+ LinkEventName['IDENTITY_VERIFICATION_FAIL_STEP'] = -+ 'IDENTITY_VERIFICATION_FAIL_STEP'; -+ LinkEventName['IDENTITY_VERIFICATION_PENDING_REVIEW_STEP'] = -+ 'IDENTITY_VERIFICATION_PENDING_REVIEW_STEP'; -+ LinkEventName['IDENTITY_VERIFICATION_PENDING_REVIEW_SESSION'] = -+ 'IDENTITY_VERIFICATION_PENDING_REVIEW_SESSION'; -+ LinkEventName['IDENTITY_VERIFICATION_CREATE_SESSION'] = -+ 'IDENTITY_VERIFICATION_CREATE_SESSION'; -+ LinkEventName['IDENTITY_VERIFICATION_RESUME_SESSION'] = -+ 'IDENTITY_VERIFICATION_RESUME_SESSION'; -+ LinkEventName['IDENTITY_VERIFICATION_PASS_SESSION'] = -+ 'IDENTITY_VERIFICATION_PASS_SESSION'; -+ LinkEventName['IDENTITY_VERIFICATION_FAIL_SESSION'] = -+ 'IDENTITY_VERIFICATION_FAIL_SESSION'; -+ LinkEventName['IDENTITY_VERIFICATION_OPEN_UI'] = -+ 'IDENTITY_VERIFICATION_OPEN_UI'; -+ LinkEventName['IDENTITY_VERIFICATION_RESUME_UI'] = -+ 'IDENTITY_VERIFICATION_RESUME_UI'; -+ LinkEventName['IDENTITY_VERIFICATION_CLOSE_UI'] = -+ 'IDENTITY_VERIFICATION_CLOSE_UI'; -+ LinkEventName['MATCHED_CONSENT'] = 'MATCHED_CONSENT'; -+ LinkEventName['MATCHED_SELECT_INSTITUTION'] = 'MATCHED_SELECT_INSTITUTION'; -+ LinkEventName['MATCHED_SELECT_VERIFY_METHOD'] = -+ 'MATCHED_SELECT_VERIFY_METHOD'; -+ LinkEventName['OPEN'] = 'OPEN'; -+ LinkEventName['OPEN_MY_PLAID'] = 'OPEN_MY_PLAID'; -+ LinkEventName['OPEN_OAUTH'] = 'OPEN_OAUTH'; -+ LinkEventName['SEARCH_INSTITUTION'] = 'SEARCH_INSTITUTION'; -+ LinkEventName['SELECT_DEGRADED_INSTITUTION'] = 'SELECT_DEGRADED_INSTITUTION'; -+ LinkEventName['SELECT_DOWN_INSTITUTION'] = 'SELECT_DOWN_INSTITUTION'; -+ LinkEventName['SELECT_FILTERED_INSTITUTION'] = 'SELECT_FILTERED_INSTITUTION'; -+ LinkEventName['SELECT_INSTITUTION'] = 'SELECT_INSTITUTION'; -+ LinkEventName['SELECT_BRAND'] = 'SELECT_BRAND'; -+ LinkEventName['SELECT_AUTH_TYPE'] = 'SELECT_AUTH_TYPE'; -+ LinkEventName['SUBMIT_ACCOUNT_NUMBER'] = 'SUBMIT_ACCOUNT_NUMBER'; -+ LinkEventName['SUBMIT_DOCUMENTS'] = 'SUBMIT_DOCUMENTS'; -+ LinkEventName['SUBMIT_DOCUMENTS_SUCCESS'] = 'SUBMIT_DOCUMENTS_SUCCESS'; -+ LinkEventName['SUBMIT_DOCUMENTS_ERROR'] = 'SUBMIT_DOCUMENTS_ERROR'; -+ LinkEventName['SUBMIT_ROUTING_NUMBER'] = 'SUBMIT_ROUTING_NUMBER'; -+ LinkEventName['VIEW_DATA_TYPES'] = 'VIEW_DATA_TYPES'; -+ LinkEventName['SUBMIT_PHONE'] = 'SUBMIT_PHONE'; -+ LinkEventName['SKIP_SUBMIT_PHONE'] = 'SKIP_SUBMIT_PHONE'; -+ LinkEventName['VERIFY_PHONE'] = 'VERIFY_PHONE'; -+ LinkEventName['SUBMIT_CREDENTIALS'] = 'SUBMIT_CREDENTIALS'; -+ LinkEventName['SUBMIT_MFA'] = 'SUBMIT_MFA'; -+ LinkEventName['TRANSITION_VIEW'] = 'TRANSITION_VIEW'; -+ LinkEventName['CONNECT_NEW_INSTITUTION'] = 'CONNECT_NEW_INSTITUTION'; - })(LinkEventName || (LinkEventName = {})); - export var LinkEventViewName; --(function (LinkEventViewName) { -- LinkEventViewName["ACCEPT_TOS"] = "ACCEPT_TOS"; -- LinkEventViewName["CONNECTED"] = "CONNECTED"; -- LinkEventViewName["CONSENT"] = "CONSENT"; -- LinkEventViewName["CREDENTIAL"] = "CREDENTIAL"; -- LinkEventViewName["DATA_TRANSPARENCY"] = "DATA_TRANSPARENCY"; -- LinkEventViewName["DATA_TRANSPARENCY_CONSENT"] = "DATA_TRANSPARENCY_CONSENT"; -- LinkEventViewName["DOCUMENTARY_VERIFICATION"] = "DOCUMENTARY_VERIFICATION"; -- LinkEventViewName["ERROR"] = "ERROR"; -- LinkEventViewName["EXIT"] = "EXIT"; -- LinkEventViewName["KYC_CHECK"] = "KYC_CHECK"; -- LinkEventViewName["SELFIE_CHECK"] = "SELFIE_CHECK"; -- LinkEventViewName["LOADING"] = "LOADING"; -- LinkEventViewName["MATCHED_CONSENT"] = "MATCHED_CONSENT"; -- LinkEventViewName["MATCHED_CREDENTIAL"] = "MATCHED_CREDENTIAL"; -- LinkEventViewName["MATCHED_MFA"] = "MATCHED_MFA"; -- LinkEventViewName["MFA"] = "MFA"; -- LinkEventViewName["NUMBERS"] = "NUMBERS"; -- LinkEventViewName["NUMBERS_SELECT_INSTITUTION"] = "NUMBERS_SELECT_INSTITUTION"; -- LinkEventViewName["OAUTH"] = "OAUTH"; -- LinkEventViewName["RECAPTCHA"] = "RECAPTCHA"; -- LinkEventViewName["RISK_CHECK"] = "RISK_CHECK"; -- LinkEventViewName["SCREENING"] = "SCREENING"; -- LinkEventViewName["SELECT_ACCOUNT"] = "SELECT_ACCOUNT"; -- LinkEventViewName["SELECT_AUTH_TYPE"] = "SELECT_AUTH_TYPE"; -- LinkEventViewName["SUBMIT_PHONE"] = "SUBMIT_PHONE"; -- LinkEventViewName["VERIFY_PHONE"] = "VERIFY_PHONE"; -- LinkEventViewName["SELECT_SAVED_INSTITUTION"] = "SELECT_SAVED_INSTITUTION"; -- LinkEventViewName["SELECT_SAVED_ACCOUNT"] = "SELECT_SAVED_ACCOUNT"; -- LinkEventViewName["SELECT_BRAND"] = "SELECT_BRAND"; -- LinkEventViewName["SELECT_INSTITUTION"] = "SELECT_INSTITUTION"; -- LinkEventViewName["SUBMIT_DOCUMENTS"] = "SUBMIT_DOCUMENTS"; -- LinkEventViewName["SUBMIT_DOCUMENTS_SUCCESS"] = "SUBMIT_DOCUMENTS_SUCCESS"; -- LinkEventViewName["SUBMIT_DOCUMENTS_ERROR"] = "SUBMIT_DOCUMENTS_ERROR"; -- LinkEventViewName["UPLOAD_DOCUMENTS"] = "UPLOAD_DOCUMENTS"; -- LinkEventViewName["VERIFY_SMS"] = "VERIFY_SMS"; -+(function(LinkEventViewName) { -+ LinkEventViewName['ACCEPT_TOS'] = 'ACCEPT_TOS'; -+ LinkEventViewName['CONNECTED'] = 'CONNECTED'; -+ LinkEventViewName['CONSENT'] = 'CONSENT'; -+ LinkEventViewName['CREDENTIAL'] = 'CREDENTIAL'; -+ LinkEventViewName['DATA_TRANSPARENCY'] = 'DATA_TRANSPARENCY'; -+ LinkEventViewName['DATA_TRANSPARENCY_CONSENT'] = 'DATA_TRANSPARENCY_CONSENT'; -+ LinkEventViewName['DOCUMENTARY_VERIFICATION'] = 'DOCUMENTARY_VERIFICATION'; -+ LinkEventViewName['ERROR'] = 'ERROR'; -+ LinkEventViewName['EXIT'] = 'EXIT'; -+ LinkEventViewName['KYC_CHECK'] = 'KYC_CHECK'; -+ LinkEventViewName['SELFIE_CHECK'] = 'SELFIE_CHECK'; -+ LinkEventViewName['LOADING'] = 'LOADING'; -+ LinkEventViewName['MATCHED_CONSENT'] = 'MATCHED_CONSENT'; -+ LinkEventViewName['MATCHED_CREDENTIAL'] = 'MATCHED_CREDENTIAL'; -+ LinkEventViewName['MATCHED_MFA'] = 'MATCHED_MFA'; -+ LinkEventViewName['MFA'] = 'MFA'; -+ LinkEventViewName['NUMBERS'] = 'NUMBERS'; -+ LinkEventViewName['NUMBERS_SELECT_INSTITUTION'] = -+ 'NUMBERS_SELECT_INSTITUTION'; -+ LinkEventViewName['OAUTH'] = 'OAUTH'; -+ LinkEventViewName['RECAPTCHA'] = 'RECAPTCHA'; -+ LinkEventViewName['RISK_CHECK'] = 'RISK_CHECK'; -+ LinkEventViewName['SCREENING'] = 'SCREENING'; -+ LinkEventViewName['SELECT_ACCOUNT'] = 'SELECT_ACCOUNT'; -+ LinkEventViewName['SELECT_AUTH_TYPE'] = 'SELECT_AUTH_TYPE'; -+ LinkEventViewName['SUBMIT_PHONE'] = 'SUBMIT_PHONE'; -+ LinkEventViewName['VERIFY_PHONE'] = 'VERIFY_PHONE'; -+ LinkEventViewName['SELECT_SAVED_INSTITUTION'] = 'SELECT_SAVED_INSTITUTION'; -+ LinkEventViewName['SELECT_SAVED_ACCOUNT'] = 'SELECT_SAVED_ACCOUNT'; -+ LinkEventViewName['SELECT_BRAND'] = 'SELECT_BRAND'; -+ LinkEventViewName['SELECT_INSTITUTION'] = 'SELECT_INSTITUTION'; -+ LinkEventViewName['SUBMIT_DOCUMENTS'] = 'SUBMIT_DOCUMENTS'; -+ LinkEventViewName['SUBMIT_DOCUMENTS_SUCCESS'] = 'SUBMIT_DOCUMENTS_SUCCESS'; -+ LinkEventViewName['SUBMIT_DOCUMENTS_ERROR'] = 'SUBMIT_DOCUMENTS_ERROR'; -+ LinkEventViewName['UPLOAD_DOCUMENTS'] = 'UPLOAD_DOCUMENTS'; -+ LinkEventViewName['VERIFY_SMS'] = 'VERIFY_SMS'; - })(LinkEventViewName || (LinkEventViewName = {})); - /// Methods to present Link on iOS. - /// FULL_SCREEN is the converts to UIModalPresentationOverFullScreen on the native side. - /// MODAL will use the default presentation style for iOS which is UIModalPresentationAutomatic. - export var LinkIOSPresentationStyle; --(function (LinkIOSPresentationStyle) { -- LinkIOSPresentationStyle["FULL_SCREEN"] = "FULL_SCREEN"; -- LinkIOSPresentationStyle["MODAL"] = "MODAL"; -+(function(LinkIOSPresentationStyle) { -+ LinkIOSPresentationStyle['FULL_SCREEN'] = 'FULL_SCREEN'; -+ LinkIOSPresentationStyle['MODAL'] = 'MODAL'; - })(LinkIOSPresentationStyle || (LinkIOSPresentationStyle = {})); -diff --git a/node_modules/react-native-plaid-link-sdk/dist/__tests__/Types.tests.d.ts b/node_modules/react-native-plaid-link-sdk/dist/__tests__/Types.tests.d.ts -index cd4ccde..cb0ff5c 100644 ---- a/node_modules/react-native-plaid-link-sdk/dist/__tests__/Types.tests.d.ts -+++ b/node_modules/react-native-plaid-link-sdk/dist/__tests__/Types.tests.d.ts -@@ -1 +1 @@ --declare const Types: any; -+export {}; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/__tests__/Types.tests.js b/node_modules/react-native-plaid-link-sdk/dist/__tests__/Types.tests.js -index 831866b..f38aff8 100644 ---- a/node_modules/react-native-plaid-link-sdk/dist/__tests__/Types.tests.js -+++ b/node_modules/react-native-plaid-link-sdk/dist/__tests__/Types.tests.js -@@ -1,14 +1,14 @@ --"use strict"; - const Types = require('./../Types'); - test('test token configuration', () => { -- const linkTokenConfiguration = { -- token: "test-token", -- noLoadingState: false, -- logLevel: Types.LinkLogLevel.DEBUG, -- extras: null, -- }; -- expect(linkTokenConfiguration.noLoadingState).toBe(false); -- expect(linkTokenConfiguration.token).toBe("test-token"); -- expect(linkTokenConfiguration.logLevel).toBe(Types.LinkLogLevel.DEBUG); -- expect(linkTokenConfiguration.extras).toBe(null); -+ const linkTokenConfiguration = { -+ token: 'test-token', -+ noLoadingState: false, -+ logLevel: Types.LinkLogLevel.DEBUG, -+ extras: null, -+ }; -+ expect(linkTokenConfiguration.noLoadingState).toBe(false); -+ expect(linkTokenConfiguration.token).toBe('test-token'); -+ expect(linkTokenConfiguration.logLevel).toBe(Types.LinkLogLevel.DEBUG); -+ expect(linkTokenConfiguration.extras).toBe(null); - }); -+export {}; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/check_version_hook.d.ts b/node_modules/react-native-plaid-link-sdk/dist/check_version_hook.d.ts -new file mode 100644 -index 0000000..cb0ff5c ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/dist/check_version_hook.d.ts -@@ -0,0 +1 @@ -+export {}; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/check_version_hook.js b/node_modules/react-native-plaid-link-sdk/dist/check_version_hook.js -new file mode 100644 -index 0000000..34a47d4 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/dist/check_version_hook.js -@@ -0,0 +1,15 @@ -+'use strict'; -+const fs = require('fs'); -+const rn_version = JSON.parse(fs.readFileSync('package.json', 'utf-8'))[ -+ 'version' -+]; -+const android_version = fs -+ .readFileSync('android/src/main/AndroidManifest.xml', 'utf-8') -+ .match(/(?<=value=").*(?=")/)[0]; -+if (rn_version != android_version) { -+ console.error('Commit failed SDK version mismatch'); -+ console.error( -+ 'Please ensure package.json and android/src/main/AndroidManifest.xml have the same version', -+ ); -+ process.exit(-1); -+} -diff --git a/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModule.d.ts b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModule.d.ts -new file mode 100644 -index 0000000..1de3019 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModule.d.ts -@@ -0,0 +1,14 @@ -+import { TurboModule } from 'react-native'; -+import { Int32 } from 'react-native/Libraries/Types/CodegenTypes'; -+import { LinkSuccess as UnsafeObject, LinkExit as Double, LinkError as Float } from '../Types'; -+export interface Spec extends TurboModule { -+ continueFromRedirectUriString(redirectUriString: string): void; -+ create(configuration: Object): void; -+ open(onSuccess: (success: UnsafeObject) => void, onExit: (error: Float, result: Double) => void): void; -+ dismiss(): void; -+ startLinkActivityForResult(data: string, onSuccessCallback: (result: UnsafeObject) => void, onExitCallback: (result: Double) => void): void; -+ addListener(eventName: string): void; -+ removeListeners(count: Int32): void; -+} -+declare const _default: Spec; -+export default _default; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModule.js b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModule.js -new file mode 100644 -index 0000000..310a9c5 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModule.js -@@ -0,0 +1,4 @@ -+// we use Object type because methods on the native side use NSDictionary and ReadableMap -+// and we want to stay compatible with those -+import { TurboModuleRegistry } from 'react-native'; -+export default TurboModuleRegistry.getEnforcing('RNLinksdk'); -diff --git a/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleAndroid.d.ts b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleAndroid.d.ts -new file mode 100644 -index 0000000..82f29a1 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleAndroid.d.ts -@@ -0,0 +1,9 @@ -+import { TurboModule } from 'react-native'; -+import { Int32, UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; -+export interface Spec extends TurboModule { -+ startLinkActivityForResult(token: string, noLoadingState: boolean, logLevel: string, onSuccessCallback: (result: UnsafeObject) => void, onExitCallback: (result: UnsafeObject) => void): void; -+ addListener(eventName: string): void; -+ removeListeners(count: Int32): void; -+} -+declare const _default: Spec | null; -+export default _default; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleAndroid.js b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleAndroid.js -new file mode 100644 -index 0000000..d0ea456 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleAndroid.js -@@ -0,0 +1,4 @@ -+// we use Object type because methods on the native side use NSDictionary and ReadableMap -+// and we want to stay compatible with those -+import { TurboModuleRegistry } from 'react-native'; -+export default TurboModuleRegistry.get('PlaidAndroid'); -diff --git a/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleiOS.d.ts b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleiOS.d.ts -new file mode 100644 -index 0000000..aefee8c ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleiOS.d.ts -@@ -0,0 +1,11 @@ -+import { TurboModule } from 'react-native'; -+import { Int32, UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; -+export interface Spec extends TurboModule { -+ create(token: string, noLoadingState: boolean): void; -+ open(fullScreen: boolean, onSuccess: (success: UnsafeObject) => void, onExit: (error: UnsafeObject, result: UnsafeObject) => void): void; -+ dismiss(): void; -+ addListener(eventName: string): void; -+ removeListeners(count: Int32): void; -+} -+declare const _default: Spec | null; -+export default _default; -diff --git a/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleiOS.js b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleiOS.js -new file mode 100644 -index 0000000..99845a1 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/dist/fabric/NativePlaidLinkModuleiOS.js -@@ -0,0 +1,4 @@ -+// we use Object type because methods on the native side use NSDictionary and ReadableMap -+// and we want to stay compatible with those -+import { TurboModuleRegistry } from 'react-native'; -+export default TurboModuleRegistry.get('RNLinksdk'); -diff --git a/node_modules/react-native-plaid-link-sdk/dist/index.js b/node_modules/react-native-plaid-link-sdk/dist/index.js -index 68c2d4b..acad079 100644 ---- a/node_modules/react-native-plaid-link-sdk/dist/index.js -+++ b/node_modules/react-native-plaid-link-sdk/dist/index.js -@@ -1,6 +1,6 @@ --import { openLink, dismissLink, usePlaidEmitter, PlaidLink, } from './PlaidLink'; -+import { openLink, dismissLink, usePlaidEmitter, PlaidLink } from './PlaidLink'; - export * from './Types'; - export default PlaidLink; --export { PlaidLink, openLink, dismissLink, usePlaidEmitter, }; -+export { PlaidLink, openLink, dismissLink, usePlaidEmitter }; - // Components - export { EmbeddedLinkView } from './EmbeddedLink/EmbeddedLinkView'; -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.h b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.h -index 8a1c350..035b91c 100644 ---- a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.h -+++ b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.h -@@ -1,15 +1,17 @@ -- --#if __has_include() --#import --#import --#else --#import "RCTBridgeModule.h" --#import "RCTEventEmitter.h" -+#ifdef RCT_NEW_ARCH_ENABLED -+#import - #endif -+#import -+#import "RCTEventEmitter.h" - - #import - --@interface RNLinksdk : RCTEventEmitter -+@interface RNLinksdk : RCTEventEmitter -+#ifdef RCT_NEW_ARCH_ENABLED -+ -+#else -+ -+#endif - - + (NSDictionary *)dictionaryFromSuccess:(PLKLinkSuccess *)success; - + (NSDictionary *)dictionaryFromEvent:(PLKLinkEvent *)event; -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.mm b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.mm -index ef3fe85..b3b92d6 100644 ---- a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.mm -+++ b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.mm -@@ -1,4 +1,5 @@ - #import "RNLinksdk.h" -+#import "RNPlaidHelper.h" - - #import - #import -@@ -66,11 +67,11 @@ - (void)stopObserving { - self.hasObservers = NO; - } - --RCT_EXPORT_METHOD(create:(NSString*)token :(BOOL)noLoadingState) { -- __weak typeof(self) weakSelf = self; -+RCT_EXPORT_METHOD(create:(NSString*)token noLoadingState:(BOOL)noLoadingState) { -+ __weak RNLinksdk *weakSelf = self; - - void (^onSuccess)(PLKLinkSuccess *) = ^(PLKLinkSuccess *success) { -- __typeof(weakSelf) strongSelf = weakSelf; -+ RNLinksdk *strongSelf = weakSelf; - - if (strongSelf.successCallback) { - NSDictionary *jsMetadata = [RNLinksdk dictionaryFromSuccess:success]; -@@ -80,7 +81,7 @@ - (void)stopObserving { - }; - - void (^onExit)(PLKLinkExit *) = ^(PLKLinkExit *exit) { -- __typeof(weakSelf) strongSelf = weakSelf; -+ RNLinksdk *strongSelf = weakSelf; - - if (strongSelf.exitCallback) { - NSDictionary *exitMetadata = [RNLinksdk dictionaryFromExit:exit]; -@@ -94,7 +95,7 @@ - (void)stopObserving { - }; - - void (^onEvent)(PLKLinkEvent *) = ^(PLKLinkEvent *event) { -- __typeof(weakSelf) strongSelf = weakSelf; -+ RNLinksdk *strongSelf = weakSelf; - if (strongSelf.hasObservers) { - NSDictionary *eventDictionary = [RNLinksdk dictionaryFromEvent:event]; - [strongSelf sendEventWithName:kRNLinkKitOnEventEvent -@@ -108,11 +109,11 @@ - (void)stopObserving { - config.noLoadingState = noLoadingState; - - NSError *creationError = nil; -- self.linkHandler = [PLKPlaid createWithLinkTokenConfiguration:config error:&creationError]; -+ self.linkHandler = [RNPlaidHelper createWithLinkTokenConfiguration:config error:&creationError]; - self.creationError = creationError; - } - --RCT_EXPORT_METHOD(open: (BOOL)fullScreen :(RCTResponseSenderBlock)onSuccess :(RCTResponseSenderBlock)onExit) { -+RCT_EXPORT_METHOD(open:(BOOL)fullScreen onSuccess:(RCTResponseSenderBlock)onSuccess onExit:(RCTResponseSenderBlock)onExit) { - if (self.linkHandler) { - self.successCallback = onSuccess; - self.exitCallback = onExit; -@@ -122,7 +123,7 @@ - (void)stopObserving { - // unnecessarily invoked. - __block bool didPresent = NO; - -- __weak typeof(self) weakSelf = self; -+ __weak RNLinksdk *weakSelf = self; - void(^presentationHandler)(UIViewController *) = ^(UIViewController *linkViewController) { - - if (fullScreen) { -@@ -619,4 +620,12 @@ + (NSDictionary *)dictionaryFromExit:(PLKLinkExit *)exit { - }; - } - -+#if RCT_NEW_ARCH_ENABLED -+- (std::shared_ptr)getTurboModule: -+ (const facebook::react::ObjCTurboModule::InitParams &)params -+{ -+ return std::make_shared(params); -+} -+#endif -+ - @end -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata -deleted file mode 100644 -index 919434a..0000000 ---- a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata -+++ /dev/null -@@ -1,7 +0,0 @@ -- -- -- -- -- -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist -deleted file mode 100644 -index 18d9810..0000000 ---- a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist -+++ /dev/null -@@ -1,8 +0,0 @@ -- -- -- -- -- IDEDidComputeMac32BitWarning -- -- -- -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/xcuserdata/dtroupe.xcuserdatad/UserInterfaceState.xcuserstate b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/xcuserdata/dtroupe.xcuserdatad/UserInterfaceState.xcuserstate -deleted file mode 100644 -index 47e9cc2..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/project.xcworkspace/xcuserdata/dtroupe.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/xcuserdata/dtroupe.xcuserdatad/xcschemes/xcschememanagement.plist b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/xcuserdata/dtroupe.xcuserdatad/xcschemes/xcschememanagement.plist -deleted file mode 100644 -index 5b4fa70..0000000 ---- a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcodeproj/xcuserdata/dtroupe.xcuserdatad/xcschemes/xcschememanagement.plist -+++ /dev/null -@@ -1,19 +0,0 @@ -- -- -- -- -- SchemeUserState -- -- RNLinksdk.xcscheme_^#shared#^_ -- -- orderHint -- 0 -- -- RNLinksdkUnitTests.xcscheme_^#shared#^_ -- -- orderHint -- 1 -- -- -- -- -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcworkspace/xcuserdata/dtroupe.xcuserdatad/UserInterfaceState.xcuserstate b/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcworkspace/xcuserdata/dtroupe.xcuserdatad/UserInterfaceState.xcuserstate -deleted file mode 100644 -index 824773d..0000000 -Binary files a/node_modules/react-native-plaid-link-sdk/ios/RNLinksdk.xcworkspace/xcuserdata/dtroupe.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNPlaidHelper.h b/node_modules/react-native-plaid-link-sdk/ios/RNPlaidHelper.h -new file mode 100644 -index 0000000..535d333 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/ios/RNPlaidHelper.h -@@ -0,0 +1,7 @@ -+#import -+ -+@interface RNPlaidHelper : NSObject -+ -++ (id _Nullable)createWithLinkTokenConfiguration:(PLKLinkTokenConfiguration * _Nonnull)linkTokenConfiguration error:(NSError * _Nullable * _Nullable)error; -+ -+@end -diff --git a/node_modules/react-native-plaid-link-sdk/ios/RNPlaidHelper.m b/node_modules/react-native-plaid-link-sdk/ios/RNPlaidHelper.m -new file mode 100644 -index 0000000..2288299 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/ios/RNPlaidHelper.m -@@ -0,0 +1,10 @@ -+#import "RNPlaidHelper.h" -+ -+@implementation RNPlaidHelper -+ -++ (id _Nullable)createWithLinkTokenConfiguration:(PLKLinkTokenConfiguration * _Nonnull)linkTokenConfiguration error:(NSError * _Nullable * _Nullable)error -+{ -+ return [PLKPlaid createWithLinkTokenConfiguration:linkTokenConfiguration error:error]; -+} -+ -+@end -diff --git a/node_modules/react-native-plaid-link-sdk/package.json b/node_modules/react-native-plaid-link-sdk/package.json -index 22c7d2c..3d1b85c 100644 ---- a/node_modules/react-native-plaid-link-sdk/package.json -+++ b/node_modules/react-native-plaid-link-sdk/package.json -@@ -4,11 +4,13 @@ - "description": "React Native Plaid Link SDK", - "main": "dist/index.js", - "types": "dist/index.d.ts", -+ "react-native": "src/index.ts", - "files": [ - "dist/**/*", - "android/**/*", -- "ios", -- "react-native-plaid-link-sdk.podspec" -+ "ios/**/*", -+ "react-native-plaid-link-sdk.podspec", -+ "src/**/*" - ], - "scripts": { - "lint": "eslint \"./**/*.{js,jsx}\" --fix", -@@ -47,7 +49,7 @@ - "@react-native-community/eslint-plugin": "^1.1.0", - "@types/jest": "^26.0.14", - "@types/react": "^16.14.20", -- "@types/react-native": "^0.66.0", -+ "@types/react-native": "^0.71.3", - "@types/react-test-renderer": "^16.9.3", - "@typescript-eslint/eslint-plugin": "^4.33.0", - "@typescript-eslint/parser": "^4.33.0", -@@ -62,5 +64,16 @@ - "react": "18.0.0", - "react-native": "0.69.9", - "typescript": "^4.9.5" -+ }, -+ "dependencies": { -+ "react-native-plaid-link-sdk": "^10.4.0" -+ }, -+ "codegenConfig": { -+ "name": "rnplaidlink", -+ "type": "modules", -+ "jsSrcsDir": "./src/fabric", -+ "android": { -+ "javaPackageName": "com.plaid" -+ } - } - } -diff --git a/node_modules/react-native-plaid-link-sdk/react-native-plaid-link-sdk.podspec b/node_modules/react-native-plaid-link-sdk/react-native-plaid-link-sdk.podspec -index ee59a19..40ac7df 100644 ---- a/node_modules/react-native-plaid-link-sdk/react-native-plaid-link-sdk.podspec -+++ b/node_modules/react-native-plaid-link-sdk/react-native-plaid-link-sdk.podspec -@@ -2,6 +2,8 @@ require 'json' - - package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) - -+fabric_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1' -+ - Pod::Spec.new do |s| - s.name = package['name'] - s.version = package['version'] -@@ -13,8 +15,13 @@ Pod::Spec.new do |s| - s.platform = :ios, "14.0" - - s.source = { :git => "https://github.com/plaid/react-native-plaid-link-sdk.git", :tag => "v#{s.version}" } -- s.source_files = "ios/*.{h,m,swift}" -+ s.source_files = "ios/**/*.{h,m,mm,swift}" -+ -+ if fabric_enabled -+ install_modules_dependencies(s) -+ else -+ s.dependency "React-Core" -+ end - -- s.dependency 'React-Core' - s.dependency 'Plaid', '~> 5.2.0' - end -diff --git a/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/EmbeddedLinkView.tsx b/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/EmbeddedLinkView.tsx -new file mode 100644 -index 0000000..0243de2 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/EmbeddedLinkView.tsx -@@ -0,0 +1,95 @@ -+import React from 'react'; -+import { StyleProp, ViewStyle } from 'react-native'; -+import NativeEmbeddedLinkView from './NativeEmbeddedLinkView'; -+import { -+ LinkSuccessListener, -+ LinkSuccess, -+ LinkExitListener, -+ LinkExit, -+ LinkIOSPresentationStyle, -+ LinkOnEventListener, -+ LinkEvent, -+ LinkEventName, -+ LinkEventMetadata, -+ LinkError, -+ LinkExitMetadata, -+ LinkSuccessMetadata, -+} from '../Types'; -+ -+type EmbeddedLinkProps = { -+ token: String, -+ iOSPresentationStyle: LinkIOSPresentationStyle, -+ onEvent: LinkOnEventListener | undefined, -+ onSuccess: LinkSuccessListener, -+ onExit: LinkExitListener | undefined, -+ style: StyleProp | undefined, -+} -+ -+class EmbeddedEvent implements LinkEvent { -+ eventName: LinkEventName; -+ metadata: LinkEventMetadata; -+ -+ constructor(event: any) { -+ this.eventName = event.eventName -+ this.metadata = event.metadata -+ } -+} -+ -+class EmbeddedExit implements LinkExit { -+ error: LinkError | undefined; -+ metadata: LinkExitMetadata; -+ -+ constructor(event: any) { -+ this.error = event.error; -+ this.metadata = event.metadata; -+ } -+} -+ -+class EmbeddedSuccess implements LinkSuccess { -+ publicToken: string; -+ metadata: LinkSuccessMetadata; -+ -+ constructor(event: any) { -+ this.publicToken = event.publicToken; -+ this.metadata = event.metadata; -+ } -+} -+ -+export const EmbeddedLinkView: React.FC = (props) => { -+ -+ const {token, iOSPresentationStyle, onEvent, onSuccess, onExit, style} = props; -+ -+ const onEmbeddedEvent = (event: any) => { -+ -+ switch (event.nativeEvent.embeddedEventName) { -+ case 'onSuccess': { -+ if (!onSuccess) { return; } -+ const embeddedSuccess = new EmbeddedSuccess(event.nativeEvent); -+ onSuccess(embeddedSuccess); -+ break; -+ } -+ case 'onExit': { -+ if (!onExit) {return; } -+ const embeddedExit = new EmbeddedExit(event.nativeEvent); -+ onExit(embeddedExit); -+ break; -+ } -+ case 'onEvent': { -+ if (!onEvent) { return; } -+ const embeddedEvent = new EmbeddedEvent(event.nativeEvent); -+ onEvent(embeddedEvent); -+ break; -+ } -+ default: { -+ return; -+ } -+ } -+ } -+ -+ return -+}; -\ No newline at end of file -diff --git a/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/EmbeddedLinkView.web.tsx b/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/EmbeddedLinkView.web.tsx -new file mode 100644 -index 0000000..7a71609 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/EmbeddedLinkView.web.tsx -@@ -0,0 +1,5 @@ -+// EmbeddedLinkView.web.tsx is a shim file which causes web bundlers to ignore the EmbeddedLinkView.tsx file -+// which imports requireNativeComponent (causing a runtime error with react-native-web). -+// Ref - https://github.com/plaid/react-native-plaid-link-sdk/issues/564 -+import React from 'react'; -+export const EmbeddedLinkView = () => null; -diff --git a/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/NativeEmbeddedLinkView.tsx b/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/NativeEmbeddedLinkView.tsx -new file mode 100644 -index 0000000..da05fb1 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/EmbeddedLink/NativeEmbeddedLinkView.tsx -@@ -0,0 +1,9 @@ -+import { requireNativeComponent } from 'react-native'; -+ -+// Error "Tried to register two views with the same name PLKEmbeddedView" -+// will be thrown during hot reload when any change is made to the -+// file that is calling this requireNativeComponent('PLKEmbeddedView') call. -+// Leaving this in its own file resolves this issue. -+const NativeEmbeddedLinkView = requireNativeComponent('PLKEmbeddedView'); -+ -+export default NativeEmbeddedLinkView; -\ No newline at end of file -diff --git a/node_modules/react-native-plaid-link-sdk/src/PlaidLink.tsx b/node_modules/react-native-plaid-link-sdk/src/PlaidLink.tsx -new file mode 100644 -index 0000000..b35c06f ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/PlaidLink.tsx -@@ -0,0 +1,117 @@ -+import React, { useEffect } from 'react'; -+import { NativeEventEmitter, Platform, TouchableOpacity } from 'react-native'; -+import { -+ LinkError, -+ LinkEventListener, -+ LinkExit, -+ LinkIOSPresentationStyle, -+ LinkLogLevel, -+ LinkSuccess, -+ PlaidLinkComponentProps, -+ PlaidLinkProps, -+} from './Types'; -+import RNLinksdkAndroid from './fabric/NativePlaidLinkModuleAndroid'; -+import RNLinksdkiOS from './fabric/NativePlaidLinkModuleiOS'; -+ -+const RNLinksdk = (Platform.OS === 'android' ? RNLinksdkAndroid : RNLinksdkiOS) ?? undefined; -+ -+/** -+ * A hook that registers a listener on the Plaid emitter for the 'onEvent' type. -+ * The listener is cleaned up when this view is unmounted -+ * -+ * @param linkEventListener the listener to call -+ */ -+export const usePlaidEmitter = (linkEventListener: LinkEventListener) => { -+ useEffect(() => { -+ const emitter = new NativeEventEmitter(RNLinksdk); -+ const listener = emitter.addListener('onEvent', linkEventListener); -+ // Clean up after this effect: -+ return function cleanup() { -+ listener.remove(); -+ }; -+ }, []); -+}; -+ -+export const openLink = async (props: PlaidLinkProps) => { -+ let config = props.tokenConfig; -+ let noLoadingState = config.noLoadingState ?? false; -+ -+ if (Platform.OS === 'android') { -+ if (RNLinksdkAndroid === null) { -+ throw new Error('[react-native-plaid-link-sdk] RNLinksdkAndroid is not defined'); -+ } -+ -+ RNLinksdkAndroid.startLinkActivityForResult( -+ config.token, -+ noLoadingState, -+ config.logLevel ?? LinkLogLevel.ERROR, -+ // @ts-ignore we use Object type in the spec file as it maps to NSDictionary and ReadableMap -+ (result: LinkSuccess) => { -+ if (props.onSuccess != null) { -+ props.onSuccess(result); -+ } -+ }, -+ (result: LinkExit) => { -+ if (props.onExit != null) { -+ if (result.error != null && result.error.displayMessage != null) { -+ //TODO(RNSDK-118): Remove errorDisplayMessage field in next major update. -+ result.error.errorDisplayMessage = result.error.displayMessage; -+ } -+ props.onExit(result); -+ } -+ }, -+ ); -+ } else { -+ if (RNLinksdkiOS === null) { -+ throw new Error('[react-native-plaid-link-sdk] RNLinksdkiOS is not defined'); -+ } -+ -+ RNLinksdkiOS.create(config.token, noLoadingState); -+ -+ let presentFullScreen = -+ props.iOSPresentationStyle == LinkIOSPresentationStyle.FULL_SCREEN; -+ -+ RNLinksdkiOS.open( -+ presentFullScreen, -+ // @ts-ignore we use Object type in the spec file as it maps to NSDictionary and ReadableMap -+ (result: LinkSuccess) => { -+ if (props.onSuccess != null) { -+ props.onSuccess(result); -+ } -+ }, -+ (error: LinkError, result: LinkExit) => { -+ if (props.onExit != null) { -+ if (error) { -+ var data = result || {}; -+ data.error = error; -+ props.onExit(data); -+ } else { -+ props.onExit(result); -+ } -+ } -+ }, -+ ); -+ } -+}; -+ -+export const dismissLink = () => { -+ if (Platform.OS === 'ios') { -+ if (RNLinksdkiOS === null) { -+ throw new Error('[react-native-plaid-link-sdk] RNLinksdkiOS is not defined'); -+ } -+ -+ RNLinksdkiOS.dismiss(); -+ } -+}; -+ -+export const PlaidLink = (props: PlaidLinkComponentProps) => { -+ function onPress() { -+ props.onPress?.(); -+ openLink(props); -+ } -+ -+ return ( -+ // @ts-ignore some types directories misconfiguration -+ {props.children} -+ ); -+}; -diff --git a/node_modules/react-native-plaid-link-sdk/src/Types.ts b/node_modules/react-native-plaid-link-sdk/src/Types.ts -new file mode 100644 -index 0000000..a7d30c6 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/Types.ts -@@ -0,0 +1,550 @@ -+interface CommonPlaidLinkOptions { -+ logLevel?: LinkLogLevel; -+ extras?: Record; -+} -+ -+export type LinkTokenConfiguration = (CommonPlaidLinkOptions & { -+ token: string; -+ // A `Bool` indicating that Link should skip displaying a loading animation until the Link UI is fully loaded. -+ // This can be used to display custom loading UI while Link content is loading (and will skip any initial loading UI in Link). -+ // Note: Dismiss custom loading UI on the OPEN & EXIT events. -+ // -+ // Note: This should be set to `true` when setting the `eu_config.headless` field in /link/token/create requests to `true`. -+ // For reference, see https://plaid.com/docs/api/tokens/#link-token-create-request-eu-config-headless -+ noLoadingState?: boolean; -+}); -+ -+export enum LinkLogLevel { -+ DEBUG="debug", -+ INFO="info", -+ WARN="warn", -+ ERROR="error", -+} -+ -+export enum PlaidEnvironment { -+ PRODUCTION = 'production', -+ DEVELOPMENT = 'development', -+ SANDBOX = 'sandbox', -+} -+ -+export enum PlaidProduct { -+ ASSETS="assets", -+ AUTH="auth", -+ DEPOSIT_SWITCH="deposit_switch", -+ IDENTITY="identity", -+ INCOME="income", -+ INVESTMENTS="investments", -+ LIABILITIES="liabilities", -+ LIABILITIES_REPORT="liabilities_report", -+ PAYMENT_INITIATION="payment_initiation", -+ TRANSACTIONS="transactions", -+} -+ -+export enum LinkAccountType { -+ CREDIT = 'credit', -+ DEPOSITORY = 'depository', -+ INVESTMENT = 'investment', -+ LOAN = 'loan', -+ OTHER = 'other', -+} -+ -+export enum LinkAccountSubtypes { -+ ALL = 'all', -+ CREDIT_CARD = 'credit card', -+ PAYPAL = 'paypal', -+ AUTO = 'auto', -+ BUSINESS = 'business', -+ COMMERCIAL = 'commercial', -+ CONSTRUCTION = 'construction', -+ CONSUMER = 'consumer', -+ HOME_EQUITY = 'home equity', -+ LINE_OF_CREDIT = 'line of credit', -+ LOAN = 'loan', -+ MORTGAGE = 'mortgage', -+ OVERDRAFT = 'overdraft', -+ STUDENT = 'student', -+ CASH_MANAGEMENT = 'cash management', -+ CD = 'cd', -+ CHECKING = 'checking', -+ EBT = 'ebt', -+ HSA = 'hsa', -+ MONEY_MARKET = 'money market', -+ PREPAID = 'prepaid', -+ SAVINGS = 'savings', -+ FOUR_0_1_A = '401a', -+ FOUR_0_1_K = '401k', -+ FOUR_0_3_B = '403B', -+ FOUR_5_7_B = '457b', -+ FIVE_2_9 = '529', -+ BROKERAGE = 'brokerage', -+ CASH_ISA = 'cash isa', -+ EDUCATION_SAVINGS_ACCOUNT = 'education savings account', -+ FIXED_ANNUNITY = 'fixed annuity', -+ GIC = 'gic', -+ HEALTH_REIMBURSEMENT_ARRANGEMENT = 'health reimbursement arrangement', -+ IRA = 'ira', -+ ISA = 'isa', -+ KEOGH = 'keogh', -+ LIF = 'lif', -+ LIRA = 'lira', -+ LRIF = 'lrif', -+ LRSP = 'lrsp', -+ MUTUAL_FUND = 'mutual fund', -+ NON_TAXABLE_BROKERAGE_ACCOUNT = 'non-taxable brokerage account', -+ PENSION = 'pension', -+ PLAN = 'plan', -+ PRIF = 'prif', -+ PROFIT_SHARING_PLAN = 'profit sharing plan', -+ RDSP = 'rdsp', -+ RESP = 'resp', -+ RETIREMENT = 'retirement', -+ RLIF = 'rlif', -+ ROTH_401K = 'roth 401k', -+ ROTH = 'roth', -+ RRIF = 'rrif', -+ RRSP = 'rrsp', -+ SARSEP = 'sarsep', -+ SEP_IRA = 'sep ira', -+ SIMPLE_IRA = 'simple ira', -+ SIPP = 'sipp', -+ STOCK_PLAN = 'stock plan', -+ TFSA = 'tfsa', -+ THRIFT_SAVINGS_PLAN = 'thrift savings plan', -+ TRUST = 'trust', -+ UGMA = 'ugma', -+ UTMA = 'utma', -+ VARIABLE_ANNUITY = 'variable annuity' -+} -+ -+export interface LinkAccountSubtype { -+} -+ -+export class LinkAccountSubtypeCredit implements LinkAccountSubtype { -+ public static readonly ALL = new LinkAccountSubtypeCredit(LinkAccountType.CREDIT, LinkAccountSubtypes.ALL); -+ public static readonly CREDIT_CARD = new LinkAccountSubtypeCredit(LinkAccountType.CREDIT, LinkAccountSubtypes.CREDIT_CARD); -+ public static readonly PAYPAL = new LinkAccountSubtypeCredit(LinkAccountType.CREDIT, LinkAccountSubtypes.PAYPAL); -+ -+ private constructor(public readonly type: LinkAccountType, public readonly subtype: LinkAccountSubtype) { } -+} -+ -+export class LinkAccountSubtypeDepository implements LinkAccountSubtype { -+ public static readonly ALL = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.ALL); -+ public static readonly CASH_MANAGEMENT = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.CASH_MANAGEMENT); -+ public static readonly CD = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.CD); -+ public static readonly CHECKING = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.CHECKING); -+ public static readonly EBT = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.EBT); -+ public static readonly HSA = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.HSA); -+ public static readonly MONEY_MARKET = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.MONEY_MARKET); -+ public static readonly PAYPAL = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.PAYPAL); -+ public static readonly PREPAID = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.PREPAID); -+ public static readonly SAVINGS = new LinkAccountSubtypeDepository(LinkAccountType.DEPOSITORY, LinkAccountSubtypes.SAVINGS); -+ -+ private constructor(public readonly type: LinkAccountType, public readonly subtype: LinkAccountSubtype) { } -+} -+ -+export class LinkAccountSubtypeInvestment implements LinkAccountSubtype { -+ public static readonly ALL = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.ALL); -+ public static readonly BROKERAGE = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.BROKERAGE); -+ public static readonly CASH_ISA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.CASH_ISA); -+ public static readonly EDUCATION_SAVINGS_ACCOUNT = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.EDUCATION_SAVINGS_ACCOUNT); -+ public static readonly FIXED_ANNUNITY = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FIXED_ANNUNITY); -+ public static readonly GIC = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.GIC); -+ public static readonly HEALTH_REIMBURSEMENT_ARRANGEMENT = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.HEALTH_REIMBURSEMENT_ARRANGEMENT); -+ public static readonly HSA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.HSA); -+ public static readonly INVESTMENT_401A = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FOUR_0_1_A); -+ public static readonly INVESTMENT_401K = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FOUR_0_1_K); -+ public static readonly INVESTMENT_403B = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FOUR_0_3_B); -+ public static readonly INVESTMENT_457B = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FOUR_5_7_B); -+ public static readonly INVESTMENT_529 = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.FIVE_2_9); -+ public static readonly IRA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.IRA); -+ public static readonly ISA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.ISA); -+ public static readonly KEOGH = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.KEOGH); -+ public static readonly LIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.LIF); -+ public static readonly LIRA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.LIRA); -+ public static readonly LRIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.LRIF); -+ public static readonly LRSP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.LRSP); -+ public static readonly MUTUAL_FUND = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.MUTUAL_FUND); -+ public static readonly NON_TAXABLE_BROKERAGE_ACCOUNT = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.NON_TAXABLE_BROKERAGE_ACCOUNT); -+ public static readonly PENSION = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.PENSION); -+ public static readonly PLAN = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.PLAN); -+ public static readonly PRIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.PRIF); -+ public static readonly PROFIT_SHARING_PLAN = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.PROFIT_SHARING_PLAN); -+ public static readonly RDSP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RDSP); -+ public static readonly RESP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RESP); -+ public static readonly RETIREMENT = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RETIREMENT); -+ public static readonly RLIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RLIF); -+ public static readonly ROTH = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.ROTH); -+ public static readonly ROTH_401K = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.ROTH_401K); -+ public static readonly RRIF = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RRIF); -+ public static readonly RRSP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.RRSP); -+ public static readonly SARSEP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.SARSEP); -+ public static readonly SEP_IRA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.SEP_IRA); -+ public static readonly SIMPLE_IRA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.SIMPLE_IRA); -+ public static readonly SIIP = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.SIPP); -+ public static readonly STOCK_PLAN = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.STOCK_PLAN); -+ public static readonly TFSA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.TFSA); -+ public static readonly THRIFT_SAVINGS_PLAN = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.THRIFT_SAVINGS_PLAN); -+ public static readonly TRUST = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.TRUST); -+ public static readonly UGMA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.UGMA); -+ public static readonly UTMA = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.UTMA); -+ public static readonly VARIABLE_ANNUITY = new LinkAccountSubtypeInvestment(LinkAccountType.INVESTMENT, LinkAccountSubtypes.VARIABLE_ANNUITY); -+ -+ private constructor(public readonly type: LinkAccountType, public readonly subtype: LinkAccountSubtype) { } -+} -+ -+export class LinkAccountSubtypeLoan implements LinkAccountSubtype { -+ public static readonly ALL = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.ALL); -+ public static readonly AUTO = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.AUTO); -+ public static readonly BUSINESS = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.BUSINESS); -+ public static readonly COMMERCIAL = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.COMMERCIAL); -+ public static readonly CONSTRUCTION = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.CONSTRUCTION); -+ public static readonly CONSUMER = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.CONSUMER); -+ public static readonly HOME_EQUITY = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.HOME_EQUITY); -+ public static readonly LINE_OF_CREDIT = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.LINE_OF_CREDIT); -+ public static readonly LOAN = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.LOAN); -+ public static readonly MORTGAGE = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.MORTGAGE); -+ public static readonly OVERDRAFT = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.OVERDRAFT); -+ public static readonly STUDENT = new LinkAccountSubtypeLoan(LinkAccountType.CREDIT, LinkAccountSubtypes.STUDENT); -+ -+ private constructor(public readonly type: LinkAccountType, public readonly subtype: LinkAccountSubtype) { } -+} -+ -+export class LinkAccountSubtypeUnknown implements LinkAccountSubtype { -+ constructor(public readonly type: string, public readonly subtype: string) { } -+} -+ -+export interface LinkSuccess { -+ publicToken: string; -+ metadata: LinkSuccessMetadata; -+} -+ -+export interface LinkSuccessMetadata { -+ institution?: LinkInstitution; -+ accounts: LinkAccount[]; -+ linkSessionId: string; -+ metadataJson?: string; -+} -+ -+export interface LinkAccount { -+ id: string; -+ name?: string; -+ mask?: string; -+ type: LinkAccountType; -+ subtype: LinkAccountSubtype; -+ verificationStatus?: LinkAccountVerificationStatus; -+} -+ -+export enum LinkAccountVerificationStatus { -+ PENDING_AUTOMATIC_VERIFICATION = 'pending_automatic_verification', -+ PENDING_MANUAL_VERIFICATION = 'pending_manual_verification', -+ MANUALLY_VERIFIED = 'manually_verified', -+} -+ -+export interface LinkInstitution { -+ id: string; -+ name: string; -+} -+ -+export interface LinkExit { -+ error?: LinkError; -+ metadata: LinkExitMetadata; -+} -+ -+export interface LinkExitMetadata { -+ status?: LinkExitMetadataStatus; -+ institution?: LinkInstitution; -+ linkSessionId: string; -+ requestId: string; -+ metadataJson?: string; -+} -+ -+export enum LinkExitMetadataStatus { -+ CONNECTED = 'connected', -+ CHOOSE_DEVICE = 'choose_device', -+ REQUIRES_ACCOUNT_SELECTION = 'requires_account_selection', -+ REQUIRES_CODE = 'requires_code', -+ REQUIRES_CREDENTIALS = 'requires_credentials', -+ REQUIRES_EXTERNAL_ACTION = 'requires_external_action', -+ REQUIRES_OAUTH = 'requires_oauth', -+ REQUIRES_QUESTIONS = 'requires_questions', -+ REQUIRES_RECAPTCHA = 'requires_recaptcha', -+ REQUIRES_SELECTIONS = 'requires_selections', -+ REQUIRES_DEPOSIT_SWITCH_ALLOCATION_CONFIGURATION = 'requires_deposit_switch_allocation_configuration', -+ REQUIRES_DEPOSIT_SWITCH_ALLOCATION_SELECTION = 'requires_deposit_switch_allocation_selection', -+} -+ -+export interface LinkError { -+ errorCode: LinkErrorCode; -+ errorType: LinkErrorType; -+ errorMessage: string; -+ /** @deprecated DO NOT USE, data not guaranteed. Use `displayMessage` instead */ -+ errorDisplayMessage?: string; -+ displayMessage?: string; -+ errorJson?: string; -+} -+ -+export enum LinkErrorCode { -+ // ITEM_ERROR -+ INVALID_CREDENTIALS = "INVALID_CREDENTIALS", -+ INVALID_MFA = "INVALID_MFA", -+ ITEM_LOGIN_REQUIRED = "ITEM_LOGIN_REQUIRED", -+ INSUFFICIENT_CREDENTIALS = "INSUFFICIENT_CREDENTIALS", -+ ITEM_LOCKED = "ITEM_LOCKED", -+ USER_SETUP_REQUIRED = "USER_SETUP_REQUIRED", -+ MFA_NOT_SUPPORTED = "MFA_NOT_SUPPORTED", -+ INVALID_SEND_METHOD = "INVALID_SEND_METHOD", -+ NO_ACCOUNTS = "NO_ACCOUNTS", -+ ITEM_NOT_SUPPORTED = "ITEM_NOT_SUPPORTED", -+ TOO_MANY_VERIFICATION_ATTEMPTS = "TOO_MANY_VERIFICATION_ATTEMPTS", -+ -+ INVALD_UPDATED_USERNAME = "INVALD_UPDATED_USERNAME", -+ INVALID_UPDATED_USERNAME = "INVALID_UPDATED_USERNAME", -+ -+ ITEM_NO_ERROR = "ITEM_NO_ERROR", -+ item_no_error = "item-no-error", -+ NO_AUTH_ACCOUNTS = "NO_AUTH_ACCOUNTS", -+ NO_INVESTMENT_ACCOUNTS = "NO_INVESTMENT_ACCOUNTS", -+ NO_INVESTMENT_AUTH_ACCOUNTS = "NO_INVESTMENT_AUTH_ACCOUNTS", -+ NO_LIABILITY_ACCOUNTS = "NO_LIABILITY_ACCOUNTS", -+ PRODUCTS_NOT_SUPPORTED = "PRODUCTS_NOT_SUPPORTED", -+ ITEM_NOT_FOUND = "ITEM_NOT_FOUND", -+ ITEM_PRODUCT_NOT_READY = "ITEM_PRODUCT_NOT_READY", -+ -+ // INSTITUTION_ERROR -+ INSTITUTION_DOWN = "INSTITUTION_DOWN", -+ INSTITUTION_NOT_RESPONDING = "INSTITUTION_NOT_RESPONDING", -+ INSTITUTION_NOT_AVAILABLE = "INSTITUTION_NOT_AVAILABLE", -+ INSTITUTION_NO_LONGER_SUPPORTED = "INSTITUTION_NO_LONGER_SUPPORTED", -+ -+ // API_ERROR -+ INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR", -+ PLANNED_MAINTENANCE = "PLANNED_MAINTENANCE", -+ -+ // ASSET_REPORT_ERROR -+ PRODUCT_NOT_ENABLED = "PRODUCT_NOT_ENABLED", -+ DATA_UNAVAILABLE = "DATA_UNAVAILABLE", -+ ASSET_PRODUCT_NOT_READY = "ASSET_PRODUCT_NOT_READY", -+ ASSET_REPORT_GENERATION_FAILED = "ASSET_REPORT_GENERATION_FAILED", -+ INVALID_PARENT = "INVALID_PARENT", -+ INSIGHTS_NOT_ENABLED = "INSIGHTS_NOT_ENABLED", -+ INSIGHTS_PREVIOUSLY_NOT_ENABLED = "INSIGHTS_PREVIOUSLY_NOT_ENABLED", -+ -+ // BANK_TRANSFER_ERROR -+ BANK_TRANSFER_LIMIT_EXCEEDED = "BANK_TRANSFER_LIMIT_EXCEEDED", -+ BANK_TRANSFER_MISSING_ORIGINATION_ACCOUNT = "BANK_TRANSFER_MISSING_ORIGINATION_ACCOUNT", -+ BANK_TRANSFER_INVALID_ORIGINATION_ACCOUNT = "BANK_TRANSFER_INVALID_ORIGINATION_ACCOUNT", -+ BANK_TRANSFER_ACCOUNT_BLOCKED = "BANK_TRANSFER_ACCOUNT_BLOCKED", -+ BANK_TRANSFER_INSUFFICIENT_FUNDS = "BANK_TRANSFER_INSUFFICIENT_FUNDS", -+ BANK_TRANSFER_NOT_CANCELLABLE = "BANK_TRANSFER_NOT_CANCELLABLE", -+ BANK_TRANSFER_UNSUPPORTED_ACCOUNT_TYPE = "BANK_TRANSFER_UNSUPPORTED_ACCOUNT_TYPE", -+ BANK_TRANSFER_UNSUPPORTED_ENVIRONMENT = "BANK_TRANSFER_UNSUPPORTED_ENVIRONMENT", -+ -+ // SANDBOX_ERROR -+ SANDBOX_PRODUCT_NOT_ENABLED = "SANDBOX_PRODUCT_NOT_ENABLED", -+ SANDBOX_WEBHOOK_INVALID = "SANDBOX_WEBHOOK_INVALID", -+ SANDBOX_BANK_TRANSFER_EVENT_TRANSITION_INVALID = "SANDBOX_BANK_TRANSFER_EVENT_TRANSITION_INVALID", -+ -+ // INVALID_REQUEST -+ MISSING_FIELDS = "MISSING_FIELDS", -+ UNKNOWN_FIELDS = "UNKNOWN_FIELDS", -+ INVALID_FIELD = "INVALID_FIELD", -+ INCOMPATIBLE_API_VERSION = "INCOMPATIBLE_API_VERSION", -+ INVALID_BODY = "INVALID_BODY", -+ INVALID_HEADERS = "INVALID_HEADERS", -+ NOT_FOUND = "NOT_FOUND", -+ NO_LONGER_AVAILABLE = "NO_LONGER_AVAILABLE", -+ SANDBOX_ONLY = "SANDBOX_ONLY", -+ INVALID_ACCOUNT_NUMBER = "INVALID_ACCOUNT_NUMBER", -+ -+ // INVALID_INPUT -+ // From above ITEM_LOGIN_REQUIRED = "INVALID_CREDENTIALS", -+ INCORRECT_DEPOSIT_AMOUNTS = "INCORRECT_DEPOSIT_AMOUNTS", -+ UNAUTHORIZED_ENVIRONMENT = "UNAUTHORIZED_ENVIRONMENT", -+ INVALID_PRODUCT = "INVALID_PRODUCT", -+ UNAUTHORIZED_ROUTE_ACCESS = "UNAUTHORIZED_ROUTE_ACCESS", -+ DIRECT_INTEGRATION_NOT_ENABLED = "DIRECT_INTEGRATION_NOT_ENABLED", -+ INVALID_API_KEYS = "INVALID_API_KEYS", -+ INVALID_ACCESS_TOKEN = "INVALID_ACCESS_TOKEN", -+ INVALID_PUBLIC_TOKEN = "INVALID_PUBLIC_TOKEN", -+ INVALID_LINK_TOKEN = "INVALID_LINK_TOKEN", -+ INVALID_PROCESSOR_TOKEN = "INVALID_PROCESSOR_TOKEN", -+ INVALID_AUDIT_COPY_TOKEN = "INVALID_AUDIT_COPY_TOKEN", -+ INVALID_ACCOUNT_ID = "INVALID_ACCOUNT_ID", -+ MICRODEPOSITS_ALREADY_VERIFIED = "MICRODEPOSITS_ALREADY_VERIFIED", -+ -+ // INVALID_RESULT -+ PLAID_DIRECT_ITEM_IMPORT_RETURNED_INVALID_MFA = "PLAID_DIRECT_ITEM_IMPORT_RETURNED_INVALID_MFA", -+ -+ // RATE_LIMIT_EXCEEDED -+ ACCOUNTS_LIMIT = "ACCOUNTS_LIMIT", -+ ADDITION_LIMIT = "ADDITION_LIMIT", -+ AUTH_LIMIT = "AUTH_LIMIT", -+ BALANCE_LIMIT = "BALANCE_LIMIT", -+ IDENTITY_LIMIT = "IDENTITY_LIMIT", -+ ITEM_GET_LIMIT = "ITEM_GET_LIMIT", -+ RATE_LIMIT = "RATE_LIMIT", -+ TRANSACTIONS_LIMIT = "TRANSACTIONS_LIMIT", -+ -+ // RECAPTCHA_ERROR -+ RECAPTCHA_REQUIRED = "RECAPTCHA_REQUIRED", -+ RECAPTCHA_BAD = "RECAPTCHA_BAD", -+ -+ // OAUTH_ERROR -+ INCORRECT_OAUTH_NONCE = "INCORRECT_OAUTH_NONCE", -+ OAUTH_STATE_ID_ALREADY_PROCESSED = "OAUTH_STATE_ID_ALREADY_PROCESSED", -+} -+ -+export enum LinkErrorType { -+ BANK_TRANSFER = 'BANK_TRANSFER_ERROR', -+ INVALID_REQUEST = 'INVALID_REQUEST', -+ INVALID_RESULT = 'INVALID_RESULT', -+ INVALID_INPUT = 'INVALID_INPUT', -+ INSTITUTION_ERROR = 'INSTITUTION_ERROR', -+ RATE_LIMIT_EXCEEDED = 'RATE_LIMIT_EXCEEDED', -+ API_ERROR = 'API_ERROR', -+ ITEM_ERROR = 'ITEM_ERROR', -+ AUTH_ERROR = 'AUTH_ERROR', -+ ASSET_REPORT_ERROR = 'ASSET_REPORT_ERROR', -+ SANDBOX_ERROR = 'SANDBOX_ERROR', -+ RECAPTCHA_ERROR = 'RECAPTCHA_ERROR', -+ OAUTH_ERROR = 'OAUTH_ERROR', -+} -+ -+export type LinkEventListener = (linkEvent: LinkEvent) => void -+ -+export interface LinkEvent { -+ eventName: LinkEventName; -+ metadata: LinkEventMetadata; -+} -+ -+export interface LinkEventMetadata { -+ accountNumberMask?: string; -+ linkSessionId: string; -+ mfaType?: string; -+ requestId?: string; -+ viewName: LinkEventViewName; -+ errorCode?: string; -+ errorMessage?: string; -+ errorType?: string; -+ exitStatus?: string; -+ institutionId?: string; -+ institutionName?: string; -+ institutionSearchQuery?: string; -+ isUpdateMode?: string; -+ matchReason?: string; -+ // see possible values for selection at https://plaid.com/docs/link/web/#link-web-onevent-selection -+ selection?: null | string; -+ timestamp: string; -+} -+ -+export enum LinkEventName { -+ BANK_INCOME_INSIGHTS_COMPLETED = "BANK_INCOME_INSIGHTS_COMPLETED", -+ CLOSE_OAUTH = 'CLOSE_OAUTH', -+ ERROR = 'ERROR', -+ EXIT = 'EXIT', -+ FAIL_OAUTH = 'FAIL_OAUTH', -+ HANDOFF = 'HANDOFF', -+ IDENTITY_VERIFICATION_START_STEP = 'IDENTITY_VERIFICATION_START_STEP', -+ IDENTITY_VERIFICATION_PASS_STEP = 'IDENTITY_VERIFICATION_PASS_STEP', -+ IDENTITY_VERIFICATION_FAIL_STEP = 'IDENTITY_VERIFICATION_FAIL_STEP', -+ IDENTITY_VERIFICATION_PENDING_REVIEW_STEP = 'IDENTITY_VERIFICATION_PENDING_REVIEW_STEP', -+ IDENTITY_VERIFICATION_PENDING_REVIEW_SESSION = 'IDENTITY_VERIFICATION_PENDING_REVIEW_SESSION', -+ IDENTITY_VERIFICATION_CREATE_SESSION = 'IDENTITY_VERIFICATION_CREATE_SESSION', -+ IDENTITY_VERIFICATION_RESUME_SESSION = 'IDENTITY_VERIFICATION_RESUME_SESSION', -+ IDENTITY_VERIFICATION_PASS_SESSION = 'IDENTITY_VERIFICATION_PASS_SESSION', -+ IDENTITY_VERIFICATION_FAIL_SESSION = 'IDENTITY_VERIFICATION_FAIL_SESSION', -+ IDENTITY_VERIFICATION_OPEN_UI = 'IDENTITY_VERIFICATION_OPEN_UI', -+ IDENTITY_VERIFICATION_RESUME_UI = 'IDENTITY_VERIFICATION_RESUME_UI', -+ IDENTITY_VERIFICATION_CLOSE_UI = 'IDENTITY_VERIFICATION_CLOSE_UI', -+ MATCHED_CONSENT = 'MATCHED_CONSENT', -+ MATCHED_SELECT_INSTITUTION = 'MATCHED_SELECT_INSTITUTION', -+ MATCHED_SELECT_VERIFY_METHOD = 'MATCHED_SELECT_VERIFY_METHOD', -+ OPEN = 'OPEN', -+ OPEN_MY_PLAID = 'OPEN_MY_PLAID', -+ OPEN_OAUTH = 'OPEN_OAUTH', -+ SEARCH_INSTITUTION = 'SEARCH_INSTITUTION', -+ SELECT_DEGRADED_INSTITUTION = 'SELECT_DEGRADED_INSTITUTION', -+ SELECT_DOWN_INSTITUTION = 'SELECT_DOWN_INSTITUTION', -+ SELECT_FILTERED_INSTITUTION = 'SELECT_FILTERED_INSTITUTION', -+ SELECT_INSTITUTION = 'SELECT_INSTITUTION', -+ SELECT_BRAND = 'SELECT_BRAND', -+ SELECT_AUTH_TYPE = 'SELECT_AUTH_TYPE', -+ SUBMIT_ACCOUNT_NUMBER = 'SUBMIT_ACCOUNT_NUMBER', -+ SUBMIT_DOCUMENTS = 'SUBMIT_DOCUMENTS', -+ SUBMIT_DOCUMENTS_SUCCESS = 'SUBMIT_DOCUMENTS_SUCCESS', -+ SUBMIT_DOCUMENTS_ERROR = 'SUBMIT_DOCUMENTS_ERROR', -+ SUBMIT_ROUTING_NUMBER = 'SUBMIT_ROUTING_NUMBER', -+ VIEW_DATA_TYPES = 'VIEW_DATA_TYPES', -+ SUBMIT_PHONE = 'SUBMIT_PHONE', -+ SKIP_SUBMIT_PHONE = 'SKIP_SUBMIT_PHONE', -+ VERIFY_PHONE = 'VERIFY_PHONE', -+ SUBMIT_CREDENTIALS = 'SUBMIT_CREDENTIALS', -+ SUBMIT_MFA = 'SUBMIT_MFA', -+ TRANSITION_VIEW = 'TRANSITION_VIEW', -+ CONNECT_NEW_INSTITUTION = 'CONNECT_NEW_INSTITUTION', -+} -+ -+export enum LinkEventViewName { -+ ACCEPT_TOS = 'ACCEPT_TOS', -+ CONNECTED = 'CONNECTED', -+ CONSENT = 'CONSENT', -+ CREDENTIAL = 'CREDENTIAL', -+ DATA_TRANSPARENCY = 'DATA_TRANSPARENCY', -+ DATA_TRANSPARENCY_CONSENT = 'DATA_TRANSPARENCY_CONSENT', -+ DOCUMENTARY_VERIFICATION = 'DOCUMENTARY_VERIFICATION', -+ ERROR = 'ERROR', -+ EXIT = 'EXIT', -+ KYC_CHECK = 'KYC_CHECK', -+ SELFIE_CHECK = 'SELFIE_CHECK', -+ LOADING = 'LOADING', -+ MATCHED_CONSENT = 'MATCHED_CONSENT', -+ MATCHED_CREDENTIAL = 'MATCHED_CREDENTIAL', -+ MATCHED_MFA = 'MATCHED_MFA', -+ MFA = 'MFA', -+ NUMBERS = 'NUMBERS', -+ NUMBERS_SELECT_INSTITUTION = 'NUMBERS_SELECT_INSTITUTION', -+ OAUTH = 'OAUTH', -+ RECAPTCHA = 'RECAPTCHA', -+ RISK_CHECK = 'RISK_CHECK', -+ SCREENING = 'SCREENING', -+ SELECT_ACCOUNT = 'SELECT_ACCOUNT', -+ SELECT_AUTH_TYPE = 'SELECT_AUTH_TYPE', -+ SUBMIT_PHONE = 'SUBMIT_PHONE', -+ VERIFY_PHONE = 'VERIFY_PHONE', -+ SELECT_SAVED_INSTITUTION = 'SELECT_SAVED_INSTITUTION', -+ SELECT_SAVED_ACCOUNT = 'SELECT_SAVED_ACCOUNT', -+ SELECT_BRAND = 'SELECT_BRAND', -+ SELECT_INSTITUTION = 'SELECT_INSTITUTION', -+ SUBMIT_DOCUMENTS = 'SUBMIT_DOCUMENTS', -+ SUBMIT_DOCUMENTS_SUCCESS = 'SUBMIT_DOCUMENTS_SUCCESS', -+ SUBMIT_DOCUMENTS_ERROR = 'SUBMIT_DOCUMENTS_ERROR', -+ UPLOAD_DOCUMENTS = 'UPLOAD_DOCUMENTS', -+ VERIFY_SMS = 'VERIFY_SMS', -+} -+ -+/// Methods to present Link on iOS. -+/// FULL_SCREEN is the converts to UIModalPresentationOverFullScreen on the native side. -+/// MODAL will use the default presentation style for iOS which is UIModalPresentationAutomatic. -+export enum LinkIOSPresentationStyle { -+ FULL_SCREEN = 'FULL_SCREEN', -+ MODAL = 'MODAL' -+} -+ -+export type LinkSuccessListener = (LinkSuccess: LinkSuccess) => void -+ -+export type LinkExitListener = (LinkExit: LinkExit) => void -+ -+export type LinkOnEventListener = (LinkEvent: LinkEvent) => void -+ -+export interface PlaidLinkProps { -+ tokenConfig: LinkTokenConfiguration -+ onSuccess: LinkSuccessListener -+ onExit?: LinkExitListener -+ iOSPresentationStyle?: LinkIOSPresentationStyle -+ logLevel?: LinkLogLevel -+ onPress?(): any -+} -+ -+export type PlaidLinkComponentProps = (PlaidLinkProps & { -+ children: React.ReactNode -+}); -diff --git a/node_modules/react-native-plaid-link-sdk/src/__tests__/Types.tests.ts b/node_modules/react-native-plaid-link-sdk/src/__tests__/Types.tests.ts -new file mode 100644 -index 0000000..2dd7a54 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/__tests__/Types.tests.ts -@@ -0,0 +1,15 @@ -+const Types = require('./../Types'); -+ -+test('test token configuration', () => { -+ const linkTokenConfiguration = { -+ token: "test-token", -+ noLoadingState: false, -+ logLevel: Types.LinkLogLevel.DEBUG, -+ extras: null, -+ }; -+ -+ expect(linkTokenConfiguration.noLoadingState).toBe(false); -+ expect(linkTokenConfiguration.token).toBe("test-token"); -+ expect(linkTokenConfiguration.logLevel).toBe(Types.LinkLogLevel.DEBUG); -+ expect(linkTokenConfiguration.extras).toBe(null); -+}); -\ No newline at end of file -diff --git a/node_modules/react-native-plaid-link-sdk/src/fabric/NativePlaidLinkModuleAndroid.ts b/node_modules/react-native-plaid-link-sdk/src/fabric/NativePlaidLinkModuleAndroid.ts -new file mode 100644 -index 0000000..d1e4062 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/fabric/NativePlaidLinkModuleAndroid.ts -@@ -0,0 +1,20 @@ -+// we use Object type because methods on the native side use NSDictionary and ReadableMap -+// and we want to stay compatible with those -+import {TurboModuleRegistry, TurboModule} from 'react-native'; -+import { Int32, UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; -+ -+export interface Spec extends TurboModule { -+ startLinkActivityForResult( -+ token: string, -+ noLoadingState: boolean, -+ logLevel: string, -+ onSuccessCallback: (result: UnsafeObject) => void, -+ onExitCallback: (result: UnsafeObject) => void -+ ): void; -+ -+ // those two are here for event emitter methods -+ addListener(eventName: string): void; -+ removeListeners(count: Int32): void; -+} -+ -+export default TurboModuleRegistry.get('PlaidAndroid'); -diff --git a/node_modules/react-native-plaid-link-sdk/src/fabric/NativePlaidLinkModuleiOS.ts b/node_modules/react-native-plaid-link-sdk/src/fabric/NativePlaidLinkModuleiOS.ts -new file mode 100644 -index 0000000..d1b3565 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/fabric/NativePlaidLinkModuleiOS.ts -@@ -0,0 +1,19 @@ -+// we use Object type because methods on the native side use NSDictionary and ReadableMap -+// and we want to stay compatible with those -+import {TurboModuleRegistry, TurboModule} from 'react-native'; -+import { Int32, UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes'; -+ -+export interface Spec extends TurboModule { -+ create(token: string, noLoadingState: boolean): void; -+ open( -+ fullScreen: boolean, -+ onSuccess: (success: UnsafeObject) => void, -+ onExit: (error: UnsafeObject, result: UnsafeObject) => void, -+ ): void; -+ dismiss(): void; -+ // those two are here for event emitter methods -+ addListener(eventName: string): void; -+ removeListeners(count: Int32): void; -+} -+ -+export default TurboModuleRegistry.get('RNLinksdk'); -diff --git a/node_modules/react-native-plaid-link-sdk/src/index.ts b/node_modules/react-native-plaid-link-sdk/src/index.ts -new file mode 100644 -index 0000000..23ef946 ---- /dev/null -+++ b/node_modules/react-native-plaid-link-sdk/src/index.ts -@@ -0,0 +1,21 @@ -+import { -+ openLink, -+ dismissLink, -+ usePlaidEmitter, -+ PlaidLink, -+} from './PlaidLink'; -+ -+export * from './Types'; -+ -+export default PlaidLink; -+ -+export { -+ PlaidLink, -+ openLink, -+ dismissLink, -+ usePlaidEmitter, -+}; -+ -+// Components -+ -+export { EmbeddedLinkView } from './EmbeddedLink/EmbeddedLinkView'; -\ No newline at end of file diff --git a/patches/react-native-reanimated+3.8.1.patch b/patches/react-native-reanimated+3.8.1+001+initial.patch similarity index 100% rename from patches/react-native-reanimated+3.8.1.patch rename to patches/react-native-reanimated+3.8.1+001+initial.patch diff --git a/patches/react-native-reanimated+3.8.1+001+fix-boost-dependency.patch b/patches/react-native-reanimated+3.8.1+002+fix-boost-dependency.patch similarity index 100% rename from patches/react-native-reanimated+3.8.1+001+fix-boost-dependency.patch rename to patches/react-native-reanimated+3.8.1+002+fix-boost-dependency.patch diff --git a/patches/react-native-reanimated+3.8.1+002+copy-state.patch b/patches/react-native-reanimated+3.8.1+003+copy-state.patch similarity index 100% rename from patches/react-native-reanimated+3.8.1+002+copy-state.patch rename to patches/react-native-reanimated+3.8.1+003+copy-state.patch diff --git a/patches/react-native-reanimated+3.8.1+003+fix-strict-mode.patch b/patches/react-native-reanimated+3.8.1+004+fix-strict-mode.patch similarity index 100% rename from patches/react-native-reanimated+3.8.1+003+fix-strict-mode.patch rename to patches/react-native-reanimated+3.8.1+004+fix-strict-mode.patch diff --git a/patches/react-native-web+0.19.12+003+image-header-support.patch b/patches/react-native-web+0.19.12+003+image-header-support.patch index 6652f0345cc4..d0a490a4ed70 100644 --- a/patches/react-native-web+0.19.12+003+image-header-support.patch +++ b/patches/react-native-web+0.19.12+003+image-header-support.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/react-native-web/dist/exports/Image/index.js b/node_modules/react-native-web/dist/exports/Image/index.js -index 9649d27..3281cc8 100644 +index 9649d27..66ef95c 100644 --- a/node_modules/react-native-web/dist/exports/Image/index.js +++ b/node_modules/react-native-web/dist/exports/Image/index.js @@ -135,7 +135,22 @@ function resolveAssetUri(source) { @@ -47,7 +47,7 @@ index 9649d27..3281cc8 100644 }); } function abortPendingRequest() { -@@ -279,10 +288,78 @@ var Image = /*#__PURE__*/React.forwardRef((props, ref) => { +@@ -279,10 +288,79 @@ var Image = /*#__PURE__*/React.forwardRef((props, ref) => { suppressHydrationWarning: true }), hiddenImage, createTintColorSVG(tintColor, filterRef.current)); }); @@ -64,24 +64,20 @@ index 9649d27..3281cc8 100644 + var _React$useState3 = React.useState(''), + blobUri = _React$useState3[0], + setBlobUri = _React$useState3[1]; -+ var request = React.useRef({ -+ cancel: () => {}, -+ source: { -+ uri: '', -+ headers: {} -+ }, -+ promise: Promise.resolve('') -+ }); ++ var request = React.useRef(null); + var onError = props.onError, + onLoadStart = props.onLoadStart, + onLoadEnd = props.onLoadEnd; + React.useEffect(() => { -+ if (!hasSourceDiff(nextSource, request.current.source)) { ++ if (request.current !== null && !hasSourceDiff(nextSource, request.current.source)) { + return; + } + + // When source changes we want to clean up any old/running requests -+ request.current.cancel(); ++ if (request.current !== null) { ++ request.current.cancel(); ++ } ++ + if (onLoadStart) { + onLoadStart(); + } @@ -96,7 +92,12 @@ index 9649d27..3281cc8 100644 + }, [nextSource, onLoadStart, onError, onLoadEnd]); + + // Cancel any request on unmount -+ React.useEffect(() => request.current.cancel, []); ++ React.useEffect(() => () => { ++ if (request.current !== null) { ++ request.current.cancel(); ++ request.current = null; ++ } ++ }, []); + var propsToPass = _objectSpread(_objectSpread({}, props), {}, { + // `onLoadStart` is called from the current component + // We skip passing it down to prevent BaseImage raising it a 2nd time diff --git a/scripts/applyPatches.sh b/scripts/applyPatches.sh index 9145629015ee..4ce023755258 100755 --- a/scripts/applyPatches.sh +++ b/scripts/applyPatches.sh @@ -11,7 +11,7 @@ source "$SCRIPTS_DIR/shellUtils.sh" function patchPackage { OS="$(uname)" if [[ "$OS" == "Darwin" || "$OS" == "Linux" ]]; then - npx patch-package --error-on-fail + npx patch-package --error-on-fail --color=always else error "Unsupported OS: $OS" exit 1 diff --git a/scripts/symbolicate-profile.ts b/scripts/symbolicate-profile.ts index a100c05029dd..a58c2894edb6 100755 --- a/scripts/symbolicate-profile.ts +++ b/scripts/symbolicate-profile.ts @@ -32,7 +32,7 @@ if (Object.keys(argsMap).length === 0 || argsMap.help !== undefined) { Logger.log('Options:'); Logger.log(' --profile= The .cpuprofile file to symbolicate'); Logger.log(' --platform= The platform for which the source map was uploaded'); - Logger.log(' --gh-token Token to use for requests send to the GitHub API. By default tries to pick up from the environment variable GITHUB_TOKEN'); + Logger.log(' --ghToken Token to use for requests send to the GitHub API. By default tries to pick up from the environment variable GITHUB_TOKEN'); Logger.log(' --help Display this help message'); process.exit(0); } @@ -53,7 +53,7 @@ if (argsMap.platform === undefined) { const githubToken = argsMap.ghToken ?? process.env.GITHUB_TOKEN; if (githubToken === undefined) { - Logger.error('No GitHub token provided. Either set a GITHUB_TOKEN environment variable or pass it using --gh-token'); + Logger.error('No GitHub token provided. Either set a GITHUB_TOKEN environment variable or pass it using --ghToken'); process.exit(1); } diff --git a/src/CONST.ts b/src/CONST.ts index 50df9118a74e..f591373a45c2 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -182,6 +182,8 @@ const CONST = { MERCHANT_NAME_MAX_LENGTH: 255, + MASKED_PAN_PREFIX: 'XXXXXXXXXXXX', + REQUEST_PREVIEW: { MAX_LENGTH: 83, }, @@ -228,6 +230,8 @@ const CONST = { ANDROID: `https://play.google.com/store/apps/details?id=${ANDROID_PACKAGE_NAME}`, IOS: 'https://apps.apple.com/us/app/expensify-cash/id1530278510', DESKTOP: `${ACTIVE_EXPENSIFY_URL}NewExpensify.dmg`, + OLD_DOT_ANDROID: 'https://play.google.com/store/apps/details?id=org.me.mobiexpensifyg&hl=en_US&pli=1', + OLD_DOT_IOS: 'https://apps.apple.com/us/app/expensify-expense-tracker/id471713959', }, DATE: { SQL_DATE_TIME: 'YYYY-MM-DD HH:mm:ss', @@ -335,6 +339,8 @@ const CONST = { VERIFICATION_MAX_ATTEMPTS: 7, STATE: { VERIFYING: 'VERIFYING', + VALIDATING: 'VALIDATING', + SETUP: 'SETUP', PENDING: 'PENDING', OPEN: 'OPEN', }, @@ -361,11 +367,9 @@ const CONST = { DEFAULT_ROOMS: 'defaultRooms', VIOLATIONS: 'violations', DUPE_DETECTION: 'dupeDetection', - REPORT_FIELDS: 'reportFields', P2P_DISTANCE_REQUESTS: 'p2pDistanceRequests', - WORKFLOWS_DELAYED_SUBMISSION: 'workflowsDelayedSubmission', + WORKFLOWS_ADVANCED_APPROVAL: 'workflowsAdvancedApproval', SPOTNANA_TRAVEL: 'spotnanaTravel', - NETSUITE_ON_NEW_EXPENSIFY: 'netsuiteOnNewExpensify', REPORT_FIELDS_FEATURE: 'reportFieldsFeature', WORKSPACE_FEEDS: 'workspaceFeeds', NETSUITE_USA_TAX: 'netsuiteUsaTax', @@ -623,6 +627,8 @@ const CONST = { SIGN_IN_FORM_WIDTH: 300, + REQUEST_CODE_DELAY: 30, + DEEPLINK_PROMPT_DENYLIST: [SCREENS.HOME, SCREENS.SIGN_IN_WITH_APPLE_DESKTOP, SCREENS.SIGN_IN_WITH_GOOGLE_DESKTOP], SIGN_IN_METHOD: { @@ -663,11 +669,13 @@ const CONST = { MEMBER: 'member', }, MAX_COUNT_BEFORE_FOCUS_UPDATE: 30, + MIN_INITIAL_REPORT_ACTION_COUNT: 15, SPLIT_REPORTID: '-2', ACTIONS: { LIMIT: 50, // OldDot Actions render getMessage from Web-Expensify/lib/Report/Action PHP files via getMessageOfOldDotReportAction in ReportActionsUtils.ts TYPE: { + ACTIONABLE_ADD_PAYMENT_CARD: 'ACTIONABLEADDPAYMENTCARD', ACTIONABLE_JOIN_REQUEST: 'ACTIONABLEJOINREQUEST', ACTIONABLE_MENTION_WHISPER: 'ACTIONABLEMENTIONWHISPER', ACTIONABLE_REPORT_MENTION_WHISPER: 'ACTIONABLEREPORTMENTIONWHISPER', @@ -840,6 +848,8 @@ const CONST = { IOU: 'iou', TASK: 'task', INVOICE: 'invoice', + }, + UNSUPPORTED_TYPE: { PAYCHECK: 'paycheck', BILL: 'bill', }, @@ -895,9 +905,17 @@ const CONST = { INDIVIDUAL: 'individual', BUSINESS: 'policy', }, + EXPORT_OPTIONS: { + EXPORT_TO_INTEGRATION: 'exportToIntegration', + MARK_AS_EXPORTED: 'markAsExported', + }, }, NEXT_STEP: { - FINISHED: 'Finished!', + ICONS: { + HOURGLASS: 'hourglass', + CHECKMARK: 'checkmark', + STOPWATCH: 'stopwatch', + }, }, COMPOSER: { MAX_LINES: 16, @@ -1203,6 +1221,8 @@ const CONST = { NOTE: 'n', }, + IMAGE_HIGH_RESOLUTION_THRESHOLD: 7000, + IMAGE_OBJECT_POSITION: { TOP: 'top', INITIAL: 'initial', @@ -1245,7 +1265,7 @@ const CONST = { MAX_AMOUNT_OF_SUGGESTIONS: 20, MAX_AMOUNT_OF_VISIBLE_SUGGESTIONS_IN_CONTAINER: 5, HERE_TEXT: '@here', - SUGGESTION_BOX_MAX_SAFE_DISTANCE: 38, + SUGGESTION_BOX_MAX_SAFE_DISTANCE: 10, BIG_SCREEN_SUGGESTION_WIDTH: 300, }, COMPOSER_MAX_HEIGHT: 125, @@ -1322,9 +1342,17 @@ const CONST = { XERO_CONFIG: { AUTO_SYNC: 'autoSync', + ENABLED: 'enabled', + REIMBURSEMENT_ACCOUNT_ID: 'reimbursementAccountID', + INVOICE_COLLECTIONS_ACCOUNT_ID: 'invoiceCollectionsAccountID', SYNC: 'sync', + SYNC_REIMBURSED_REPORTS: 'syncReimbursedReports', ENABLE_NEW_CATEGORIES: 'enableNewCategories', EXPORT: 'export', + EXPORTER: 'exporter', + BILL_DATE: 'billDate', + BILL_STATUS: 'billStatus', + NON_REIMBURSABLE_ACCOUNT: 'nonReimbursableAccount', TENANT_ID: 'tenantID', IMPORT_CUSTOMERS: 'importCustomers', IMPORT_TAX_RATES: 'importTaxRates', @@ -1379,6 +1407,7 @@ const CONST = { SYNC: 'sync', SYNC_REIMBURSED_REPORTS: 'syncReimbursedReports', REIMBURSEMENT_ACCOUNT_ID: 'reimbursementAccountID', + ENTITY: 'entity', }, SAGE_INTACCT: { @@ -2084,8 +2113,12 @@ const CONST = { NAME_USER_FRIENDLY: { netsuite: 'NetSuite', quickbooksOnline: 'Quickbooks Online', + quickbooksDesktop: 'Quickbooks Desktop', xero: 'Xero', intacct: 'Sage Intacct', + financialForce: 'FinancialForce', + billCom: 'Bill.com', + zenefits: 'Zenefits', }, SYNC_STAGE_NAME: { STARTING_IMPORT_QBO: 'startingImportQBO', @@ -2145,6 +2178,7 @@ const CONST = { ACCESS_VARIANTS: { PAID: 'paid', ADMIN: 'admin', + CONTROL: 'control', }, DEFAULT_MAX_EXPENSE_AGE: 90, DEFAULT_MAX_EXPENSE_AMOUNT: 200000, @@ -2231,6 +2265,10 @@ const CONST = { PHYSICAL: 'physical', VIRTUAL: 'virtual', }, + FREQUENCY_SETTING: { + DAILY: 'daily', + MONTHLY: 'monthly', + }, }, AVATAR_ROW_SIZE: { DEFAULT: 4, @@ -2267,8 +2305,8 @@ const CONST = { // eslint-disable-next-line max-len, no-misleading-character-class EMOJI: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu, - // eslint-disable-next-line max-len, no-misleading-character-class - EMOJIS: /[\p{Extended_Pictographic}](\u200D[\p{Extended_Pictographic}]|[\u{1F3FB}-\u{1F3FF}]|[\u{E0020}-\u{E007F}]|\uFE0F|\u20E3)*|[\u{1F1E6}-\u{1F1FF}]{2}|[#*0-9]\uFE0F?\u20E3/gu, + // eslint-disable-next-line max-len, no-misleading-character-class, no-empty-character-class + EMOJIS: /[\p{Extended_Pictographic}](\u200D[\p{Extended_Pictographic}]|[\u{1F3FB}-\u{1F3FF}]|[\u{E0020}-\u{E007F}]|\uFE0F|\u20E3)*|[\u{1F1E6}-\u{1F1FF}]{2}|[#*0-9]\uFE0F?\u20E3/du, // eslint-disable-next-line max-len, no-misleading-character-class EMOJI_SKIN_TONES: /[\u{1f3fb}-\u{1f3ff}]/gu, @@ -2332,6 +2370,8 @@ const CONST = { POLICY_ID_FROM_PATH: /\/w\/([a-zA-Z0-9]+)(\/|$)/, SHORT_MENTION: new RegExp(`@[\\w\\-\\+\\'#@]+(?:\\.[\\w\\-\\'\\+]+)*(?![^\`]*\`)`, 'gim'), + + REPORT_ID_FROM_PATH: /\/r\/(\d+)/, }, PRONOUNS: { @@ -2352,6 +2392,7 @@ const CONST = { WORKSPACE_WORKFLOWS: 'WorkspaceWorkflows', WORKSPACE_BANK_ACCOUNT: 'WorkspaceBankAccount', WORKSPACE_SETTINGS: 'WorkspaceSettings', + WORKSPACE_FEATURES: 'WorkspaceFeatures', }, get EXPENSIFY_EMAILS() { return [ @@ -2391,7 +2432,7 @@ const CONST = { this.ACCOUNT_ID.REWARDS, this.ACCOUNT_ID.STUDENT_AMBASSADOR, this.ACCOUNT_ID.SVFG, - ]; + ].filter((id) => id !== -1); }, // Emails that profile view is prohibited @@ -2450,6 +2491,7 @@ const CONST = { SETTINGS: 'settings', LEAVE_ROOM: 'leaveRoom', PRIVATE_NOTES: 'privateNotes', + EXPORT: 'export', DELETE: 'delete', MARK_AS_INCOMPLETE: 'markAsIncomplete', CANCEL_PAYMENT: 'cancelPayment', @@ -3840,6 +3882,9 @@ const CONST = { ENABLED: 'ENABLED', DISABLED: 'DISABLED', }, + STRIPE_GBP_AUTH_STATUSES: { + SUCCEEDED: 'succeeded', + }, TAB: { NEW_CHAT_TAB_ID: 'NewChatTab', NEW_CHAT: 'chat', @@ -4009,6 +4054,15 @@ const CONST = { WARNING: 'warning', }, + /** + * Constants with different types for the modifiedAmount violation + */ + MODIFIED_AMOUNT_VIOLATION_DATA: { + DISTANCE: 'distance', + CARD: 'card', + SMARTSCAN: 'smartscan', + }, + /** * Constants for types of violation names. * Defined here because they need to be referenced by the type system to generate the @@ -4052,6 +4106,14 @@ const CONST = { }, REVIEW_DUPLICATES_ORDER: ['merchant', 'category', 'tag', 'description', 'taxCode', 'billable', 'reimbursable'], + REPORT_VIOLATIONS: { + FIELD_REQUIRED: 'fieldRequired', + }, + + REPORT_VIOLATIONS_EXCLUDED_FIELDS: { + TEXT_TITLE: 'text_title', + }, + /** Context menu types */ CONTEXT_MENU_TYPES: { LINK: 'LINK', @@ -5116,6 +5178,7 @@ const CONST = { SESSION_STORAGE_KEYS: { INITIAL_URL: 'INITIAL_URL', ACTIVE_WORKSPACE_ID: 'ACTIVE_WORKSPACE_ID', + RETRY_LAZY_REFRESHED: 'RETRY_LAZY_REFRESHED', }, RESERVATION_TYPE: { @@ -5162,12 +5225,16 @@ const CONST = { REPORT: 'report', }, ACTION_TYPES: { - DONE: 'done', - PAID: 'paid', VIEW: 'view', REVIEW: 'review', + DONE: 'done', + PAID: 'paid', + }, + BULK_ACTION_TYPES: { + EXPORT: 'export', HOLD: 'hold', UNHOLD: 'unhold', + DELETE: 'delete', }, TRANSACTION_TYPE: { CASH: 'cash', @@ -5178,12 +5245,23 @@ const CONST = { ASC: 'asc', DESC: 'desc', }, - TAB: { + STATUS: { ALL: 'all', SHARED: 'shared', DRAFTS: 'drafts', FINISHED: 'finished', }, + TYPE: { + EXPENSE: 'expense', + }, + TAB: { + EXPENSE: { + ALL: 'type:expense status:all', + SHARED: 'type:expense status:shared', + DRAFTS: 'type:expense status:drafts', + FINISHED: 'type:expense status:finished', + }, + }, TABLE_COLUMNS: { RECEIPT: 'receipt', DATE: 'date', @@ -5198,13 +5276,37 @@ const CONST = { ACTION: 'action', TAX_AMOUNT: 'taxAmount', }, - BULK_ACTION_TYPES: { - DELETE: 'delete', - HOLD: 'hold', - UNHOLD: 'unhold', - SUBMIT: 'submit', - APPROVE: 'approve', - PAY: 'pay', + SYNTAX_OPERATORS: { + AND: 'and', + OR: 'or', + EQUAL_TO: 'eq', + NOT_EQUAL_TO: 'neq', + GREATER_THAN: 'gt', + GREATER_THAN_OR_EQUAL_TO: 'gte', + LOWER_THAN: 'lt', + LOWER_THAN_OR_EQUAL_TO: 'lte', + }, + SYNTAX_ROOT_KEYS: { + TYPE: 'type', + STATUS: 'status', + SORT_BY: 'sortBy', + SORT_ORDER: 'sortOrder', + }, + SYNTAX_FILTER_KEYS: { + DATE: 'date', + AMOUNT: 'amount', + EXPENSE_TYPE: 'expenseType', + CURRENCY: 'currency', + MERCHANT: 'merchant', + DESCRIPTION: 'description', + FROM: 'from', + TO: 'to', + CATEGORY: 'category', + TAG: 'tag', + TAX_RATE: 'taxRate', + CARD_ID: 'cardID', + REPORT_ID: 'reportID', + KEYWORD: 'keyword', }, }, @@ -5220,8 +5322,10 @@ const CONST = { PAYMENT_CARD_CURRENCY: { USD: 'USD', AUD: 'AUD', + GBP: 'GBP', NZD: 'NZD', }, + GBP_AUTHENTICATION_COMPLETE: '3DS-authentication-complete', SUBSCRIPTION_PRICE_FACTOR: 2, FEEDBACK_SURVEY_OPTIONS: { @@ -5243,6 +5347,7 @@ const CONST = { }, }, + MAX_LENGTH_256: 256, WORKSPACE_CARDS_LIST_LABEL_TYPE: { CURRENT_BALANCE: 'currentBalance', REMAINING_LIMIT: 'remainingLimit', @@ -5251,23 +5356,60 @@ const CONST = { EXCLUDE_FROM_LAST_VISITED_PATH: [SCREENS.NOT_FOUND, SCREENS.SAML_SIGN_IN, SCREENS.VALIDATE_LOGIN] as string[], + CANCELLATION_TYPE: { + MANUAL: 'manual', + AUTOMATIC: 'automatic', + NONE: 'none', + }, EMPTY_STATE_MEDIA: { ANIMATION: 'animation', ILLUSTRATION: 'illustration', VIDEO: 'video', }, - - UPGRADE_FEATURE_INTRO_MAPPING: [ - { - id: 'reportFields', - alias: 'report-fields', - name: 'Report Fields', - title: 'workspace.upgrade.reportFields.title', - description: 'workspace.upgrade.reportFields.description', - icon: 'Pencil', - }, - ], - + get UPGRADE_FEATURE_INTRO_MAPPING() { + return { + reportFields: { + id: 'reportFields' as const, + alias: 'report-fields', + name: 'Report Fields', + title: 'workspace.upgrade.reportFields.title' as const, + description: 'workspace.upgrade.reportFields.description' as const, + icon: 'Pencil', + }, + [this.POLICY.CONNECTIONS.NAME.NETSUITE]: { + id: this.POLICY.CONNECTIONS.NAME.NETSUITE, + alias: 'netsuite', + name: this.POLICY.CONNECTIONS.NAME_USER_FRIENDLY.netsuite, + title: `workspace.upgrade.${this.POLICY.CONNECTIONS.NAME.NETSUITE}.title` as const, + description: `workspace.upgrade.${this.POLICY.CONNECTIONS.NAME.NETSUITE}.description` as const, + icon: 'NetSuiteSquare', + }, + [this.POLICY.CONNECTIONS.NAME.SAGE_INTACCT]: { + id: this.POLICY.CONNECTIONS.NAME.SAGE_INTACCT, + alias: 'sage-intacct', + name: this.POLICY.CONNECTIONS.NAME_USER_FRIENDLY.intacct, + title: `workspace.upgrade.${this.POLICY.CONNECTIONS.NAME.SAGE_INTACCT}.title` as const, + description: `workspace.upgrade.${this.POLICY.CONNECTIONS.NAME.SAGE_INTACCT}.description` as const, + icon: 'IntacctSquare', + }, + glCodes: { + id: 'glCodes' as const, + alias: 'gl-codes', + name: 'GL codes', + title: 'workspace.upgrade.glCodes.title' as const, + description: 'workspace.upgrade.glCodes.description' as const, + icon: 'Tag', + }, + glAndPayrollCodes: { + id: 'glAndPayrollCodes' as const, + alias: 'gl-and-payroll-codes', + name: 'GL & Payroll codes', + title: 'workspace.upgrade.glAndPayrollCodes.title' as const, + description: 'workspace.upgrade.glAndPayrollCodes.description' as const, + icon: 'FolderOpen', + }, + }; + }, REPORT_FIELD_TYPES: { TEXT: 'text', DATE: 'date', @@ -5287,7 +5429,8 @@ type IOURequestType = ValueOf; type FeedbackSurveyOptionID = ValueOf, 'ID'>>; type SubscriptionType = ValueOf; +type CancellationType = ValueOf; -export type {Country, IOUAction, IOUType, RateAndUnit, OnboardingPurposeType, IOURequestType, SubscriptionType, FeedbackSurveyOptionID}; +export type {Country, IOUAction, IOUType, RateAndUnit, OnboardingPurposeType, IOURequestType, SubscriptionType, FeedbackSurveyOptionID, CancellationType}; export default CONST; diff --git a/src/Expensify.tsx b/src/Expensify.tsx index f96c51961acc..f9fd379d94ce 100644 --- a/src/Expensify.tsx +++ b/src/Expensify.tsx @@ -3,12 +3,13 @@ import React, {useCallback, useEffect, useLayoutEffect, useMemo, useRef, useStat import type {NativeEventSubscription} from 'react-native'; import {AppState, Linking, NativeModules} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import Onyx, {withOnyx} from 'react-native-onyx'; +import Onyx, {useOnyx, withOnyx} from 'react-native-onyx'; import ConfirmModal from './components/ConfirmModal'; import DeeplinkWrapper from './components/DeeplinkWrapper'; import EmojiPicker from './components/EmojiPicker/EmojiPicker'; import FocusModeNotification from './components/FocusModeNotification'; import GrowlNotification from './components/GrowlNotification'; +import RequireTwoFactorAuthenticationModal from './components/RequireTwoFactorAuthenticationModal'; import AppleAuthWrapper from './components/SignInButtons/AppleAuthWrapper'; import SplashScreenHider from './components/SplashScreenHider'; import UpdateAppModal from './components/UpdateAppModal'; @@ -19,6 +20,7 @@ import * as Report from './libs/actions/Report'; import * as User from './libs/actions/User'; import * as ActiveClientManager from './libs/ActiveClientManager'; import BootSplash from './libs/BootSplash'; +import FS from './libs/Fullstory'; import * as Growl from './libs/Growl'; import Log from './libs/Log'; import migrateOnyx from './libs/migrateOnyx'; @@ -36,6 +38,7 @@ import ONYXKEYS from './ONYXKEYS'; import PopoverReportActionContextMenu from './pages/home/report/ContextMenu/PopoverReportActionContextMenu'; import * as ReportActionContextMenu from './pages/home/report/ContextMenu/ReportActionContextMenu'; import type {Route} from './ROUTES'; +import ROUTES from './ROUTES'; import type {ScreenShareRequest, Session} from './types/onyx'; Onyx.registerLogger(({level, message}) => { @@ -100,6 +103,16 @@ function Expensify({ const [isSplashHidden, setIsSplashHidden] = useState(false); const [hasAttemptedToOpenPublicRoom, setAttemptedToOpenPublicRoom] = useState(false); const {translate} = useLocalize(); + const [account] = useOnyx(ONYXKEYS.ACCOUNT); + const [shouldShowRequire2FAModal, setShouldShowRequire2FAModal] = useState(false); + + useEffect(() => { + if (!account?.needsTwoFactorAuthSetup || account.requiresTwoFactorAuth) { + return; + } + setShouldShowRequire2FAModal(true); + }, [account?.needsTwoFactorAuthSetup, account?.requiresTwoFactorAuth]); + const [initialUrl, setInitialUrl] = useState(null); useEffect(() => { @@ -147,6 +160,9 @@ function Expensify({ // Initialize this client as being an active client ActiveClientManager.init(); + // Initialize Fullstory lib + FS.init(); + // Used for the offline indicator appearing when someone is offline const unsubscribeNetInfo = NetworkConnection.subscribeToNetInfo(); @@ -249,6 +265,16 @@ function Expensify({ /> ) : null} {focusModeNotification ? : null} + {shouldShowRequire2FAModal ? ( + { + setShouldShowRequire2FAModal(false); + Navigation.navigate(ROUTES.SETTINGS_2FA.getRoute(ROUTES.HOME)); + }} + isVisible + description={translate('twoFactorAuth.twoFactorAuthIsRequiredForAdminsDescription')} + /> + ) : null} )} diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 8abb7738289c..4bf7987f9ceb 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -134,7 +134,7 @@ const ONYXKEYS = { NVP_LAST_PAYMENT_METHOD: 'nvp_private_lastPaymentMethod', /** This NVP holds to most recent waypoints that a person has used when creating a distance expense */ - NVP_RECENT_WAYPOINTS: 'expensify_recentWaypoints', + NVP_RECENT_WAYPOINTS: 'nvp_expensify_recentWaypoints', /** This NVP contains the choice that the user made on the engagement modal */ NVP_INTRO_SELECTED: 'nvp_introSelected', @@ -350,6 +350,9 @@ const ONYXKEYS = { /** Indicates whether we should store logs or not */ SHOULD_STORE_LOGS: 'shouldStoreLogs', + /** Indicates whether we should mask fragile user data while exporting onyx state or not */ + SHOULD_MASK_ONYX_STATE: 'shouldMaskOnyxState', + /** Stores new group chat draft */ NEW_GROUP_CHAT_DRAFT: 'newGroupChatDraft', @@ -376,9 +379,17 @@ const ONYXKEYS = { /** Stores info during review duplicates flow */ REVIEW_DUPLICATES: 'reviewDuplicates', + /** Stores the last export method for policy */ + LAST_EXPORT_METHOD: 'lastExportMethod', + /** Stores the information about the state of issuing a new card */ ISSUE_NEW_EXPENSIFY_CARD: 'issueNewExpensifyCard', + NVP_PRIVATE_CANCELLATION_DETAILS: 'nvp_private_cancellationDetails', + + /** Stores the information about currently edited advanced approval workflow */ + APPROVAL_WORKFLOW: 'approvalWorkflow', + /** Collection Keys */ COLLECTION: { DOWNLOAD: 'download_', @@ -414,6 +425,7 @@ const ONYXKEYS = { REPORT_IS_COMPOSER_FULL_SIZE: 'reportIsComposerFullSize_', REPORT_USER_IS_TYPING: 'reportUserIsTyping_', REPORT_USER_IS_LEAVING_ROOM: 'reportUserIsLeavingRoom_', + REPORT_VIOLATIONS: 'reportViolations_', SECURITY_GROUP: 'securityGroup_', TRANSACTION: 'transactions_', TRANSACTION_VIOLATIONS: 'transactionViolations_', @@ -446,8 +458,11 @@ const ONYXKEYS = { */ WORKSPACE_CARDS_LIST: 'card_', - /** The bank account that Expensify Card payments will be reconciled against */ + /** Stores which connection is set up to use Continuous Reconciliation */ SHARED_NVP_EXPENSIFY_CARD_CONTINUOUS_RECONCILIATION_CONNECTION: 'sharedNVP_expensifyCard_continuousReconciliationConnection_', + + /** The value that indicates whether Continuous Reconciliation should be used on the domain */ + SHARED_NVP_EXPENSIFY_CARD_USE_CONTINUOUS_RECONCILIATION: 'sharedNVP_expensifyCard_useContinuousReconciliation_', }, /** List of Form ids */ @@ -555,6 +570,8 @@ const ONYXKEYS = { WORKSPACE_NEW_TAX_FORM: 'workspaceNewTaxForm', WORKSPACE_NEW_TAX_FORM_DRAFT: 'workspaceNewTaxFormDraft', WORKSPACE_TAX_NAME_FORM: 'workspaceTaxNameForm', + WORKSPACE_TAX_CODE_FORM: 'workspaceTaxCodeForm', + WORKSPACE_TAX_CODE_FORM_DRAFT: 'workspaceTaxCodeFormDraft', WORKSPACE_TAX_NAME_FORM_DRAFT: 'workspaceTaxNameFormDraft', WORKSPACE_TAX_VALUE_FORM: 'workspaceTaxValueForm', WORKSPACE_TAX_VALUE_FORM_DRAFT: 'workspaceTaxValueFormDraft', @@ -564,6 +581,10 @@ const ONYXKEYS = { SUBSCRIPTION_SIZE_FORM_DRAFT: 'subscriptionSizeFormDraft', ISSUE_NEW_EXPENSIFY_CARD_FORM: 'issueNewExpensifyCard', ISSUE_NEW_EXPENSIFY_CARD_FORM_DRAFT: 'issueNewExpensifyCardDraft', + EDIT_EXPENSIFY_CARD_NAME_FORM: 'editExpensifyCardName', + EDIT_EXPENSIFY_CARD_NAME_DRAFT_FORM: 'editExpensifyCardNameDraft', + EDIT_EXPENSIFY_CARD_LIMIT_FORM: 'editExpensifyCardLimit', + EDIT_EXPENSIFY_CARD_LIMIT_DRAFT_FORM: 'editExpensifyCardLimitDraft', SAGE_INTACCT_CREDENTIALS_FORM: 'sageIntacctCredentialsForm', SAGE_INTACCT_CREDENTIALS_FORM_DRAFT: 'sageIntacctCredentialsFormDraft', NETSUITE_CUSTOM_FIELD_FORM: 'netSuiteCustomFieldForm', @@ -578,6 +599,8 @@ const ONYXKEYS = { NETSUITE_CUSTOM_FORM_ID_FORM_DRAFT: 'netsuiteCustomFormIDFormDraft', SAGE_INTACCT_DIMENSION_TYPE_FORM: 'sageIntacctDimensionTypeForm', SAGE_INTACCT_DIMENSION_TYPE_FORM_DRAFT: 'sageIntacctDimensionTypeFormDraft', + SEARCH_ADVANCED_FILTERS_FORM: 'searchAdvancedFiltersForm', + SEARCH_ADVANCED_FILTERS_FORM_DRAFT: 'searchAdvancedFiltersFormDraft', }, } as const; @@ -636,10 +659,13 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.POLICY_DISTANCE_RATE_EDIT_FORM]: FormTypes.PolicyDistanceRateEditForm; [ONYXKEYS.FORMS.POLICY_DISTANCE_RATE_TAX_RECLAIMABLE_ON_EDIT_FORM]: FormTypes.PolicyDistanceRateTaxReclaimableOnEditForm; [ONYXKEYS.FORMS.WORKSPACE_TAX_NAME_FORM]: FormTypes.WorkspaceTaxNameForm; + [ONYXKEYS.FORMS.WORKSPACE_TAX_CODE_FORM]: FormTypes.WorkspaceTaxCodeForm; [ONYXKEYS.FORMS.WORKSPACE_TAX_VALUE_FORM]: FormTypes.WorkspaceTaxValueForm; [ONYXKEYS.FORMS.NEW_CHAT_NAME_FORM]: FormTypes.NewChatNameForm; [ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM]: FormTypes.SubscriptionSizeForm; [ONYXKEYS.FORMS.ISSUE_NEW_EXPENSIFY_CARD_FORM]: FormTypes.IssueNewExpensifyCardForm; + [ONYXKEYS.FORMS.EDIT_EXPENSIFY_CARD_NAME_FORM]: FormTypes.EditExpensifyCardNameForm; + [ONYXKEYS.FORMS.EDIT_EXPENSIFY_CARD_LIMIT_FORM]: FormTypes.EditExpensifyCardLimitForm; [ONYXKEYS.FORMS.SAGE_INTACCT_CREDENTIALS_FORM]: FormTypes.SageIntactCredentialsForm; [ONYXKEYS.FORMS.NETSUITE_CUSTOM_FIELD_FORM]: FormTypes.NetSuiteCustomFieldForm; [ONYXKEYS.FORMS.NETSUITE_CUSTOM_LIST_ADD_FORM]: FormTypes.NetSuiteCustomFieldForm; @@ -647,6 +673,7 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.NETSUITE_TOKEN_INPUT_FORM]: FormTypes.NetSuiteTokenInputForm; [ONYXKEYS.FORMS.NETSUITE_CUSTOM_FORM_ID_FORM]: FormTypes.NetSuiteCustomFormIDForm; [ONYXKEYS.FORMS.SAGE_INTACCT_DIMENSION_TYPE_FORM]: FormTypes.SageIntacctDimensionForm; + [ONYXKEYS.FORMS.SEARCH_ADVANCED_FILTERS_FORM]: FormTypes.SearchAdvancedFiltersForm; }; type OnyxFormDraftValuesMapping = { @@ -677,6 +704,7 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.REPORT_IS_COMPOSER_FULL_SIZE]: boolean; [ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING]: OnyxTypes.ReportUserIsTyping; [ONYXKEYS.COLLECTION.REPORT_USER_IS_LEAVING_ROOM]: boolean; + [ONYXKEYS.COLLECTION.REPORT_VIOLATIONS]: OnyxTypes.ReportViolations; [ONYXKEYS.COLLECTION.SECURITY_GROUP]: OnyxTypes.SecurityGroup; [ONYXKEYS.COLLECTION.TRANSACTION]: OnyxTypes.Transaction; [ONYXKEYS.COLLECTION.TRANSACTION_DRAFT]: OnyxTypes.Transaction; @@ -695,7 +723,8 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_USER_BILLING_GRACE_PERIOD_END]: OnyxTypes.BillingGraceEndPeriod; [ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_EXPENSIFY_CARD_SETTINGS]: OnyxTypes.ExpensifyCardSettings; [ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST]: OnyxTypes.WorkspaceCardsList; - [ONYXKEYS.COLLECTION.SHARED_NVP_EXPENSIFY_CARD_CONTINUOUS_RECONCILIATION_CONNECTION]: OnyxTypes.BankAccount; + [ONYXKEYS.COLLECTION.SHARED_NVP_EXPENSIFY_CARD_CONTINUOUS_RECONCILIATION_CONNECTION]: OnyxTypes.PolicyConnectionName; + [ONYXKEYS.COLLECTION.SHARED_NVP_EXPENSIFY_CARD_USE_CONTINUOUS_RECONCILIATION]: boolean; }; type OnyxValuesMapping = { @@ -748,6 +777,7 @@ type OnyxValuesMapping = { [ONYXKEYS.NVP_DISMISSED_HOLD_USE_EXPLANATION]: boolean; [ONYXKEYS.FOCUS_MODE_NOTIFICATION]: boolean; [ONYXKEYS.NVP_LAST_PAYMENT_METHOD]: OnyxTypes.LastPaymentMethod; + [ONYXKEYS.LAST_EXPORT_METHOD]: OnyxTypes.LastExportMethod; [ONYXKEYS.NVP_RECENT_WAYPOINTS]: OnyxTypes.RecentWaypoint[]; [ONYXKEYS.NVP_INTRO_SELECTED]: OnyxTypes.IntroSelected; [ONYXKEYS.NVP_LAST_SELECTED_DISTANCE_RATES]: OnyxTypes.LastSelectedDistanceRates; @@ -806,12 +836,14 @@ type OnyxValuesMapping = { [ONYXKEYS.ONBOARDING_ADMINS_CHAT_REPORT_ID]: string; [ONYXKEYS.IS_SEARCHING_FOR_REPORTS]: boolean; [ONYXKEYS.LAST_VISITED_PATH]: string | undefined; + [ONYXKEYS.VERIFY_3DS_SUBSCRIPTION]: string; [ONYXKEYS.RECENTLY_USED_REPORT_FIELDS]: OnyxTypes.RecentlyUsedReportFields; [ONYXKEYS.UPDATE_REQUIRED]: boolean; [ONYXKEYS.RESET_REQUIRED]: boolean; [ONYXKEYS.PLAID_CURRENT_EVENT]: string; [ONYXKEYS.LOGS]: OnyxTypes.CapturedLogs; [ONYXKEYS.SHOULD_STORE_LOGS]: boolean; + [ONYXKEYS.SHOULD_MASK_ONYX_STATE]: boolean; [ONYXKEYS.CACHED_PDF_PATHS]: Record; [ONYXKEYS.POLICY_OWNERSHIP_CHANGE_CHECKS]: Record; [ONYXKEYS.NVP_QUICK_ACTION_GLOBAL_CREATE]: OnyxTypes.QuickAction; @@ -826,6 +858,8 @@ type OnyxValuesMapping = { [ONYXKEYS.NVP_BILLING_FUND_ID]: number; [ONYXKEYS.NVP_PRIVATE_AMOUNT_OWED]: number; [ONYXKEYS.NVP_PRIVATE_OWNER_BILLING_GRACE_PERIOD_END]: number; + [ONYXKEYS.NVP_PRIVATE_CANCELLATION_DETAILS]: OnyxTypes.CancellationDetails[]; + [ONYXKEYS.APPROVAL_WORKFLOW]: OnyxTypes.ApprovalWorkflow; }; type OnyxValues = OnyxValuesMapping & OnyxCollectionValuesMapping & OnyxFormValuesMapping & OnyxFormDraftValuesMapping; diff --git a/src/ROUTES.ts b/src/ROUTES.ts index e072227b5726..c461defb6352 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -1,10 +1,9 @@ import type {TupleToUnion, ValueOf} from 'type-fest'; +import type {SearchQueryString} from './components/Search/types'; import type CONST from './CONST'; import type {IOUAction, IOUType} from './CONST'; import type {IOURequestType} from './libs/actions/IOU'; -import type {AuthScreensParamList} from './libs/Navigation/types'; -import type {SageIntacctMappingName} from './types/onyx/Policy'; -import type {SearchQuery} from './types/onyx/SearchResults'; +import type {ConnectionName, SageIntacctMappingName} from './types/onyx/Policy'; import type AssertTypesNotEqual from './types/utils/AssertTypesNotEqual'; // This is a file containing constants for all the routes we want to be able to go to @@ -34,33 +33,31 @@ const ROUTES = { // This route renders the list of reports. HOME: 'home', - ALL_SETTINGS: 'all-settings', + SEARCH_CENTRAL_PANE: { + route: 'search', + getRoute: ({query, isCustomQuery = false, policyIDs}: {query: SearchQueryString; isCustomQuery?: boolean; policyIDs?: string}) => + `search?q=${query}&isCustomQuery=${isCustomQuery}${policyIDs ? `&policyIDs=${policyIDs}` : ''}` as const, + }, - SEARCH: { - route: '/search/:query', - getRoute: (searchQuery: SearchQuery, queryParams?: AuthScreensParamList['Search_Central_Pane']) => { - const {sortBy, sortOrder} = queryParams ?? {}; + SEARCH_ADVANCED_FILTERS: 'search/filters', - if (!sortBy && !sortOrder) { - return `search/${searchQuery}` as const; - } + SEARCH_ADVANCED_FILTERS_DATE: 'search/filters/date', - return `search/${searchQuery}?sortBy=${sortBy}&sortOrder=${sortOrder}` as const; - }, - }, + SEARCH_ADVANCED_FILTERS_TYPE: 'search/filters/type', + + SEARCH_ADVANCED_FILTERS_STATUS: 'search/filters/status', SEARCH_REPORT: { - route: '/search/:query/view/:reportID', - getRoute: (query: string, reportID: string) => `search/${query}/view/${reportID}` as const, + route: 'search/view/:reportID', + getRoute: (reportID: string) => `search/view/${reportID}` as const, }, - TRANSACTION_HOLD_REASON_RHP: { - route: '/search/:query/hold/:transactionID', - getRoute: (query: string, transactionID: string) => `search/${query}/hold/${transactionID}` as const, - }, + TRANSACTION_HOLD_REASON_RHP: 'search/hold', // This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated CONCIERGE: 'concierge', + TRACK_EXPENSE: 'track-expense', + SUBMIT_EXPENSE: 'submit-expense', FLAG_COMMENT: { route: 'flag/:reportID/:reportActionID', getRoute: (reportID: string, reportActionID: string) => `flag/${reportID}/${reportActionID}` as const, @@ -117,6 +114,7 @@ const ROUTES = { SETTINGS_SUBSCRIPTION_CHANGE_BILLING_CURRENCY: 'settings/subscription/change-billing-currency', SETTINGS_SUBSCRIPTION_CHANGE_PAYMENT_CURRENCY: 'settings/subscription/add-payment-card/change-payment-currency', SETTINGS_SUBSCRIPTION_DISABLE_AUTO_RENEW_SURVEY: 'settings/subscription/disable-auto-renew-survey', + SETTINGS_SUBSCRIPTION_REQUEST_EARLY_CANCELLATION: 'settings/subscription/request-early-cancellation-survey', SETTINGS_PRIORITY_MODE: 'settings/preferences/priority-mode', SETTINGS_LANGUAGE: 'settings/preferences/language', SETTINGS_THEME: 'settings/preferences/theme', @@ -198,7 +196,8 @@ const ROUTES = { }, SETTINGS_2FA: { route: 'settings/security/two-factor-auth', - getRoute: (backTo?: string) => getUrlWithBackToParam('settings/security/two-factor-auth', backTo), + getRoute: (backTo?: string, forwardTo?: string) => + getUrlWithBackToParam(forwardTo ? `settings/security/two-factor-auth?forwardTo=${encodeURIComponent(forwardTo)}` : 'settings/security/two-factor-auth', backTo), }, SETTINGS_STATUS: 'settings/profile/status', @@ -286,6 +285,10 @@ const ROUTES = { route: 'r/:reportID/details', getRoute: (reportID: string, backTo?: string) => getUrlWithBackToParam(`r/${reportID}/details`, backTo), }, + REPORT_WITH_ID_DETAILS_EXPORT: { + route: 'r/:reportID/details/export/:connectionName', + getRoute: (reportID: string, connectionName: ConnectionName) => `r/${reportID}/details/export/${connectionName}` as const, + }, REPORT_SETTINGS: { route: 'r/:reportID/settings', getRoute: (reportID: string) => `r/${reportID}/settings` as const, @@ -608,21 +611,33 @@ const ROUTES = { route: 'settings/workspaces/:policyID/workflows', getRoute: (policyID: string) => `settings/workspaces/${policyID}/workflows` as const, }, - WORKSPACE_WORKFLOWS_PAYER: { - route: 'workspace/:policyID/settings/workflows/payer', - getRoute: (policyId: string) => `workspace/${policyId}/settings/workflows/payer` as const, + WORKSPACE_WORKFLOWS_APPROVALS_NEW: { + route: 'settings/workspaces/:policyID/workflows/approvals/new', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/workflows/approvals/new` as const, + }, + WORKSPACE_WORKFLOWS_APPROVALS_EDIT: { + route: 'settings/workspaces/:policyID/workflows/approvals/:firstApproverEmail/edit', + getRoute: (policyID: string, firstApproverEmail: string) => `settings/workspaces/${policyID}/workflows/approvals/${encodeURIComponent(firstApproverEmail)}/edit` as const, }, - WORKSPACE_WORKFLOWS_APPROVER: { - route: 'settings/workspaces/:policyID/settings/workflows/approver', - getRoute: (policyID: string) => `settings/workspaces/${policyID}/settings/workflows/approver` as const, + WORKSPACE_WORKFLOWS_APPROVALS_EXPENSES_FROM: { + route: 'settings/workspaces/:policyID/workflows/approvals/expenses-from', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/workflows/approvals/expenses-from` as const, + }, + WORKSPACE_WORKFLOWS_APPROVALS_APPROVER: { + route: 'settings/workspaces/:policyID/workflows/approvals/approver', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/workflows/approvals/approver` as const, + }, + WORKSPACE_WORKFLOWS_PAYER: { + route: 'settings/workspaces/:policyID/workflows/payer', + getRoute: (policyId: string) => `settings/workspaces/${policyId}/workflows/payer` as const, }, WORKSPACE_WORKFLOWS_AUTOREPORTING_FREQUENCY: { - route: 'settings/workspaces/:policyID/settings/workflows/auto-reporting-frequency', - getRoute: (policyID: string) => `settings/workspaces/${policyID}/settings/workflows/auto-reporting-frequency` as const, + route: 'settings/workspaces/:policyID/workflows/auto-reporting-frequency', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/workflows/auto-reporting-frequency` as const, }, WORKSPACE_WORKFLOWS_AUTOREPORTING_MONTHLY_OFFSET: { - route: 'settings/workspaces/:policyID/settings/workflows/auto-reporting-frequency/monthly-offset', - getRoute: (policyID: string) => `settings/workspaces/${policyID}/settings/workflows/auto-reporting-frequency/monthly-offset` as const, + route: 'settings/workspaces/:policyID/workflows/auto-reporting-frequency/monthly-offset', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/workflows/auto-reporting-frequency/monthly-offset` as const, }, WORKSPACE_CARD: { route: 'settings/workspaces/:policyID/card', @@ -676,10 +691,15 @@ const ROUTES = { route: 'settings/workspaces/:policyID/accounting/quickbooks-online/invoice-account-selector', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/quickbooks-online/invoice-account-selector` as const, }, - WORKSPACE_ACCOUNTING_RECONCILIATION_ACCOUNT_SETTINGS: { + WORKSPACE_ACCOUNTING_CARD_RECONCILIATION: { route: 'settings/workspaces/:policyID/accounting/:connection/card-reconciliation', getRoute: (policyID: string, connection: ValueOf) => `settings/workspaces/${policyID}/accounting/${connection}/card-reconciliation` as const, }, + WORKSPACE_ACCOUNTING_RECONCILIATION_ACCOUNT_SETTINGS: { + route: 'settings/workspaces/:policyID/accounting/:connection/card-reconciliation/account', + getRoute: (policyID: string, connection: ValueOf) => + `settings/workspaces/${policyID}/accounting/${connection}/card-reconciliation/account` as const, + }, WORKSPACE_CATEGORIES: { route: 'settings/workspaces/:policyID/categories', getRoute: (policyID: string) => `settings/workspaces/${policyID}/categories` as const, @@ -690,7 +710,8 @@ const ROUTES = { }, WORKSPACE_UPGRADE: { route: 'settings/workspaces/:policyID/upgrade/:featureName', - getRoute: (policyID: string, featureName: string) => `settings/workspaces/${policyID}/upgrade/${encodeURIComponent(featureName)}` as const, + getRoute: (policyID: string, featureName: string, backTo?: string) => + getUrlWithBackToParam(`settings/workspaces/${policyID}/upgrade/${encodeURIComponent(featureName)}` as const, backTo), }, WORKSPACE_CATEGORIES_SETTINGS: { route: 'settings/workspaces/:policyID/categories/settings', @@ -704,6 +725,14 @@ const ROUTES = { route: 'settings/workspaces/:policyID/categories/:categoryName/edit', getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}/edit` as const, }, + WORKSPACE_CATEGORY_PAYROLL_CODE: { + route: 'settings/workspaces/:policyID/categories/:categoryName/payroll-code', + getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}/payroll-code` as const, + }, + WORKSPACE_CATEGORY_GL_CODE: { + route: 'settings/workspaces/:policyID/categories/:categoryName/gl-code', + getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}/gl-code` as const, + }, WORKSPACE_MORE_FEATURES: { route: 'settings/workspaces/:policyID/more-features', getRoute: (policyID: string) => `settings/workspaces/${policyID}/more-features` as const, @@ -736,6 +765,10 @@ const ROUTES = { route: 'settings/workspaces/:policyID/tag-list/:orderWeight', getRoute: (policyID: string, orderWeight: number) => `settings/workspaces/${policyID}/tag-list/${orderWeight}` as const, }, + WORKSPACE_TAG_GL_CODE: { + route: 'settings/workspaces/:policyID/tag/:orderWeight/:tagName/gl-code', + getRoute: (policyID: string, orderWeight: number, tagName: string) => `settings/workspaces/${policyID}/tag/${orderWeight}/${encodeURIComponent(tagName)}/gl-code` as const, + }, WORKSPACE_TAXES: { route: 'settings/workspaces/:policyID/taxes', getRoute: (policyID: string) => `settings/workspaces/${policyID}/taxes` as const, @@ -793,6 +826,10 @@ const ROUTES = { route: 'settings/workspaces/:policyID/tax/:taxID/value', getRoute: (policyID: string, taxID: string) => `settings/workspaces/${policyID}/tax/${encodeURIComponent(taxID)}/value` as const, }, + WORKSPACE_TAX_CODE: { + route: 'settings/workspaces/:policyID/tax/:taxID/tax-code', + getRoute: (policyID: string, taxID: string) => `settings/workspaces/${policyID}/tax/${encodeURIComponent(taxID)}/tax-code` as const, + }, WORKSPACE_REPORT_FIELDS: { route: 'settings/workspaces/:policyID/reportFields', getRoute: (policyID: string) => `settings/workspaces/${policyID}/reportFields` as const, @@ -830,10 +867,42 @@ const ROUTES = { route: 'settings/workspaces/:policyID/expensify-card', getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card` as const, }, + WORKSPACE_EXPENSIFY_CARD_DETAILS: { + route: 'settings/workspaces/:policyID/expensify-card/:cardID', + getRoute: (policyID: string, cardID: string, backTo?: string) => getUrlWithBackToParam(`settings/workspaces/${policyID}/expensify-card/${cardID}`, backTo), + }, + WORKSPACE_EXPENSIFY_CARD_NAME: { + route: 'settings/workspaces/:policyID/expensify-card/:cardID/edit/name', + getRoute: (policyID: string, cardID: string) => `settings/workspaces/${policyID}/expensify-card/${cardID}/edit/name` as const, + }, + WORKSPACE_EXPENSIFY_CARD_LIMIT: { + route: 'settings/workspaces/:policyID/expensify-card/:cardID/edit/limit', + getRoute: (policyID: string, cardID: string) => `settings/workspaces/${policyID}/expensify-card/${cardID}/edit/limit` as const, + }, + WORKSPACE_EXPENSIFY_CARD_LIMIT_TYPE: { + route: 'settings/workspaces/:policyID/expensify-card/:cardID/edit/limit-type', + getRoute: (policyID: string, cardID: string) => `settings/workspaces/${policyID}/expensify-card/${cardID}/edit/limit-type` as const, + }, WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW: { route: 'settings/workspaces/:policyID/expensify-card/issue-new', getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card/issue-new` as const, }, + WORKSPACE_EXPENSIFY_CARD_BANK_ACCOUNT: { + route: 'settings/workspaces/:policyID/expensify-card/choose-bank-account', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card/choose-bank-account` as const, + }, + WORKSPACE_EXPENSIFY_CARD_SETTINGS: { + route: 'settings/workspaces/:policyID/expensify-card/settings', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card/settings` as const, + }, + WORKSPACE_EXPENSIFY_CARD_SETTINGS_ACCOUNT: { + route: 'settings/workspaces/:policyID/expensify-card/settings/account', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card/settings/account` as const, + }, + WORKSPACE_EXPENSIFY_CARD_SETTINGS_FREQUENCY: { + route: 'settings/workspaces/:policyID/expensify-card/settings/frequency', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card/settings/frequency` as const, + }, WORKSPACE_DISTANCE_RATES: { route: 'settings/workspaces/:policyID/distance-rates', getRoute: (policyID: string) => `settings/workspaces/${policyID}/distance-rates` as const, @@ -871,10 +940,22 @@ const ROUTES = { TRAVEL_MY_TRIPS: 'travel', TRAVEL_TCS: 'travel/terms', TRACK_TRAINING_MODAL: 'track-training', - ONBOARDING_ROOT: 'onboarding', - ONBOARDING_PERSONAL_DETAILS: 'onboarding/personal-details', - ONBOARDING_WORK: 'onboarding/work', - ONBOARDING_PURPOSE: 'onboarding/purpose', + ONBOARDING_ROOT: { + route: 'onboarding', + getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding`, backTo), + }, + ONBOARDING_PERSONAL_DETAILS: { + route: 'onboarding/personal-details', + getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding/personal-details`, backTo), + }, + ONBOARDING_WORK: { + route: 'onboarding/work', + getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding/work`, backTo), + }, + ONBOARDING_PURPOSE: { + route: 'onboarding/purpose', + getRoute: (backTo?: string) => getUrlWithBackToParam(`onboarding/purpose`, backTo), + }, WELCOME_VIDEO_ROOT: 'onboarding/welcome-video', EXPLANATION_MODAL_ROOT: 'onboarding/explanation', @@ -903,8 +984,8 @@ const ROUTES = { getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/tax-code` as const, }, TRANSACTION_DUPLICATE_REVIEW_DESCRIPTION_PAGE: { - route: 'r/:threadReportID/duplicates/confirm', - getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/confirm` as const, + route: 'r/:threadReportID/duplicates/review/description', + getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/description` as const, }, TRANSACTION_DUPLICATE_REVIEW_REIMBURSABLE_PAGE: { route: 'r/:threadReportID/duplicates/review/reimbursable', @@ -914,7 +995,10 @@ const ROUTES = { route: 'r/:threadReportID/duplicates/review/billable', getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/review/billable` as const, }, - + TRANSACTION_DUPLICATE_CONFIRMATION_PAGE: { + route: 'r/:threadReportID/duplicates/confirm', + getRoute: (threadReportID: string) => `r/${threadReportID}/duplicates/confirm` as const, + }, POLICY_ACCOUNTING_XERO_IMPORT: { route: 'settings/workspaces/:policyID/accounting/xero/import', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/xero/import` as const, @@ -1008,6 +1092,10 @@ const ROUTES = { route: 'settings/workspaces/:policyID/accounting/netsuite/subsidiary-selector', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/netsuite/subsidiary-selector` as const, }, + POLICY_ACCOUNTING_NETSUITE_EXISTING_CONNECTIONS: { + route: 'settings/workspaces/:policyID/accounting/netsuite/existing-connections', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/netsuite/existing-connections` as const, + }, POLICY_ACCOUNTING_NETSUITE_TOKEN_INPUT: { route: 'settings/workspaces/:policyID/accounting/netsuite/token-input', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/netsuite/token-input` as const, @@ -1154,6 +1242,10 @@ const ROUTES = { route: 'settings/workspaces/:policyID/accounting/sage-intacct/existing-connections', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/existing-connections` as const, }, + POLICY_ACCOUNTING_SAGE_INTACCT_ENTITY: { + route: 'settings/workspaces/:policyID/accounting/sage-intacct/entity', + getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/entity` as const, + }, POLICY_ACCOUNTING_SAGE_INTACCT_IMPORT: { route: 'settings/workspaces/:policyID/accounting/sage-intacct/import', getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting/sage-intacct/import` as const, diff --git a/src/SCREENS.ts b/src/SCREENS.ts index 0768ca8bb291..4047b0a851bc 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -8,11 +8,12 @@ const PROTECTED_SCREENS = { HOME: 'Home', CONCIERGE: 'Concierge', ATTACHMENTS: 'Attachments', + TRACK_EXPENSE: 'TrackExpense', + SUBMIT_EXPENSE: 'SubmitExpense', } as const; const SCREENS = { ...PROTECTED_SCREENS, - ALL_SETTINGS: 'AllSettings', REPORT: 'Report', PROFILE_AVATAR: 'ProfileAvatar', WORKSPACE_AVATAR: 'WorkspaceAvatar', @@ -30,6 +31,10 @@ const SCREENS = { SEARCH: { CENTRAL_PANE: 'Search_Central_Pane', REPORT_RHP: 'Search_Report_RHP', + ADVANCED_FILTERS_RHP: 'Search_Advanced_Filters_RHP', + ADVANCED_FILTERS_DATE_RHP: 'Search_Advanced_Filters_Date_RHP', + ADVANCED_FILTERS_TYPE_RHP: 'Search_Advanced_Filters_Type_RHP', + ADVANCED_FILTERS_STATUS_RHP: 'Search_Advanced_Filters_Status_RHP', TRANSACTION_HOLD_REASON_RHP: 'Search_Transaction_Hold_Reason_RHP', BOTTOM_TAB: 'Search_Bottom_Tab', }, @@ -108,6 +113,7 @@ const SCREENS = { DISABLE_AUTO_RENEW_SURVEY: 'Settings_Subscription_DisableAutoRenewSurvey', CHANGE_BILLING_CURRENCY: 'Settings_Subscription_Change_Billing_Currency', CHANGE_PAYMENT_CURRENCY: 'Settings_Subscription_Change_Payment_Currency', + REQUEST_EARLY_CANCELLATION: 'Settings_Subscription_RequestEarlyCancellation', }, }, SAVE_THE_WORLD: { @@ -145,8 +151,10 @@ const SCREENS = { TRANSACTION_DUPLICATE: 'TransactionDuplicate', TRAVEL: 'Travel', SEARCH_REPORT: 'SearchReport', + SEARCH_ADVANCED_FILTERS: 'SearchAdvancedFilters', SETTINGS_CATEGORIES: 'SettingsCategories', RESTRICTED_ACTION: 'RestrictedAction', + REPORT_EXPORT: 'Report_Export', }, ONBOARDING_MODAL: { ONBOARDING: 'Onboarding', @@ -194,6 +202,7 @@ const SCREENS = { TAX_CODE: 'Transaction_Duplicate_Tax_Code', REIMBURSABLE: 'Transaction_Duplicate_Reimburable', BILLABLE: 'Transaction_Duplicate_Billable', + CONFIRMATION: 'Transaction_Duplicate_Confirmation', }, IOU_SEND: { @@ -240,6 +249,7 @@ const SCREENS = { REPORT_DETAILS: { ROOT: 'Report_Details_Root', SHARE_CODE: 'Report_Details_Share_Code', + EXPORT: 'Report_Details_Export', }, WORKSPACE: { @@ -288,6 +298,7 @@ const SCREENS = { NETSUITE_IMPORT_CUSTOM_SEGMENT_ADD: 'Policy_Accounting_NetSuite_Import_Custom_Segment_Add', NETSUITE_IMPORT_CUSTOMERS_OR_PROJECTS: 'Policy_Accounting_NetSuite_Import_CustomersOrProjects', NETSUITE_IMPORT_CUSTOMERS_OR_PROJECTS_SELECT: 'Policy_Accounting_NetSuite_Import_CustomersOrProjects_Select', + NETSUITE_REUSE_EXISTING_CONNECTIONS: 'Policy_Accounting_NetSuite_Reuse_Existing_Connections', NETSUITE_TOKEN_INPUT: 'Policy_Accounting_NetSuite_Token_Input', NETSUITE_SUBSIDIARY_SELECTOR: 'Policy_Accounting_NetSuite_Subsidiary_Selector', NETSUITE_IMPORT: 'Policy_Accounting_NetSuite_Import', @@ -315,6 +326,7 @@ const SCREENS = { SAGE_INTACCT_PREREQUISITES: 'Policy_Accounting_Sage_Intacct_Prerequisites', ENTER_SAGE_INTACCT_CREDENTIALS: 'Policy_Enter_Sage_Intacct_Credentials', EXISTING_SAGE_INTACCT_CONNECTIONS: 'Policy_Existing_Sage_Intacct_Connections', + SAGE_INTACCT_ENTITY: 'Policy_Sage_Intacct_Entity', SAGE_INTACCT_IMPORT: 'Policy_Accounting_Sage_Intacct_Import', SAGE_INTACCT_TOGGLE_MAPPING: 'Policy_Accounting_Sage_Intacct_Toggle_Mapping', SAGE_INTACCT_MAPPING_TYPE: 'Policy_Accounting_Sage_Intacct_Mapping_Type', @@ -330,6 +342,7 @@ const SCREENS = { SAGE_INTACCT_NON_REIMBURSABLE_CREDIT_CARD_ACCOUNT: 'Policy_Accounting_Sage_Intacct_Non_Reimbursable_Credit_Card_Account', SAGE_INTACCT_ADVANCED: 'Policy_Accounting_Sage_Intacct_Advanced', SAGE_INTACCT_PAYMENT_ACCOUNT: 'Policy_Accounting_Sage_Intacct_Payment_Account', + CARD_RECONCILIATION: 'Policy_Accounting_Card_Reconciliation', RECONCILIATION_ACCOUNT_SETTINGS: 'Policy_Accounting_Reconciliation_Account_Settings', }, INITIAL: 'Workspace_Initial', @@ -340,7 +353,15 @@ const SCREENS = { RATE_AND_UNIT_RATE: 'Workspace_RateAndUnit_Rate', RATE_AND_UNIT_UNIT: 'Workspace_RateAndUnit_Unit', EXPENSIFY_CARD: 'Workspace_ExpensifyCard', + EXPENSIFY_CARD_DETAILS: 'Workspace_ExpensifyCard_Details', + EXPENSIFY_CARD_LIMIT: 'Workspace_ExpensifyCard_Limit', EXPENSIFY_CARD_ISSUE_NEW: 'Workspace_ExpensifyCard_New', + EXPENSIFY_CARD_NAME: 'Workspace_ExpensifyCard_Name', + EXPENSIFY_CARD_LIMIT_TYPE: 'Workspace_ExpensifyCard_LimitType', + EXPENSIFY_CARD_BANK_ACCOUNT: 'Workspace_ExpensifyCard_BankAccount', + EXPENSIFY_CARD_SETTINGS: 'Workspace_ExpensifyCard_Settings', + EXPENSIFY_CARD_SETTINGS_ACCOUNT: 'Workspace_ExpensifyCard_Settings_Account', + EXPENSIFY_CARD_SETTINGS_FREQUENCY: 'Workspace_ExpensifyCard_Settings_Frequency', BILLS: 'Workspace_Bills', INVOICES: 'Workspace_Invoices', TRAVEL: 'Workspace_Travel', @@ -364,6 +385,7 @@ const SCREENS = { TAX_EDIT: 'Workspace_Tax_Edit', TAX_NAME: 'Workspace_Tax_Name', TAX_VALUE: 'Workspace_Tax_Value', + TAX_CODE: 'Workspace_Tax_Code', TAXES_SETTINGS: 'Workspace_Taxes_Settings', TAXES_SETTINGS_CUSTOM_TAX_NAME: 'Workspace_Taxes_Settings_CustomTaxName', TAXES_SETTINGS_WORKSPACE_CURRENCY_DEFAULT: 'Workspace_Taxes_Settings_WorkspaceCurrency', @@ -372,11 +394,15 @@ const SCREENS = { TAG_CREATE: 'Tag_Create', TAG_SETTINGS: 'Tag_Settings', TAG_LIST_VIEW: 'Tag_List_View', + TAG_GL_CODE: 'Tag_GL_Code', CURRENCY: 'Workspace_Profile_Currency', ADDRESS: 'Workspace_Profile_Address', WORKFLOWS: 'Workspace_Workflows', WORKFLOWS_PAYER: 'Workspace_Workflows_Payer', - WORKFLOWS_APPROVER: 'Workspace_Workflows_Approver', + WORKFLOWS_APPROVALS_NEW: 'Workspace_Approvals_New', + WORKFLOWS_APPROVALS_EDIT: 'Workspace_Approvals_Edit', + WORKFLOWS_APPROVALS_EXPENSES_FROM: 'Workspace_Workflows_Approvals_Expenses_From', + WORKFLOWS_APPROVALS_APPROVER: 'Workspace_Workflows_Approvals_Approver', WORKFLOWS_AUTO_REPORTING_FREQUENCY: 'Workspace_Workflows_Auto_Reporting_Frequency', WORKFLOWS_AUTO_REPORTING_MONTHLY_OFFSET: 'Workspace_Workflows_Auto_Reporting_Monthly_Offset', DESCRIPTION: 'Workspace_Profile_Description', @@ -384,6 +410,8 @@ const SCREENS = { NAME: 'Workspace_Profile_Name', CATEGORY_CREATE: 'Category_Create', CATEGORY_EDIT: 'Category_Edit', + CATEGORY_PAYROLL_CODE: 'Category_Payroll_Code', + CATEGORY_GL_CODE: 'Category_GL_Code', CATEGORY_SETTINGS: 'Category_Settings', CATEGORIES_SETTINGS: 'Categories_Settings', MORE_FEATURES: 'Workspace_More_Features', diff --git a/src/components/AddPaymentMethodMenu.tsx b/src/components/AddPaymentMethodMenu.tsx index 325bab091bec..451979b92efa 100644 --- a/src/components/AddPaymentMethodMenu.tsx +++ b/src/components/AddPaymentMethodMenu.tsx @@ -1,5 +1,5 @@ import type {RefObject} from 'react'; -import React from 'react'; +import React, {useEffect} from 'react'; import type {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -70,6 +70,21 @@ function AddPaymentMethodMenu({ const canUsePersonalBankAccount = shouldShowPersonalBankAccountOption || isIOUReport; + const isPersonalOnlyOption = canUsePersonalBankAccount && !canUseBusinessBankAccount; + + // We temporarily disabled P2P debit cards so we will automatically select the personal bank account option if there is no other option to select. + useEffect(() => { + if (!isVisible) { + return; + } + + onItemSelected(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); + }, [isPersonalOnlyOption, isVisible, onItemSelected]); + + if (isPersonalOnlyOption) { + return null; + } + return ( onItemSelected(CONST.PAYMENT_METHODS.DEBIT_CARD), - }, - ], + // Adding a debit card for P2P payments is temporarily disabled + // ...[ + // { + // text: translate('common.debitCard'), + // icon: Expensicons.CreditCard, + // onSelected: () => onItemSelected(CONST.PAYMENT_METHODS.DEBIT_CARD), + // }, + // ], ]} withoutOverlay /> diff --git a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx index 48604ec364c7..b9aeceeb3621 100644 --- a/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx +++ b/src/components/AnchorForAttachmentsOnly/BaseAnchorForAttachmentsOnly.tsx @@ -41,7 +41,7 @@ function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', dow return ( - {({anchor, report, action, checkIfContextMenuActive}) => ( + {({anchor, report, reportNameValuePairs, action, checkIfContextMenuActive}) => ( { @@ -53,7 +53,9 @@ function BaseAnchorForAttachmentsOnly({style, source = '', displayName = '', dow }} onPressIn={onPressIn} onPressOut={onPressOut} - onLongPress={(event) => showContextMenuForReport(event, anchor, report?.reportID ?? '-1', action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report))} + onLongPress={(event) => + showContextMenuForReport(event, anchor, report?.reportID ?? '-1', action, checkIfContextMenuActive, ReportUtils.isArchivedRoom(report, reportNameValuePairs)) + } shouldUseHapticsOnLongPress accessibilityLabel={displayName} role={CONST.ROLE.BUTTON} diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx index 368347847890..f0c5e29bc3ba 100644 --- a/src/components/AttachmentModal.tsx +++ b/src/components/AttachmentModal.tsx @@ -1,5 +1,5 @@ import {Str} from 'expensify-common'; -import React, {memo, useCallback, useEffect, useMemo, useState} from 'react'; +import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {Animated, Keyboard, View} from 'react-native'; import {GestureHandlerRootView} from 'react-native-gesture-handler'; import {withOnyx} from 'react-native-onyx'; @@ -28,6 +28,7 @@ import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type ModalType from '@src/types/utils/ModalType'; +import viewRef from '@src/types/utils/viewRef'; import AttachmentCarousel from './Attachments/AttachmentCarousel'; import AttachmentCarouselPagerContext from './Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext'; import AttachmentView from './Attachments/AttachmentView'; @@ -455,6 +456,8 @@ function AttachmentModal({ [closeModal, nope, sourceForAttachmentView], ); + const submitRef = useRef(null); + return ( <> { + if (!submitRef.current) { + return false; + } + return submitRef.current; + }} > {shouldUseNarrowLayout && } @@ -529,6 +538,7 @@ function AttachmentModal({ fallbackSource={fallbackSource} isUsedInAttachmentModal transactionID={transaction?.transactionID} + isUploaded={!isEmptyObject(report)} /> ) @@ -540,6 +550,7 @@ function AttachmentModal({ {({safeAreaPaddingBottomStyle}) => (