From dd0a8b6087fe0e70f3611d75f3ef613de08ead3c Mon Sep 17 00:00:00 2001 From: Levhita Date: Tue, 10 Sep 2024 15:11:46 -0600 Subject: [PATCH 1/6] * added eslint * added ability to save identityId * updated apiurl to /0 --- .env.example | 2 +- .eslintrc.cjs | 26 + main.js | 105 +- package-lock.json | 2533 ++++++++++++++++++++++++++++++++++++++++++++- package.json | 7 +- 5 files changed, 2578 insertions(+), 95 deletions(-) create mode 100644 .eslintrc.cjs diff --git a/.env.example b/.env.example index 46c7639..76b61bb 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ VITE_TOKEN_SERVER_URL=/api -VITE_API_URL=https://demo-api.incodesmile.com +VITE_API_URL=https://demo-api.incodesmile.com/0 VITE_SDK_URL=https://sdk.incode.com/sdk/onBoarding-1.72.0.js #Enable for 1:N diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..bc47b8f --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,26 @@ +module.exports = { + env: { + browser: true, + es2021: true + }, + extends: 'standard', + overrides: [ + { + env: { + node: true + }, + files: [ + '.eslintrc.{js,cjs}' + ], + parserOptions: { + sourceType: 'script' + } + } + ], + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module' + }, + rules: { + } +} diff --git a/main.js b/main.js index f1ad05d..df5bb99 100644 --- a/main.js +++ b/main.js @@ -1,75 +1,86 @@ -const tokenServerURL= import.meta.env.VITE_TOKEN_SERVER_URL -let onBoarding; +const tokenServerURL = import.meta.env.VITE_TOKEN_SERVER_URL +let onBoarding -const mainContainer = document.getElementById("app"); -const loginContainer = document.getElementById("login"); -const loginButton = document.getElementById("login-button"); +const mainContainer = document.getElementById('app') +const loginContainer = document.getElementById('login') +const loginButton = document.getElementById('login-button') -function showError(e=null) { - mainContainer.innerHTML = "Something Went Wrong, see console for details..."; +function showError (e = null) { + mainContainer.innerHTML = 'Something Went Wrong, see console for details...' console.log(e) } -function identifyUser(identityId){ - onBoarding.renderLogin(mainContainer,{ +function identifyUser (identityId) { + onBoarding.renderLogin(mainContainer, { onSuccess: async (response) => { - const {token, transactionId, interviewToken, faceMatch, customerId, email} = response; - if (faceMatch){ + const { token, transactionId, interviewToken, faceMatch, customerId, email } = response + if (faceMatch) { // User has an Incode Identity. // Verify using your backend that the faceMatch was actually valid and // not man in the middle attack const response = await fetch(`${tokenServerURL}/auth`, - { - method: "POST", - mode: "cors", - body: JSON.stringify({token,transactionId: transactionId, interviewToken}) + { + method: 'POST', + mode: 'cors', + body: JSON.stringify({ token, transactionId, interviewToken }) + } + ) + const verification = await response.json() + if (verification.verified === true) { + finish(customerId, email) + } else { + showError(new Error('FaceMatch is invalid.')) } - ); - const verification = await response.json(); - if(verification.verified===true){ - finish(customerId, email); } else { - showError(new Error("FaceMatch is invalid.")); + showError(new Error('Face did not match any user.')) } - } else { - showError(new Error("Face did not match any user.")); - } - }, - onError: error => { - showError(error) + }, + onError: error => { + showError(error) // User not found. Add rejection your logic here - }, - isOneToOne: true, - oneToOneProps: { - identityId: identityId, - } -}); + }, + isOneToOne: true, + oneToOneProps: { + identityId + } + }) } -function finish(customerId, email) { - mainContainer.innerHTML = `Sucessfull Login:
\n
CustomerId: ${customerId}
\n
Email: ${email}
`; +function finish (customerId, email) { + mainContainer.innerHTML = `Sucessfull Login:
\n
CustomerId: ${customerId}
\n
Email: ${email}
` } -async function app() { +async function app () { // Create the instance of incode linked to a client - const apiURL = import.meta.env.VITE_API_URL; + const apiURL = import.meta.env.VITE_API_URL // Enable for 1:N - //const clientId = import.meta.env.VITE_CLIENT_ID; - //const apiKey = import.meta.env.VITE_API_KEY; - + // const clientId = import.meta.env.VITE_CLIENT_ID; + // const apiKey = import.meta.env.VITE_API_KEY; + + const identityIdInput = document.getElementById('identity-id') + onBoarding = window.OnBoarding.create({ apiURL // clientId, // Enable for 1:N // apiKey // Enable for 1:N - }); - + }) + + // Get it from localstorage so dev doesn't have to type it everytime + const identityId = localStorage.getItem('identityId') + if (identityId) { + identityIdInput.value = identityId + } + // Empty the message and starting the flow - mainContainer.innerHTML = ""; - loginContainer.style.display="flex"; - loginButton.addEventListener('click', () =>{ - const identityIdInput = document.getElementById("identity-id"); - loginContainer.style.display="none"; + mainContainer.innerHTML = '' + loginContainer.style.display = 'flex' + loginButton.addEventListener('click', () => { + loginContainer.style.display = 'none' + + // Save it to localstorage so dev doesn't have to type it everytime + localStorage.setItem('identityId', identityIdInput.value) + identifyUser(identityIdInput.value) }) } -document.addEventListener("DOMContentLoaded", app); +document.addEventListener('DOMContentLoaded', app) diff --git a/package-lock.json b/package-lock.json index a46a0a6..7331616 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,12 @@ "name": "vite-vanilla-web-sdk", "version": "0.0.0", "dependencies": { - "dotenv": "^16.4.5" + "dotenv": "^16.4.5", + "eslint": "^8.57.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^16.6.2", + "eslint-plugin-promise": "^6.6.0" }, "devDependencies": { "vite": "^5.3.1", @@ -383,6 +388,122 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@octokit/auth-token": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", @@ -746,18 +867,216 @@ "win32" ] }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==" + }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "dev": true }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { "version": "1.7.7", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", @@ -769,12 +1088,113 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, "node_modules/before-after-hook": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/builtins": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", + "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/builtins/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "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/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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "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==" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -787,11 +1207,76 @@ "node": ">= 0.8" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, "dependencies": { "ms": "^2.1.3" }, @@ -804,6 +1289,43 @@ } } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -819,6 +1341,17 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", @@ -830,6 +1363,132 @@ "url": "https://dotenvx.com" } }, + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -868,9 +1527,438 @@ "@esbuild/win32-x64": "0.21.5" } }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-compat-utils/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-config-standard": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", + "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": "^8.0.1", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", + "eslint-plugin-promise": "^6.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.11.0.tgz", + "integrity": "sha512-gbBE5Hitek/oG6MUVj6sFuzEjA/ClzNflVrLovHi/JgLdC7fiN5gLAY1WIPW1a0V5I999MnsrvVrCOGmmVqDBQ==", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-es-x": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", + "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.11.0", + "eslint-compat-utils": "^0.5.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", + "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.9.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-n": { + "version": "16.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", + "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "builtins": "^5.0.1", + "eslint-plugin-es-x": "^7.5.0", + "get-tsconfig": "^4.7.0", + "globals": "^13.24.0", + "ignore": "^5.2.4", + "is-builtin-module": "^3.2.1", + "is-core-module": "^2.12.1", + "minimatch": "^3.1.2", + "resolve": "^1.22.2", + "semver": "^7.5.3" + }, + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-promise": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz", + "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "dev": true, "funding": [ @@ -888,6 +1976,14 @@ } } }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -902,6 +1998,11 @@ "node": ">= 6" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -916,66 +2017,877 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { - "mime-db": "1.52.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" + "node_modules/get-tsconfig": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", + "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "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", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "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==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "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==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/object-inspect": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=6" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" } }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.45", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.45.tgz", @@ -1004,12 +2916,120 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "4.21.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.2.tgz", @@ -1045,6 +3065,135 @@ "fsevents": "~2.3.2" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -1054,12 +3203,239 @@ "node": ">=0.10.0" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/universal-user-agent": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", "dev": true }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/vite": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.3.tgz", @@ -1137,11 +3513,76 @@ "vite": ">=3" } }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/package.json b/package.json index cb815be..6deb592 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,11 @@ "vite-plugin-mkcert": "^1.17.5" }, "dependencies": { - "dotenv": "^16.4.5" + "dotenv": "^16.4.5", + "eslint": "^8.57.0", + "eslint-config-standard": "^17.1.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^16.6.2", + "eslint-plugin-promise": "^6.6.0" } } From c604d8319fe4318d7916c7edb1ebad5eb8ec4443 Mon Sep 17 00:00:00 2001 From: Levhita Date: Tue, 17 Sep 2024 18:41:29 -0600 Subject: [PATCH 2/6] added upload document capabiity and get download link at the end --- main.js | 36 +++++++++++++++++++++++++++++++++--- small-sample-contract.pdf | Bin 0 -> 34709 bytes 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 small-sample-contract.pdf diff --git a/main.js b/main.js index df5bb99..c8f0b9c 100644 --- a/main.js +++ b/main.js @@ -27,7 +27,7 @@ function identifyUser (identityId) { ) const verification = await response.json() if (verification.verified === true) { - finish(customerId, email) + finish(customerId, email, interviewToken) } else { showError(new Error('FaceMatch is invalid.')) } @@ -46,8 +46,38 @@ function identifyUser (identityId) { }) } -function finish (customerId, email) { - mainContainer.innerHTML = `Sucessfull Login:
\n
CustomerId: ${customerId}
\n
Email: ${email}
` +function finish (customerId, email, interviewToken) { + mainContainer.innerHTML = `Sucessfull Login:
\n
CustomerId: ${customerId}
\n
Email: ${email}

` + const fileInput = document.getElementById('file-input') + const signButton = document.getElementById('sign-button') + + signButton.addEventListener('click', async () => { + const file = fileInput.files[0] + const base64Contract = await toBase64(file) + sign(interviewToken, base64Contract.replace('data:application/pdf;base64,', '')) + }) +} + +async function sign (interviewToken, base64Contract) { + const response = await fetch(`${tokenServerURL}/sign`, + { + method: 'POST', + mode: 'cors', + body: JSON.stringify({ interviewToken, base64Contract }) + } + ) + const signData = await response.json() + const { referenceId, documentUrl } = signData + mainContainer.innerHTML = `Sucessfull sign:
\n
refenceId: ${referenceId}
\n
DocumentUrl: Download
` +} + +function toBase64 (file) { + return new Promise((resolve, reject) => { + const reader = new FileReader() + reader.readAsDataURL(file) + reader.onload = () => resolve(reader.result) + reader.onerror = reject + }) } async function app () { diff --git a/small-sample-contract.pdf b/small-sample-contract.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8efc28230d6d87a123c977ec0e18be6e41a38d53 GIT binary patch literal 34709 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 Date: Tue, 17 Sep 2024 19:14:54 -0600 Subject: [PATCH 3/6] moved frontend to it's own folder --- README.md => frontend/README.md | 0 index.html => frontend/index.html | 0 main.js => frontend/main.js | 0 package-lock.json => frontend/package-lock.json | 0 package.json => frontend/package.json | 0 {public => frontend/public}/style.css | 0 vite.config.js => frontend/vite.config.js | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename README.md => frontend/README.md (100%) rename index.html => frontend/index.html (100%) rename main.js => frontend/main.js (100%) rename package-lock.json => frontend/package-lock.json (100%) rename package.json => frontend/package.json (100%) rename {public => frontend/public}/style.css (100%) rename vite.config.js => frontend/vite.config.js (100%) diff --git a/README.md b/frontend/README.md similarity index 100% rename from README.md rename to frontend/README.md diff --git a/index.html b/frontend/index.html similarity index 100% rename from index.html rename to frontend/index.html diff --git a/main.js b/frontend/main.js similarity index 100% rename from main.js rename to frontend/main.js diff --git a/package-lock.json b/frontend/package-lock.json similarity index 100% rename from package-lock.json rename to frontend/package-lock.json diff --git a/package.json b/frontend/package.json similarity index 100% rename from package.json rename to frontend/package.json diff --git a/public/style.css b/frontend/public/style.css similarity index 100% rename from public/style.css rename to frontend/public/style.css diff --git a/vite.config.js b/frontend/vite.config.js similarity index 100% rename from vite.config.js rename to frontend/vite.config.js From 7faa4d375665ec08ad77e054a744937b4dbe8762 Mon Sep 17 00:00:00 2001 From: Levhita Date: Tue, 17 Sep 2024 19:17:35 -0600 Subject: [PATCH 4/6] added backend --- backend/.gitignore | 2 + backend/README.md | 186 ++++++ backend/index.js | 489 +++++++++++++++ backend/package-lock.json | 1181 +++++++++++++++++++++++++++++++++++++ backend/package.json | 26 + backend/sample.env | 4 + 6 files changed, 1888 insertions(+) create mode 100644 backend/.gitignore create mode 100644 backend/README.md create mode 100644 backend/index.js create mode 100644 backend/package-lock.json create mode 100644 backend/package.json create mode 100644 backend/sample.env diff --git a/backend/.gitignore b/backend/.gitignore new file mode 100644 index 0000000..97aca2e --- /dev/null +++ b/backend/.gitignore @@ -0,0 +1,2 @@ +.env +node_modules \ No newline at end of file diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 0000000..3d38f7e --- /dev/null +++ b/backend/README.md @@ -0,0 +1,186 @@ +# Backend Server using NodeJS + +Backend Server that implements all the endpoints needed to run our Frontend Samples + +## Endpoints + +- GET `/start`: Call Incode's `/omni/start` API to create an Incode session which will include a `token` in the JSON response. This token can be shared with Incode SDK client apps to do token based initialization, which is a best practice. + +It also performs basic storage of sessions in the `sessions` directory to help implement `renderRedirectToMobile`in frontend. + +At session generation it will generate an `uniqueId` and save the session in `session/.json`, later if you call `/start` again passing a valid `uniqueId` it will retrieve the stored session instead of creating a new one. + +- GET `/onboarding-url`: Calls incodes `/omni/start` and then with the token calls `/0/omni/onboarding-url` to retrieve the unique onboarding-url for the newly created session. + +- GET `/onboarding-status`: Calls incodes `/omni/get/onboarding/status` API and return the onboarding status. + +Expects `interviewId` as query param. + +- GET `/fetch-score`: Calls incodes `/omni/get/score` API and return the score. + +Expects `interviewId` as query param. + +- POST `/auth`: Receives the information about a faceMatch attempt and verifies if it was correct and has not been tampered. + +- POST `/webhook`: Example webhook that reads the json data and return it back a response, from here you could fetch scores or OCR data when the status is ONBOARDING_FINISHED + +- POST `/approve`: Example webhook that reads the json data and if the status is ONBOARDING_FINISHED goes ahead and creates the identity using the `/omni/process/approve` endpoint. + +- POST `/finish`: Finishes the session, receives the token as a body parameter + +## Secure Credential Handling +We highly recommend to follow the 0 rule for your implementations, where all sensitive calls to incode's endpoints are done in the backend, keeping your apikey protected and just returning a `token` with the user session to the frontend. + +Within this sample you will find the only calls to a `/omni/` endpoints we recommend for you to have, it requires the usage of the `apikey`, all further calls must be done using only the generated `token` and be addresed to the `/0/omni` endpoints. + +## Prerequisites +This sample uses the global fetch API so you must use [Node 18](https://nodejs.org/en) or higher. + +## Local Development + +### Environment +Rename `sample.env` file to `.env` adding your subscription information: + +```env +API_URL=https://demo-api.incodesmile.com +API_KEY=you-api-key +FLOW_ID=Flow or Workflow Id from your Incode dashboard. +ADMIN_TOKEN=Needed for the webhooks to be able to fetch Scores and auto-approve +``` + +### Using NPM +Install the depencies with `npm install` +```bash +npm install +``` + +Then start the local server with the nodemon script, it will keep an eye on file changes and restart the local server if needed. +```bash +npm run nodemon +``` + +The server will accept petitions on `http://localhost:3000/` + +### Using Docker + +```bash +docker-compose build +docker-compose --env-file ./.env up +``` + +The server will accept petitions on `http://localhost:3000/` + +### Frontend development + +For development most of our frontend samples have a reverse proxy configured to serve `http://localhost:3000/` on `https://:5731/api` + +That way you avoid all problems related to CORS. + +### Webhook development + +For our systems to reach your server, you will need to expose the server to the internet with ngrok + +For your frontend to properly work in tandem with this server on your mobile phone for testing, you will need a public url with proper SSL configured, by far the easiest way to acchieve this with an ngrok account properly configured on your computer. You can visit `https://ngrok.com` to make a free account and do a quick setup. + +Then simply run the nodemon script, it will start the server in port 3000 and restart whenever a file is changed, leave it running. + +```bash +npm run nodemon +``` + +In another shell expose the server to internet through your computer ngrok account: + +```bash +ngrok http 3000 +``` + +Open the `Forwarding` adress in a web browser. The URL should look similar to this: `https://466c-47-152-68-211.ngrok-free.app`. + +Now you should be able to visit the following routes to receive the associated payloads: +1. `https://yourforwardingurl.app/start` +2. `https://yourforwardingurl.app/start?uniqueId=0e810732-6e7e-4512-aaa5-1ae2e1f8df46` +3. `https://yourforwardingurl.app/onboarding-url` +4. `https://yourforwardingurl.app/onboarding-url?redirectionUrl=https%3A%2F%2Fexample.com%2F` + +## Post Endpoints + +### Auth +Receives the information about a faceMatch attempt and verifies if it was correct and has not been tampered. + +All the parameters needed come as the result of execution of the [Render Login](https://docs.incode.com/docs/web/integration-guide/sdk-methods#renderlogin) component, +you can see a full example of it's usage in [Face Login Sample](https://github.com/Incode-Technologies-Example-Repos/javascript-samples/tree/main/face-login) + +```bash +curl --location 'https://yourforwardingurl.app/auth' \ +--header 'Content-Type: application/json' \ +--data '{ + "transactionId": "Transaction Id obtained at face login", + "token": "Token obtained at face login ", + "interviewToken": "Interview token obtained at face login", +}' +``` + +### Finish +Finishes a session, is the matching endpoint of `/start` + +```bash +curl --location 'https://yourforwardingurl.app/finish' \ +--header 'Content-Type: application/json' \ +--data '{ + + "token": "Token obtained at the /start endpoint ", + +}' +``` + +## Webhooks + +### Simplified Webhook +`https://yourforwardingurl.app/webhook` +We provide an example on how to read the data we send in the webhook calls, from here you could +fetch scores and OCR data, what you do with that is up to you. + +### Auto approve on PASS +`https://yourforwardingurl.app/approve` +We provide a more complex example where we fetch the scores and if the status is `OK` we then +approve the user to create his identity for face-login + +### Admin Token +For the approval and fetching of scores to work you will need an Admin Token, Admin tokens +require an executive user-password and have a 24 hour expiration, thus need a +more involved strategy to be generated, renewed, securely saved and shared to the app. + +For this simple test just use the following cURl, and add the generated token to the `.env` file, +you will need to refresh it after 24 hours. + +```bash +curl --location 'https://demo-api.incodesmile.com/executive/log-in' \ +--header 'Content-Type: application/json' \ +--header 'api-version: 1.0' \ +--header 'x-api-key: ' \ +--data '{ + "email": "••••••", + "password": "••••••" +}' +``` + +### How to test your code +To recreate the call and the format of the data sent by Incode you can use the following script: + +```bash +curl --location 'https://yourforwardingurl.app/webhook' \ +--header 'Content-Type: application/json' \ +--data '{ + "interviewId": "", + "onboardingStatus": "ONBOARDING_FINISHED", + "clientId": "", + "flowId": "" +}' +``` + +## Dependencies + +* **nodejs18+**: JavaScript runtime built on Chrome's V8 JavaScript engine. +* **express**: Web server framework. +* **dotenv**: Used to access environment variables. +* **ngrok**: Unified ingress platform used to expose your local server to the internet. \ No newline at end of file diff --git a/backend/index.js b/backend/index.js new file mode 100644 index 0000000..4c45e0d --- /dev/null +++ b/backend/index.js @@ -0,0 +1,489 @@ +const express = require('express'); +const dotenv = require('dotenv'); +const cors = require('cors'); +const { v4: uuidv4, validate: isUUID } = require('uuid'); +const fs = require('node:fs'); + +const app = express(); +dotenv.config(); + +app.use(cors()) +// Middleware to handle raw body data +app.use(express.raw({ type: '*/*' })); + +const defaultHeader = { + 'Content-Type': "application/json", + 'x-api-key': process.env.API_KEY, + 'api-version': '1.0' +}; + +// Admin Token + ApiKey are needed for approving +const adminHeader = { + 'Content-Type': "application/json", + 'x-api-key': process.env.API_KEY, + 'X-Incode-Hardware-Id': process.env.ADMIN_TOKEN, + 'api-version': '1.0' +}; + +// Call Incode's `omni/start` API to create an Incode session which will include a +// token in the JSON response. +app.get('/start', async (req, res) => { + let uniqueId = req.query.uniqueId; + // We retrieve a session that was already started and from which we have stored. + if (uniqueId) { + try { + const { token } = readSession(uniqueId); + // The interviewId is also saved in the session, but you shouldn't return it to the frontend. + res.json({token, uniqueId}); + } catch (e) { + res.status(400).send({success:false, error: e.message}); + } + return; + } + + // We create a new random uniqueId to associate the session + uniqueId = uuidv4(); + + const startUrl = `${process.env.API_URL}/omni/start`; + const startParams = { + configurationId: process.env.FLOW_ID, + language: "en-US", + // redirectionUrl: "https://example.com?custom_parameter=some+value", + // externalCustomerId: "the id of the customer in your system", + }; + try{ + const startData = await doPost(startUrl, startParams, defaultHeader); + const {token, interviewId} = startData; + // To the session we save the interviewId for internal purposes + writeSession(uniqueId, {token, interviewId, uniqueId}); + // But we never return it to the frontend + res.json({token, uniqueId}); + } catch(e) { + console.log(e.message); + res.status(500).send({success:false, error: e.message}); + return; + } +}); + +// Calls incodes `omni/start` and then with the token calls `0/omni/onboarding-url` +// to retrieve the unique onboarding-url for the newly created session. +app.get('/onboarding-url', async (req, res) => { + const startUrl = `${process.env.API_URL}/omni/start`; + const startParams = { + configurationId: process.env.FLOW_ID, + language: "en-US", + // redirectionUrl: "https://example.com?custom_parameter=some+value", + // externalCustomerId: "the id of the customer in your system", + }; + + let startData = null; + try{ + startData = await doPost(startUrl, startParams, defaultHeader); + } catch(e) { + console.log(e.message); + res.status(500).send({success:false, error: e.message}); + return; + } + const {token, interviewId} = startData; + + const onboardingHeader = {...defaultHeader}; + onboardingHeader['X-Incode-Hardware-Id'] = startData.token; + + const onboardingUrl = `${process.env.API_URL}/0/omni/onboarding-url`; + + let onboardingUrlData= null; + try{ + onboardingUrlData = await doGet(onboardingUrl, {}, onboardingHeader); + } catch(e) { + console.log(e.message); + res.status(500).send({success:false, error: e.message}); + return; + } + session ={ success:true, token, interviewId, url: onboardingUrlData.url } + res.json(session); +}); + + + +// Checks if an onboarding has been finished against a local method of Storage +app.get('/onboarding-status', async (req, res) => { + // Get the interviewId from query parameters + const interviewId = req.query.interviewId; + if (!interviewId) { + res.status(400).send({success:false, error:'Missing required parameter interviewId'}); + return; + } + + const statusURL = `${process.env.API_URL}/omni/get/onboarding/status`; + try { + const response = await doGet(statusURL, {id:interviewId}, adminHeader); + onboardingStatus = response.onboardingStatus; + res.status(200).send({success:true, onboardingStatus}) + } catch(e) { + console.log(e.message); + res.status(500).send({success:false, error: e.message}); + } +}); + +// Checks if an onboarding has been finished against a local method of Storage +app.get('/fetch-score', async (req, res) => { + // Get the interviewId from query parameters + const interviewId = req.query.interviewId; + if (!interviewId) { + res.status(400).send({success:false, error:'Missing required parameter interviewId'}); + return; + } + + //Get the token of the session from the headers + let token = req.headers["x-token"]; + if (!token) { + res.status(400).send({success:false, error:'Missing required header X-Token'}); + return; + } + + scoreHeader = {...defaultHeader}; + scoreHeader['X-Incode-Hardware-Id'] = token; + + //Let's find out the score + const scoreUrl = `${process.env.API_URL}/omni/get/score`; + let onboardingScore = null + try { + onboardingScore = await doGet(scoreUrl, {id:interviewId}, scoreHeader); + } catch(e) { + console.log(e.message); + res.status(500).send({success:false, error: e.message}); + return; + } + + // Onboarding Score has a lot of information that might interest you + // https://docs.incode.com/docs/omni-api/api/onboarding#fetch-scores + if (onboardingScore?.overall?.status==='OK'){ + // Session passed with OK here you would procced to save user data into + // your database or any other process your bussiness logic requires. + console.log('User passed with OK'); + res.json({success:true, score: 'OK'}); + } else { + console.log("User didn't passed"); + res.json({success:true, score: 'FAIL'}); + } + +}); + +// Webhook to receive onboarding status, configure it in +// incode dasboard > settings > webhook > onboarding status +app.post('/webhook', async (req, res) => { + // Handle the received webhook data + const webhookData = JSON.parse(req.body.toString()); + + // Last Step of the onboarding, now you can ask for the score. + if(webhookData.onboardingStatus==="ONBOARDING_FINISHED"){ + + console.log('User finished onboarding'); + + + const scoreUrl = `${process.env.API_URL}/omni/get/score`; + let onboardingScore = {} + try { + onboardingScore = await doGet(scoreUrl, {id:webhookData.interviewId}, adminHeader); + } catch(e) { + console.log(e.message); + } + // Onboarding Score has a lot of information that might interest you + // https://docs.incode.com/docs/omni-api/api/onboarding#fetch-scores + if (onboardingScore?.overall?.status==='OK'){ + // Session passed with OK here you would procced to save user data into + // your database or any other process your bussiness logic requires. + console.log('User passed with OK'); + } else { + console.log('User did not passed'); + } + } + + + // Process received data (for demonstration, just returning the received payload + // and include the timestamp) + response = { + timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), + success: true, + data: webhookData + } + res.status(200).send(response); + + // Write to a log so you can debug it. + console.log(response); +}); + +// Webhook to receive onboarding status, configure it in +// incode dasboard > settings > webhook > onboarding status +// This endpoint will auto-approve(create an identity) for +// any sessions that PASS. +app.post('/approve', async (req, res) => { + // Handle the received webhook data + const webhookData = JSON.parse(req.body.toString()); + + if(webhookData.onboardingStatus==="ONBOARDING_FINISHED"){ + // Admin Token + ApiKey are needed for approving and fetching scores + const adminHeader = { + 'Content-Type': "application/json", + //'x-api-key': process.env.API_KEY, + 'X-Incode-Hardware-Id': process.env.ADMIN_TOKEN, + 'api-version': '1.0' + }; + + const scoreUrl = `${process.env.API_URL}/omni/get/score`; + const onboardingScore = await doGet(scoreUrl, {id:webhookData.interviewId}, adminHeader); + + //Onboarding Score has a lot of information that might interest you https://docs.incode.com/docs/omni-api/api/onboarding#fetch-scores + + if (onboardingScore.overall.status==='OK'){ + + const approveUrl = `${process.env.API_URL}/omni/process/approve?interviewId=${webhookData.interviewId}`; + const identityData = await doPost(approveUrl,{}, adminHeader); + + response = { + timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), + success:true, + data: identityData + } + // This would return something like this: + // { + // timestamp: '2024-01-04 00:38:28', + // success: true, + // data: { + // success: true, + // uuid: '6595c84ce69d469f69ad39fb', + // token: 'eyJhbGciOiJ4UzI1NiJ9.eyJleHRlcm5hbFVzZXJJZCI6IjY1OTVjODRjZTY5ZDk2OWY2OWF33kMjlmYiIsInJvbGUiOiJBQ0NFU5MiLCJrZXlSZWYiOiI2MmZlNjQ3ZTJjODJlOTVhZDNhZTRjMzkiLCJleHAiOjE3MTIxOTExMDksImlhdCI6MTcwNDMyODcwOX0.fbhlcTQrp-h-spgxKU2J7wpEBN4I4iOYG5CBwuQKPLQ72', + // totalScore: 'OK', + // existingCustomer: false + // } + // } + // UUID: You can save the generated uuid of your user to link your user with our systems. + // Token: Is long lived and could be used to do calls in the name of the user if needed. + // Existing Customer: Will return true in case the user was already in the database, in such case we are returning the UUID of the already existing user. + + res.status(200).send(response); + console.log(response); + } else { + response = { + timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), + success: false, + error: "Session didn't PASS, identity was not created" + } + res.status(200).send(response); + console.log(response) + } + + } else { + // Process received data (for demonstration, just returning the received payload + // and include the timestamp) + response = { + timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), + success: true, + data: JSON.parse(webhookData.toString()) + } + res.status(200).send(response); + + // Write to a log so you can debug it. + console.log(response); + } +}); + +// Receives the information about a faceMatch attempt and verifies +// if it was correct and has not been tampered. +app.post('/auth', async (req, res) => { + const faceMatchData = JSON.parse(req.body.toString()); + const {transactionId, token, interviewToken} = faceMatchData; + const verifyAttemptUrl = `${process.env.API_URL}/omni/authentication/verify`; + + const params = { transactionId, token, interviewToken }; + let verificationData={}; + try{ + verificationData = await doPost(verifyAttemptUrl, params, adminHeader); + } catch(e) { + console.log(e.message); + res.status(500).send({success:false, error: e.message}); + return; + } + log = { + timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), + data: {...params,...verificationData} + } + res.status(200).send(verificationData); + + // Write to a log so you can debug it. + console.log(log); +}); + +// if it was correct and has not been tampered. +app.post('/sign', async (req, res) => { + /** Receive contract and token as parameters */ + const signParamsData = JSON.parse(req.body.toString()); + const { interviewToken, base64Contract } = signParamsData; + + /** Prepare the authorization header that will be used in calls to incode */ + sessionHeader = {...defaultHeader}; + sessionHeader['X-Incode-Hardware-Id'] = interviewToken; + + let response = {}; + try{ + /** Get URL where to upload the contract */ + const generateDocumentUploadUrl = `${process.env.API_URL}/omni/es/generateDocumentUploadUrl`; + const documentURLData = await doPost(generateDocumentUploadUrl, { token:interviewToken }, sessionHeader); + const {referenceId, preSignedUrl} = documentURLData + + /** Upload contract to AWS presigned url */ + const binary = Buffer.from(base64Contract, 'base64'); + const uploadResponse = await fetch(preSignedUrl, { + method: "PUT", + headers: {"Content-Type": "application/pdf"}, + body: binary, + }) + if (!uploadResponse.ok) { + throw new Error('Uploading contract failed with code ' + uploadResponse.status) + } + + /** Sign the document */ + const signURL = `${process.env.API_URL}/omni/es/process/sign`; + const signData = await doPost(signURL, + { + "documentRef": referenceId, + "userConsented": true + }, + sessionHeader + ); + const {success} = signData + if (!success) { throw new Error('Sign failed');} + + /** Fetch all signed document references */ + const documentsSignedURL = `${process.env.API_URL}/omni/es/documents/signed`; + const documentsSignedData = await doGet(documentsSignedURL, {}, sessionHeader); + const {documents} = documentsSignedData + + /** This endpoint returns all documents, find the one just signed matching by referenceId*/ + const justSigned = documents.find(document => document.documentRef=== referenceId) + + /** Return referenceId and documentUrl */ + const {documentRef, documentUrl} = justSigned + response = {referenceId, documentUrl} + + } catch(e) { + console.log(e.message); + res.status(500).send({success:false, error: e.message}); + return; + } + log = { + timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), + data: {...response} + } + res.status(200).send(response); + // Write to a log so you can debug it. + console.log(log); +}); + +// Finishes the session started at /start +app.post('/finish', async (req, res) => { + let finishStatus = null; + const data = JSON.parse(req.body.toString()); + const {token} = data; + + + if (!token) { + res.status(400).send({success:false, error:'Missing required parameter token'}); + return; + } + + header = {...defaultHeader}; + header['X-Incode-Hardware-Id'] = token; + + //Let's find out the score + const url = `${process.env.API_URL}/omni/finish-status`; let onboardingScore = null + try { + finishStatus = await doGet(url, {}, header); + } catch(e) { + console.log(e.message); + res.status(500).send({success:false, error: e.message}); + return; + } + + log = { + timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), + data: {finishStatus} + } + res.status(200).send(finishStatus); + + // Write to a log so you can debug it. + console.log(log); +}); + +app.get('*', function(req, res){ + res.status(404).json({error: `Cannot GET ${req.url}`}); +}); + +app.post('*', function(req, res){ + res.status(404).json({error: `Cannot POST ${req.url}`}); +}); + +// Utility functions +const doPost = async (url, bodyparams, headers) => { + try { + const response = await fetch(url, { method: 'POST', body: JSON.stringify(bodyparams), headers}); + if (!response.ok) { + //console.log(response.json()); + throw new Error('Request failed with code ' + response.status) + } + return response.json(); + } catch(e) { + console.log({url, bodyparams, headers}) + throw new Error('HTTP Post Error: ' + e.message) + } +} + +const doGet = async (url, params, headers) => { + try { + const response = await fetch(`${url}?` + new URLSearchParams(params), {method: 'GET', headers}); + if (!response.ok) { + //console.log(await response.json()); + throw new Error('Request failed with code ' + response.status) + } + return response.json(); + } catch(e) { + console.log({url, params, headers}) + throw new Error('HTTP Get Error: ' + e.message) + } +} + +/* Session Helper Functions + * For this example we simply save the session as json file in the /sessions folder + * in a real application you would save this information in a database. + **/ + +function writeSession(uniqueId, data){ + const content = JSON.stringify(data, null, ' '); + try { + fs.writeFileSync(`sessions/${uniqueId}.json`, content); + } catch (err) { + console.error(err); + } +} + +function readSession(uniqueId){ + if(!isUUID(uniqueId) || !fs.existsSync(`sessions/${uniqueId}.json`)){ + throw new Error('Invalid uniqueId'); + } + const rawData = fs.readFileSync(`sessions/${uniqueId}.json`,{ encoding: 'utf8', flag: 'r' }); + try { + return JSON.parse(rawData); + } catch(e){ + throw new Error('Session data corrupted'); + } +} +/* End Session Helper Functions **/ + +// Listen for HTTP +const httpPort = 3000; + +app.listen(httpPort, () => { + console.log(`HTTP listening on: http://localhost:${httpPort}/`); +}); + +module.exports = app; diff --git a/backend/package-lock.json b/backend/package-lock.json new file mode 100644 index 0000000..45e6d1e --- /dev/null +++ b/backend/package-lock.json @@ -0,0 +1,1181 @@ +{ + "name": "token-and-url-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "token-and-url-server", + "version": "1.0.0", + "license": "Apache-2.0", + "dependencies": { + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "pdf-to-base64": "^1.0.3", + "uuid": "^9.0.1" + }, + "devDependencies": { + "nodemon": "^3.1.3" + }, + "engines": { + "node": ">= 18.0.0" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nodemon": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.3.tgz", + "integrity": "sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/pdf-to-base64": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pdf-to-base64/-/pdf-to-base64-1.0.3.tgz", + "integrity": "sha512-hReb9RzE8/kZE9Sjq913XXg3t8tyNn4VyDFs3VfXtMEIr/IQlKih+Te8EakJTkps8HxjUlULM5007xkp/DXs/Q==", + "dependencies": { + "node-fetch": "^2.2.0" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..a53344c --- /dev/null +++ b/backend/package.json @@ -0,0 +1,26 @@ +{ + "name": "token-and-url-server", + "description": "A simple Incode token and url service.", + "version": "1.0.0", + "private": true, + "main": "index.js", + "scripts": { + "start": "node index.js", + "nodemon": "nodemon" + }, + "engines": { + "node": ">= 18.0.0" + }, + "author": "Incode LLC", + "license": "Apache-2.0", + "dependencies": { + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.19.2", + "pdf-to-base64": "^1.0.3", + "uuid": "^9.0.1" + }, + "devDependencies": { + "nodemon": "^3.1.3" + } +} diff --git a/backend/sample.env b/backend/sample.env new file mode 100644 index 0000000..183b50b --- /dev/null +++ b/backend/sample.env @@ -0,0 +1,4 @@ +API_URL=https://demo-api.incodesmile.com +API_KEY=you-api-key +FLOW_ID=Flow or Workflow Id from your Incode dashboard. +ADMIN_TOKEN=Needed for the webhooks to be able to fetch Scores and auto-approve \ No newline at end of file From c36e4265032dc7930acc80683eab4db4e51f2071 Mon Sep 17 00:00:00 2001 From: Levhita Date: Tue, 17 Sep 2024 19:31:49 -0600 Subject: [PATCH 5/6] *moved missing files to frontend * changed endpoint to verify --- .gitignore | 23 -- backend/index.js | 347 +----------------------- .env.example => frontend/.env.example | 2 +- .eslintrc.cjs => frontend/.eslintrc.cjs | 0 frontend/.gitignore | 24 ++ frontend/main.js | 7 +- 6 files changed, 41 insertions(+), 362 deletions(-) rename .env.example => frontend/.env.example (87%) rename .eslintrc.cjs => frontend/.eslintrc.cjs (100%) create mode 100644 frontend/.gitignore diff --git a/.gitignore b/.gitignore index a547bf3..e43b0f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea .DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/backend/index.js b/backend/index.js index 4c45e0d..43d687d 100644 --- a/backend/index.js +++ b/backend/index.js @@ -1,7 +1,6 @@ const express = require('express'); const dotenv = require('dotenv'); const cors = require('cors'); -const { v4: uuidv4, validate: isUUID } = require('uuid'); const fs = require('node:fs'); const app = express(); @@ -25,280 +24,18 @@ const adminHeader = { 'api-version': '1.0' }; -// Call Incode's `omni/start` API to create an Incode session which will include a -// token in the JSON response. -app.get('/start', async (req, res) => { - let uniqueId = req.query.uniqueId; - // We retrieve a session that was already started and from which we have stored. - if (uniqueId) { - try { - const { token } = readSession(uniqueId); - // The interviewId is also saved in the session, but you shouldn't return it to the frontend. - res.json({token, uniqueId}); - } catch (e) { - res.status(400).send({success:false, error: e.message}); - } - return; - } - - // We create a new random uniqueId to associate the session - uniqueId = uuidv4(); - - const startUrl = `${process.env.API_URL}/omni/start`; - const startParams = { - configurationId: process.env.FLOW_ID, - language: "en-US", - // redirectionUrl: "https://example.com?custom_parameter=some+value", - // externalCustomerId: "the id of the customer in your system", - }; - try{ - const startData = await doPost(startUrl, startParams, defaultHeader); - const {token, interviewId} = startData; - // To the session we save the interviewId for internal purposes - writeSession(uniqueId, {token, interviewId, uniqueId}); - // But we never return it to the frontend - res.json({token, uniqueId}); - } catch(e) { - console.log(e.message); - res.status(500).send({success:false, error: e.message}); - return; - } -}); - -// Calls incodes `omni/start` and then with the token calls `0/omni/onboarding-url` -// to retrieve the unique onboarding-url for the newly created session. -app.get('/onboarding-url', async (req, res) => { - const startUrl = `${process.env.API_URL}/omni/start`; - const startParams = { - configurationId: process.env.FLOW_ID, - language: "en-US", - // redirectionUrl: "https://example.com?custom_parameter=some+value", - // externalCustomerId: "the id of the customer in your system", - }; - - let startData = null; - try{ - startData = await doPost(startUrl, startParams, defaultHeader); - } catch(e) { - console.log(e.message); - res.status(500).send({success:false, error: e.message}); - return; - } - const {token, interviewId} = startData; - - const onboardingHeader = {...defaultHeader}; - onboardingHeader['X-Incode-Hardware-Id'] = startData.token; - - const onboardingUrl = `${process.env.API_URL}/0/omni/onboarding-url`; - - let onboardingUrlData= null; - try{ - onboardingUrlData = await doGet(onboardingUrl, {}, onboardingHeader); - } catch(e) { - console.log(e.message); - res.status(500).send({success:false, error: e.message}); - return; - } - session ={ success:true, token, interviewId, url: onboardingUrlData.url } - res.json(session); -}); - - - -// Checks if an onboarding has been finished against a local method of Storage -app.get('/onboarding-status', async (req, res) => { - // Get the interviewId from query parameters - const interviewId = req.query.interviewId; - if (!interviewId) { - res.status(400).send({success:false, error:'Missing required parameter interviewId'}); - return; - } - - const statusURL = `${process.env.API_URL}/omni/get/onboarding/status`; - try { - const response = await doGet(statusURL, {id:interviewId}, adminHeader); - onboardingStatus = response.onboardingStatus; - res.status(200).send({success:true, onboardingStatus}) - } catch(e) { - console.log(e.message); - res.status(500).send({success:false, error: e.message}); - } -}); - -// Checks if an onboarding has been finished against a local method of Storage -app.get('/fetch-score', async (req, res) => { - // Get the interviewId from query parameters - const interviewId = req.query.interviewId; - if (!interviewId) { - res.status(400).send({success:false, error:'Missing required parameter interviewId'}); - return; - } - - //Get the token of the session from the headers - let token = req.headers["x-token"]; - if (!token) { - res.status(400).send({success:false, error:'Missing required header X-Token'}); - return; - } - - scoreHeader = {...defaultHeader}; - scoreHeader['X-Incode-Hardware-Id'] = token; - - //Let's find out the score - const scoreUrl = `${process.env.API_URL}/omni/get/score`; - let onboardingScore = null - try { - onboardingScore = await doGet(scoreUrl, {id:interviewId}, scoreHeader); - } catch(e) { - console.log(e.message); - res.status(500).send({success:false, error: e.message}); - return; - } - - // Onboarding Score has a lot of information that might interest you - // https://docs.incode.com/docs/omni-api/api/onboarding#fetch-scores - if (onboardingScore?.overall?.status==='OK'){ - // Session passed with OK here you would procced to save user data into - // your database or any other process your bussiness logic requires. - console.log('User passed with OK'); - res.json({success:true, score: 'OK'}); - } else { - console.log("User didn't passed"); - res.json({success:true, score: 'FAIL'}); - } - -}); - -// Webhook to receive onboarding status, configure it in -// incode dasboard > settings > webhook > onboarding status -app.post('/webhook', async (req, res) => { - // Handle the received webhook data - const webhookData = JSON.parse(req.body.toString()); - - // Last Step of the onboarding, now you can ask for the score. - if(webhookData.onboardingStatus==="ONBOARDING_FINISHED"){ - - console.log('User finished onboarding'); - - - const scoreUrl = `${process.env.API_URL}/omni/get/score`; - let onboardingScore = {} - try { - onboardingScore = await doGet(scoreUrl, {id:webhookData.interviewId}, adminHeader); - } catch(e) { - console.log(e.message); - } - // Onboarding Score has a lot of information that might interest you - // https://docs.incode.com/docs/omni-api/api/onboarding#fetch-scores - if (onboardingScore?.overall?.status==='OK'){ - // Session passed with OK here you would procced to save user data into - // your database or any other process your bussiness logic requires. - console.log('User passed with OK'); - } else { - console.log('User did not passed'); - } - } - - - // Process received data (for demonstration, just returning the received payload - // and include the timestamp) - response = { - timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), - success: true, - data: webhookData - } - res.status(200).send(response); - - // Write to a log so you can debug it. - console.log(response); -}); - -// Webhook to receive onboarding status, configure it in -// incode dasboard > settings > webhook > onboarding status -// This endpoint will auto-approve(create an identity) for -// any sessions that PASS. -app.post('/approve', async (req, res) => { - // Handle the received webhook data - const webhookData = JSON.parse(req.body.toString()); - - if(webhookData.onboardingStatus==="ONBOARDING_FINISHED"){ - // Admin Token + ApiKey are needed for approving and fetching scores - const adminHeader = { - 'Content-Type': "application/json", - //'x-api-key': process.env.API_KEY, - 'X-Incode-Hardware-Id': process.env.ADMIN_TOKEN, - 'api-version': '1.0' - }; - - const scoreUrl = `${process.env.API_URL}/omni/get/score`; - const onboardingScore = await doGet(scoreUrl, {id:webhookData.interviewId}, adminHeader); - - //Onboarding Score has a lot of information that might interest you https://docs.incode.com/docs/omni-api/api/onboarding#fetch-scores - - if (onboardingScore.overall.status==='OK'){ - - const approveUrl = `${process.env.API_URL}/omni/process/approve?interviewId=${webhookData.interviewId}`; - const identityData = await doPost(approveUrl,{}, adminHeader); - - response = { - timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), - success:true, - data: identityData - } - // This would return something like this: - // { - // timestamp: '2024-01-04 00:38:28', - // success: true, - // data: { - // success: true, - // uuid: '6595c84ce69d469f69ad39fb', - // token: 'eyJhbGciOiJ4UzI1NiJ9.eyJleHRlcm5hbFVzZXJJZCI6IjY1OTVjODRjZTY5ZDk2OWY2OWF33kMjlmYiIsInJvbGUiOiJBQ0NFU5MiLCJrZXlSZWYiOiI2MmZlNjQ3ZTJjODJlOTVhZDNhZTRjMzkiLCJleHAiOjE3MTIxOTExMDksImlhdCI6MTcwNDMyODcwOX0.fbhlcTQrp-h-spgxKU2J7wpEBN4I4iOYG5CBwuQKPLQ72', - // totalScore: 'OK', - // existingCustomer: false - // } - // } - // UUID: You can save the generated uuid of your user to link your user with our systems. - // Token: Is long lived and could be used to do calls in the name of the user if needed. - // Existing Customer: Will return true in case the user was already in the database, in such case we are returning the UUID of the already existing user. - - res.status(200).send(response); - console.log(response); - } else { - response = { - timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), - success: false, - error: "Session didn't PASS, identity was not created" - } - res.status(200).send(response); - console.log(response) - } - - } else { - // Process received data (for demonstration, just returning the received payload - // and include the timestamp) - response = { - timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), - success: true, - data: JSON.parse(webhookData.toString()) - } - res.status(200).send(response); - - // Write to a log so you can debug it. - console.log(response); - } -}); - // Receives the information about a faceMatch attempt and verifies // if it was correct and has not been tampered. -app.post('/auth', async (req, res) => { - const faceMatchData = JSON.parse(req.body.toString()); - const {transactionId, token, interviewToken} = faceMatchData; - const verifyAttemptUrl = `${process.env.API_URL}/omni/authentication/verify`; - - const params = { transactionId, token, interviewToken }; - let verificationData={}; +app.post('/verify', async (req, res) => { + let response={}; try{ - verificationData = await doPost(verifyAttemptUrl, params, adminHeader); + /** Get parameters from body */ + const faceMatchData = JSON.parse(req.body.toString()); + const {transactionId, token, interviewToken} = faceMatchData; + const verificationParams = { transactionId, token, interviewToken }; + + const verifyAttemptUrl = `${process.env.API_URL}/omni/authentication/verify`; + response = await doPost(verifyAttemptUrl, verificationParams, adminHeader); } catch(e) { console.log(e.message); res.status(500).send({success:false, error: e.message}); @@ -306,9 +43,9 @@ app.post('/auth', async (req, res) => { } log = { timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), - data: {...params,...verificationData} + data: {verificationParams, response} } - res.status(200).send(verificationData); + res.status(200).send(response); // Write to a log so you can debug it. console.log(log); @@ -373,47 +110,13 @@ app.post('/sign', async (req, res) => { } log = { timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), - data: {...response} + data: {signParamsData, response} } res.status(200).send(response); // Write to a log so you can debug it. console.log(log); }); -// Finishes the session started at /start -app.post('/finish', async (req, res) => { - let finishStatus = null; - const data = JSON.parse(req.body.toString()); - const {token} = data; - - - if (!token) { - res.status(400).send({success:false, error:'Missing required parameter token'}); - return; - } - - header = {...defaultHeader}; - header['X-Incode-Hardware-Id'] = token; - - //Let's find out the score - const url = `${process.env.API_URL}/omni/finish-status`; let onboardingScore = null - try { - finishStatus = await doGet(url, {}, header); - } catch(e) { - console.log(e.message); - res.status(500).send({success:false, error: e.message}); - return; - } - - log = { - timestamp: new Date().toISOString().slice(0, 19).replace('T', ' '), - data: {finishStatus} - } - res.status(200).send(finishStatus); - - // Write to a log so you can debug it. - console.log(log); -}); app.get('*', function(req, res){ res.status(404).json({error: `Cannot GET ${req.url}`}); @@ -452,32 +155,6 @@ const doGet = async (url, params, headers) => { } } -/* Session Helper Functions - * For this example we simply save the session as json file in the /sessions folder - * in a real application you would save this information in a database. - **/ - -function writeSession(uniqueId, data){ - const content = JSON.stringify(data, null, ' '); - try { - fs.writeFileSync(`sessions/${uniqueId}.json`, content); - } catch (err) { - console.error(err); - } -} - -function readSession(uniqueId){ - if(!isUUID(uniqueId) || !fs.existsSync(`sessions/${uniqueId}.json`)){ - throw new Error('Invalid uniqueId'); - } - const rawData = fs.readFileSync(`sessions/${uniqueId}.json`,{ encoding: 'utf8', flag: 'r' }); - try { - return JSON.parse(rawData); - } catch(e){ - throw new Error('Session data corrupted'); - } -} -/* End Session Helper Functions **/ // Listen for HTTP const httpPort = 3000; diff --git a/.env.example b/frontend/.env.example similarity index 87% rename from .env.example rename to frontend/.env.example index 76b61bb..34a0fb3 100644 --- a/.env.example +++ b/frontend/.env.example @@ -1,4 +1,4 @@ -VITE_TOKEN_SERVER_URL=/api +VITE_SERVER_URL=/api VITE_API_URL=https://demo-api.incodesmile.com/0 VITE_SDK_URL=https://sdk.incode.com/sdk/onBoarding-1.72.0.js diff --git a/.eslintrc.cjs b/frontend/.eslintrc.cjs similarity index 100% rename from .eslintrc.cjs rename to frontend/.eslintrc.cjs diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend/main.js b/frontend/main.js index c8f0b9c..abd5594 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -1,4 +1,5 @@ -const tokenServerURL = import.meta.env.VITE_TOKEN_SERVER_URL +const ServerUrl = import.meta.env.VITE_SERVER_URL +/** Imports incode instance added with script tag **/ let onBoarding const mainContainer = document.getElementById('app') @@ -18,7 +19,7 @@ function identifyUser (identityId) { // User has an Incode Identity. // Verify using your backend that the faceMatch was actually valid and // not man in the middle attack - const response = await fetch(`${tokenServerURL}/auth`, + const response = await fetch(`${ServerUrl}/verify`, { method: 'POST', mode: 'cors', @@ -59,7 +60,7 @@ function finish (customerId, email, interviewToken) { } async function sign (interviewToken, base64Contract) { - const response = await fetch(`${tokenServerURL}/sign`, + const response = await fetch(`${ServerUrl}/sign`, { method: 'POST', mode: 'cors', From a36f6cca7a78f1aa0130af8e6b1095bb826faa52 Mon Sep 17 00:00:00 2001 From: Levhita Date: Tue, 17 Sep 2024 19:43:23 -0600 Subject: [PATCH 6/6] improved ui and messaging --- backend/index.js | 15 ++++++++------- frontend/main.js | 17 +++++++++++++---- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/backend/index.js b/backend/index.js index 43d687d..8ab93b1 100644 --- a/backend/index.js +++ b/backend/index.js @@ -27,13 +27,14 @@ const adminHeader = { // Receives the information about a faceMatch attempt and verifies // if it was correct and has not been tampered. app.post('/verify', async (req, res) => { + /** Get parameters from body */ + const faceMatchData = JSON.parse(req.body.toString()); + const {transactionId, token, interviewToken} = faceMatchData; + const verificationParams = { transactionId, token, interviewToken }; + let response={}; try{ - /** Get parameters from body */ - const faceMatchData = JSON.parse(req.body.toString()); - const {transactionId, token, interviewToken} = faceMatchData; - const verificationParams = { transactionId, token, interviewToken }; - + /** Run Call against incode API **/ const verifyAttemptUrl = `${process.env.API_URL}/omni/authentication/verify`; response = await doPost(verifyAttemptUrl, verificationParams, adminHeader); } catch(e) { @@ -102,7 +103,7 @@ app.post('/sign', async (req, res) => { /** Return referenceId and documentUrl */ const {documentRef, documentUrl} = justSigned response = {referenceId, documentUrl} - + } catch(e) { console.log(e.message); res.status(500).send({success:false, error: e.message}); @@ -131,7 +132,7 @@ const doPost = async (url, bodyparams, headers) => { try { const response = await fetch(url, { method: 'POST', body: JSON.stringify(bodyparams), headers}); if (!response.ok) { - //console.log(response.json()); + //console.log(response.json()); throw new Error('Request failed with code ' + response.status) } return response.json(); diff --git a/frontend/main.js b/frontend/main.js index abd5594..caa37fe 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -16,9 +16,9 @@ function identifyUser (identityId) { onSuccess: async (response) => { const { token, transactionId, interviewToken, faceMatch, customerId, email } = response if (faceMatch) { - // User has an Incode Identity. - // Verify using your backend that the faceMatch was actually valid and - // not man in the middle attack + /** User has an Incode Identity. + * Verify using your backend that the faceMatch was actually valid and + * not man in the middle attack */ const response = await fetch(`${ServerUrl}/verify`, { method: 'POST', @@ -60,6 +60,9 @@ function finish (customerId, email, interviewToken) { } async function sign (interviewToken, base64Contract) { + const signButton = document.getElementById('sign-button') + signButton.disabled = true + signButton.innerHTML = 'Signing...' const response = await fetch(`${ServerUrl}/sign`, { method: 'POST', @@ -67,9 +70,15 @@ async function sign (interviewToken, base64Contract) { body: JSON.stringify({ interviewToken, base64Contract }) } ) + + if (!response.ok) { + console.log(response) + showError("Couldn't Sign") + } + const signData = await response.json() const { referenceId, documentUrl } = signData - mainContainer.innerHTML = `Sucessfull sign:
\n
refenceId: ${referenceId}
\n
DocumentUrl: Download
` + mainContainer.innerHTML = `Sucessfull Signature:
\n
refenceId: ${referenceId}
\n
DocumentUrl: Download
` } function toBase64 (file) {