diff --git a/.eslintrc.cjs b/.eslintrc.json similarity index 61% rename from .eslintrc.cjs rename to .eslintrc.json index 14c04aac..d8c83ce5 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.json @@ -1,9 +1,13 @@ -const fs = require('fs'); - -module.exports = { - root: true, - extends: ['airbnb-base', 'prettier', 'plugin:jest/recommended', 'plugin:import/typescript', 'airbnb-typescript/base'], - plugins: [ +{ + "root": true, + "extends": [ + "airbnb-base", + "prettier", + "plugin:jest/recommended", + "plugin:import/typescript", + "airbnb-typescript/base" + ], + "plugins": [ "@typescript-eslint", "prettier", "import", @@ -11,16 +15,17 @@ module.exports = { "jest-dom", "jest", "jest-formatting", - "no-only-tests"], - parser: '@typescript-eslint/parser', - parserOptions: { - project: './tsconfig.json', + "no-only-tests" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.json" }, - env: { - jest: true, - node: true, + "env": { + "jest": true, + "node": true }, - settings: { + "settings": { "import/parsers": { "@typescript-eslint/parser": [".ts", ".tsx", ".js"] }, @@ -30,24 +35,20 @@ module.exports = { } } }, - rules: { + "rules": { + "semi": ["error", "always"], "no-tabs": ["error", { "allowIndentationTabs": true }], "@typescript-eslint/indent": ["off"], - "quotes": [ - "error", - "single", - { "avoidEscape": true, "allowTemplateLiterals": true } - ], + "quotes": ["error", "single", { "avoidEscape": true, "allowTemplateLiterals": true }], "@typescript-eslint/quotes": [ "error", "single", { "avoidEscape": true, "allowTemplateLiterals": true } ], - "semi": ["error", "never"], "space-before-blocks": 2, "space-before-function-paren": 2, "no-multi-spaces": 2, - "@typescript-eslint/semi": "off", + "@typescript-eslint/semi": "error", "no-unexpected-multiline": "error", "@typescript-eslint/comma-dangle": ["off"], "comma-dangle": ["off"], @@ -71,21 +72,19 @@ module.exports = { "import/no-extraneous-dependencies": [ 2, { - "devDependencies": [ - "!./src/**/*" - ] + "devDependencies": ["!./src/**/*"] } ], - 'import/extensions': [ - 'error', - 'ignorePackages', + "import/extensions": [ + "error", + "ignorePackages", { - js: 'never', - jsx: 'never', - ts: 'never', - tsx: 'never', - }, - ], + "js": "never", + "jsx": "never", + "ts": "never", + "tsx": "never" + } + ] }, - ignorePatterns: ['.eslintrc.cjs', 'build/*', 'dist/*', 'coverage/*', '**/testutils/*'], -}; + "ignorePatterns": [".eslintrc.cjs", "build/*", "dist/*", "coverage/*", "**/testutils/*"] +} diff --git a/.github/workflows/build_docker.yml b/.github/workflows/build_docker.yml index 223920de..d7ca6b3e 100644 --- a/.github/workflows/build_docker.yml +++ b/.github/workflows/build_docker.yml @@ -39,21 +39,21 @@ jobs: CI: true - name: Build example - run: npm run build + run: npm run build working-directory: examples/es6 env: - CI: true + CI: true - name: Build example cert - run: npm run generateCerts + run: npm run generateCerts working-directory: examples/es6 env: - CI: true + CI: true - name: Build example docker image working-directory: examples/es6 run: | - docker build . --tag ${{ env.EXAMPLE_IMAGE_NAME }} + docker build . --tag ${{ env.EXAMPLE_IMAGE_NAME }} - name: Log in to the Container registry uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 @@ -62,4 +62,4 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Push the tagged Docker image - run: docker push ${{ env.EXAMPLE_IMAGE_NAME }} + run: docker push ${{ env.EXAMPLE_IMAGE_NAME }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9a40bfd..76621ace 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,10 +27,10 @@ jobs: run: npm run build env: NODE_AUTH_TOKEN: ${{ secrets.CI_NPM_READ_ORG }} - - name: Examples - run: | - (cd examples/es6 && npm i && npm run build) - (cd examples/commonjs && npm i) + - name: Examples - es6 + run: cd examples/es6 && npm i && npm run build + - name: Examples - common + run: cd examples/commonjs && npm i eslint: name: 🪥 ESLint @@ -49,7 +49,7 @@ jobs: env: CI: true NODE_AUTH_TOKEN: ${{ secrets.CI_NPM_READ_ORG }} - - run: npm run check-format + - run: npm run format-check - run: npm run lint gitleaks: @@ -70,8 +70,7 @@ jobs: CI: true NODE_AUTH_TOKEN: ${{ secrets.CI_NPM_READ_ORG }} - name: Gitleaks - run: | - npm run leaks + run: npm run leaks shell: bash unit-test: diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 26d6dc6d..5af49190 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,7 +1,7 @@ name: 📢 publish on: - create: + push: tags: - 'release/**' diff --git a/.husky/pre-commit b/.husky/pre-commit index e19c9b32..c8162028 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1 @@ -npm run format -npm run lint -npm run leaks -npm test \ No newline at end of file +npm run format-lint diff --git a/.npmrc b/.npmrc index a7aa9223..83f5d583 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1 @@ -# @descope:registry=https://npm.pkg.github.com \ No newline at end of file +@descope:registry=https://registry.npmjs.org \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index 99c74700..f4eb6196 100644 --- a/.prettierrc +++ b/.prettierrc @@ -2,7 +2,7 @@ "printWidth": 100, "tabWidth": 2, "useTabs": false, - "semi": false, + "semi": true, "singleQuote": true, "trailingComma": "all" } diff --git a/README.md b/README.md index 81a4d8d6..8ec9a3eb 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ npm i --save @descope/node-sdk ## What do you want to implement? -Click one of the following links to open the documentation for that specific functionality. +Click one of the following links to open the documentation for that specific functionality. - [x] [One time passwords (OTP)](./docs/otp.md) - [x] [Magic Links](./docs/magiclink.md) @@ -26,7 +26,7 @@ Instantly run the end-to-end ExpresSDK for NodeJS examples, as shown below. The ### Prerequisites -Run the following commands in your project. Replace any instance of `` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com). +Run the following commands in your project. Replace any instance of `` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com). This commands will add the Descope NodeJS SDK as a project dependency, clone the SDK repository locally, and set the `DESCOPE_PROJECT_ID`. @@ -40,27 +40,28 @@ export DESCOPE_PROJECT_ID= **TL;DR**: Run `npm run quick` Run the following commands in the root of the project to build and run the examples. + 1. Run this to start the ES6 typescript module example - ```code bash - npm i && \ - npm run build && \ - cd examples/es6 && \ - npm i && \ - npm run generateCerts && \ - npm start - ``` + ```code bash + npm i && \ + npm run build && \ + cd examples/es6 && \ + npm i && \ + npm run generateCerts && \ + npm start + ``` 2. Run this to start the commonjs example - ```code bash - npm i && \ - npm run build && \ - cd examples/commonjs && \ - npm i && \ - npm run generateCerts && \ - npm start - ``` + ```code bash + npm i && \ + npm run build && \ + cd examples/commonjs && \ + npm i && \ + npm run generateCerts && \ + npm start + ``` ## License diff --git a/docs/magiclink.md b/docs/magiclink.md index d1d29643..b0a91483 100644 --- a/docs/magiclink.md +++ b/docs/magiclink.md @@ -11,42 +11,44 @@ flowchart LR ### Prerequisites -Replace any instance of `` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com). +Replace any instance of `` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com). -* Run the following commands in your project +- Run the following commands in your project - These commands will add the Descope NodeJS SDK as a project dependency. + These commands will add the Descope NodeJS SDK as a project dependency. - ```bash - npm i --save @descope/node-sdk - ``` + ```bash + npm i --save @descope/node-sdk + ``` -* Import and initialize the ExpresSDK for NodeJS client in your source code +- Import and initialize the ExpresSDK for NodeJS client in your source code - ```javascript - import DescopeClient from '@descope/node-sdk'; - const descopeClient = DescopeClient({ projectId: }); - ``` - or + ```javascript + import DescopeClient from '@descope/node-sdk'; + const descopeClient = DescopeClient({ projectId: }); + ``` - ```javascript - const sdk = require('@descope/node-sdk'); - const descopeClient = sdk({ projectId: }); - ``` + or + + ```javascript + const sdk = require('@descope/node-sdk'); + const descopeClient = sdk({ projectId: }); + ``` ### 1. Customer Sign-up In your sign-up route using magic link (for example, `myapp.com/signup`) generate a sign-up request and send the magic link via the selected delivery method. In the example below an email is sent to "mytestmail@test.com" containing the magic link and the link will automatically return back to the provided URL ("https://mydomain.com/verify"). In additon, optional user data (for exmaple, a custom username in the code sample below) can be gathered during the sign-up process. ```javascript -await descopeClient.magiclink.signUp.email("mytestmail@test.com", { name: "custom name" }) +await descopeClient.magiclink.signUp.email('mytestmail@test.com', { name: 'custom name' }); ``` ### 2. Customer Sign-in -In your sign-in route using magic link (for exmaple, `myapp.com/login`) generate a sign-in request send the magic link via the selected delivery method. In the example below an email is sent to "mytestmail@test.com" containing the magic link and the link will automatically return back to the provided URL ("https://mydomain.com/verify"). + +In your sign-in route using magic link (for exmaple, `myapp.com/login`) generate a sign-in request send the magic link via the selected delivery method. In the example below an email is sent to "mytestmail@test.com" containing the magic link and the link will automatically return back to the provided URL ("https://mydomain.com/verify"). ```javascript -await descopeClient.magiclink.signIn.email("mytestmail@test.com") +await descopeClient.magiclink.signIn.email('mytestmail@test.com'); ``` ### 3. Customer Verification @@ -54,9 +56,9 @@ await descopeClient.magiclink.signIn.email("mytestmail@test.com") In your verify customer route for magic link (for example, `mydomain.com/verify`) verify the token from either a customer sign-up or sign-in. ```javascript -const out = await descopeClient.magiclink.verify(token) +const out = await descopeClient.magiclink.verify(token); if (out.data.cookies) { - res.set('Set-Cookie', out.data.cookies) + res.set('Set-Cookie', out.data.cookies); } ``` @@ -65,8 +67,8 @@ if (out.data.cookies) { Session validation checks to see that the visitor to your website or application is who they say they are, by comparing the value in the validation variables against the session data that is already stored. ```javascript -const out = await descopeClient.validateSession(session_jwt, refresh_jwt) +const out = await descopeClient.validateSession(session_jwt, refresh_jwt); if (out?.cookies) { - res.set('Set-Cookie', out.cookies) + res.set('Set-Cookie', out.cookies); } ``` diff --git a/docs/oauth.md b/docs/oauth.md index 58de862b..f570a638 100644 --- a/docs/oauth.md +++ b/docs/oauth.md @@ -5,28 +5,29 @@ If this is not the case, you may need sign in to [Descope console](https://app.d ### Prerequisites -Replace any instance of `` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com). +Replace any instance of `` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com). -* Run the following commands in your project +- Run the following commands in your project - These commands will add the Descope NodeJS SDK as a project dependency. + These commands will add the Descope NodeJS SDK as a project dependency. - ```bash - npm i --save @descope/node-sdk - ``` + ```bash + npm i --save @descope/node-sdk + ``` -* Import and initialize the NodeJS client in your source code +- Import and initialize the NodeJS client in your source code - ```javascript - import DescopeClient from '@descope/node-sdk'; - const descopeClient = DescopeClient({ projectId: }); - ``` - or + ```javascript + import DescopeClient from '@descope/node-sdk'; + const descopeClient = DescopeClient({ projectId: }); + ``` - ```javascript - const sdk = require('@descope/node-sdk'); - const descopeClient = sdk({ projectId: }); - ``` + or + + ```javascript + const sdk = require('@descope/node-sdk'); + const descopeClient = sdk({ projectId: }); + ``` ### 1. Customer Sign-up/Sign-In @@ -34,12 +35,12 @@ In your OAuth start flow (for example, `myapp.com/login-with-facebook`) generate We also use the optional redirect URL to `https://localhost:3000/exchange` to call the exchange route. You may also define this in the [Descope console](https://app.descope.com). ```javascript -const out = await descopeClient.oauth.start.facebook("https://localhost:3000/exchange"); +const out = await descopeClient.oauth.start.facebook('https://localhost:3000/exchange'); // res.redirect(out.data.url); return out.data.url; ``` -### 1.1 Error handling +### 1.1 Error handling Each authentication function may return an error upon authentication failure or bad request. In case of an error, you will recieve an sdk response with `ok` equal to false and the error details are also included, such as the `errorCode` and the `errorDescription`. Needless to say, the `data` will be empty whenever an error occur. @@ -54,13 +55,13 @@ if (!out.ok) { ### 2. Customer Exchange -In your exchange for any of the OAuth provider (for example, `mydomain.com/exchange`) verify the code from the provider by using the exchange method. +In your exchange for any of the OAuth provider (for example, `mydomain.com/exchange`) verify the code from the provider by using the exchange method. ```javascript -const code = req.query.code +const code = req.query.code; const out = await descopeClient.oauth.exchange(code); if (out.data.cookies) { - res.set('Set-Cookie', out.data.cookies); + res.set('Set-Cookie', out.data.cookies); } ``` @@ -71,6 +72,6 @@ Session validation checks to see that the visitor to your website or application ```javascript const out = await descopeClient.validateSession(session_jwt, refresh_jwt); if (out.cookies) { - res.set('Set-Cookie', out.cookies); + res.set('Set-Cookie', out.cookies); } ``` diff --git a/docs/otp.md b/docs/otp.md index 17d8922a..71f07252 100644 --- a/docs/otp.md +++ b/docs/otp.md @@ -1,4 +1,3 @@ - ## OTP Authentication This section will show you how to implement user authentication using a one-time password (OTP). A typical four step flow for OTP authentictaion is shown below. @@ -12,42 +11,44 @@ flowchart LR ### Prerequisites -Replace any instance of `` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com). +Replace any instance of `` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com). + +- Run the following commands in your project -* Run the following commands in your project + These commands will add the Descope NodeJS SDK as a project dependency. - These commands will add the Descope NodeJS SDK as a project dependency. + ```bash + npm i --save @descope/node-sdk + ``` - ```bash - npm i --save @descope/node-sdk - ``` +- Import and initialize the ExpresSDK for NodeJS client in your source code -* Import and initialize the ExpresSDK for NodeJS client in your source code + ```javascript + import DescopeClient from '@descope/node-sdk'; + const descopeClient = DescopeClient({ projectId: }); + ``` - ```javascript - import DescopeClient from '@descope/node-sdk'; - const descopeClient = DescopeClient({ projectId: }); - ``` - or + or - ```javascript - const sdk = require('@descope/node-sdk'); - const descopeClient = sdk({ projectId: }); - ``` + ```javascript + const sdk = require('@descope/node-sdk'); + const descopeClient = sdk({ projectId: }); + ``` ### 1. Customer Sign-up In your sign-up route for OTP (for example, `myapp.com/signup`) generate a sign-up request and send the OTP verification code via the selected delivery method. In the example below an email is sent to "mytestmail@test.com". In additon, optional user data (for exmaple, a custom username in the code sample below) can be gathered during the sign-up process. ```javascript -await descopeClient.otp.signUp.email("mytestmail@test.com"); +await descopeClient.otp.signUp.email('mytestmail@test.com'); ``` ### 2. Customer Sign-in + In your sign-in route for OTP (for exmaple, `myapp.com/login`) generate a sign-in request send the OTP verification code via the selected delivery method. In the example below an email is sent to "mytestmail@test.com". ```javascript -await descopeClient.otp.signIn.email("mytestmail@test.com"); +await descopeClient.otp.signIn.email('mytestmail@test.com'); ``` ### 3. Customer Verification @@ -57,7 +58,7 @@ In your verify customer route for OTP (for example, `myapp.com/verify`) verify t ```javascript const out = await descopeClient.otp.verify.email(identifier, code); if (out.data.cookies) { - res.set('Set-Cookie', out.data.cookies); + res.set('Set-Cookie', out.data.cookies); } ``` @@ -68,6 +69,6 @@ Session validation checks to see that the visitor to your website or application ```javascript const out = await descopeClient.validateSession(session_jwt, refresh_jwt); if (out?.cookies) { - res.set('Set-Cookie', out.cookies); + res.set('Set-Cookie', out.cookies); } ``` diff --git a/examples/commonjs/index.js b/examples/commonjs/index.js index d9e434c7..8319371e 100644 --- a/examples/commonjs/index.js +++ b/examples/commonjs/index.js @@ -16,7 +16,10 @@ var options = { const authMiddleware = async (req, res, next) => { try { const cookies = parseCookies(req); - const out = await clientAuth.validateSession(cookies[DescopeClient.SessionTokenCookieName], cookies[DescopeClient.RefreshTokenCookieName]); + const out = await clientAuth.validateSession( + cookies[DescopeClient.SessionTokenCookieName], + cookies[DescopeClient.RefreshTokenCookieName], + ); if (out && out.cookies) { res.set('Set-Cookie', out.cookies); } @@ -31,170 +34,187 @@ const authMiddleware = async (req, res, next) => { const returnOK = (res, out) => { res.setHeader('Content-Type', 'application/json'); if (!out.ok) { - res.status(400).send(out.error) + res.status(400).send(out.error); } else if (out.data) { - res.status(200).send(out.data) + res.status(200).send(out.data); } else { - res.sendStatus(200) + res.sendStatus(200); } -} +}; const setCookies = (res, out) => { if (out && out.ok && out.data && out.data.cookies) { - res.set('Set-Cookie', out.data.cookies) + res.set('Set-Cookie', out.data.cookies); res.setHeader('Content-Type', 'application/json'); - res.status(200).send(out.data) + res.status(200).send(out.data); } else { - res.sendStatus(401) + res.sendStatus(401); } -} +}; app.post('/otp/signup', async (req, res) => { - const { identifier, deliveryMethod } = getMethodAndIdentifier(req) + const { identifier, deliveryMethod } = getMethodAndIdentifier(req); try { - const out = await clientAuth.otp.signUp[deliveryMethod](identifier) - returnOK(res, out) + const out = await clientAuth.otp.signUp[deliveryMethod](identifier); + returnOK(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/otp/signin', async (req, res) => { - const { identifier, deliveryMethod } = getMethodAndIdentifier(req) + const { identifier, deliveryMethod } = getMethodAndIdentifier(req); try { - const out = await clientAuth.otp.signIn[deliveryMethod](identifier) - returnOK(res, out) + const out = await clientAuth.otp.signIn[deliveryMethod](identifier); + returnOK(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/otp/verify', async (req, res) => { - const { identifier, deliveryMethod } = getMethodAndIdentifier(req) - const code = req.body.code + const { identifier, deliveryMethod } = getMethodAndIdentifier(req); + const code = req.body.code; try { - const out = await clientAuth.otp.verify[deliveryMethod](identifier, code) - setCookies(res, out) + const out = await clientAuth.otp.verify[deliveryMethod](identifier, code); + setCookies(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/totp/signup', async (req, res) => { - const { identifier } = getMethodAndIdentifier(req) + const { identifier } = getMethodAndIdentifier(req); try { - const out = await clientAuth.totp.signUp(identifier) + const out = await clientAuth.totp.signUp(identifier); var img = Buffer.from(out.data.image, 'base64'); res.writeHead(200, { 'Content-Type': 'image/png', - 'Content-Length': img.length + 'Content-Length': img.length, }); res.end(img); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/totp/verify', async (req, res) => { - const { identifier } = getMethodAndIdentifier(req) - const code = req.body.code + const { identifier } = getMethodAndIdentifier(req); + const code = req.body.code; try { - const out = await clientAuth.totp.verify(identifier, code) - setCookies(res, out) + const out = await clientAuth.totp.verify(identifier, code); + setCookies(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); -app.use('/webauthn', express.static('../demo.html')) +app.use('/webauthn', express.static('../demo.html')); app.post('/webauthn/signup/start', async (req, res) => { try { - const credentials = await clientAuth.webauthn.signUp.start(req.body.externalID, req.query.origin, req.body.displayName); - returnOK(res, credentials) + const credentials = await clientAuth.webauthn.signUp.start( + req.body.externalID, + req.query.origin, + req.body.displayName, + ); + returnOK(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/signup/finish', async (req, res) => { try { - const credentials = await clientAuth.webauthn.signUp.finish(req.body.transactionId, req.body.response); - setCookies(res, credentials) + const credentials = await clientAuth.webauthn.signUp.finish( + req.body.transactionId, + req.body.response, + ); + setCookies(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/signin/start', async (req, res) => { try { const credentials = await clientAuth.webauthn.signIn.start(req.query.id, req.query.origin); - returnOK(res, credentials) + returnOK(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/signin/finish', async (req, res) => { try { - const credentials = await clientAuth.webauthn.signIn.finish(req.body.transactionId, req.body.response); - setCookies(res, credentials) + const credentials = await clientAuth.webauthn.signIn.finish( + req.body.transactionId, + req.body.response, + ); + setCookies(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/add/start', authMiddleware, async (req, res) => { try { - const cookies = parseCookies(req) - const credentials = await clientAuth.webauthn.add.start(req.query.id, req.query.origin, cookies[DescopeClient.RefreshTokenCookieName]); - returnOK(res, credentials) + const cookies = parseCookies(req); + const credentials = await clientAuth.webauthn.update.start( + req.query.id, + req.query.origin, + cookies[DescopeClient.RefreshTokenCookieName], + ); + returnOK(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/add/finish', authMiddleware, async (req, res) => { try { - const credentials = await clientAuth.webauthn.add.finish(req.body.transactionId, req.body.response); - setCookies(res, credentials) + const credentials = await clientAuth.webauthn.update.finish( + req.body.transactionId, + req.body.response, + ); + setCookies(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/oauth', async (req, res) => { - const provider = req.body.provider + const provider = req.body.provider; try { - const out = await clientAuth.oauth.start[provider](`https://localhost:${port}/oauth/finish`) - res.status(200).send(out.data.url) + const out = await clientAuth.oauth.start[provider](`https://localhost:${port}/oauth/finish`); + res.status(200).send(out.data.url); } catch (error) { - console.log(error) - res.sendStatus(500) + console.log(error); + res.sendStatus(500); } -}) +}); app.get('/oauth/finish', async (req, res) => { - const code = req.query.code + const code = req.query.code; try { - const out = await clientAuth.oauth.exchange(code) - setCookies(res, out) + const out = await clientAuth.oauth.exchange(code); + setCookies(res, out); } catch (error) { - console.log(error) - res.sendStatus(500) + console.log(error); + res.sendStatus(500); } -}) +}); app.post('/api/private', authMiddleware, (_unused, res) => { res.sendStatus(200); }); @@ -203,7 +223,7 @@ app.post('/logout', authMiddleware, async (_unused, res) => { try { const cookies = parseCookies(req); const out = await clientAuth.logout(cookies['DS'], cookies['DSR']); - setCookies(res, out) + setCookies(res, out); } catch (error) { console.log(error); res.sendStatus(401); @@ -222,7 +242,10 @@ const getMethodAndIdentifier = (req) => { return { identifier: req.body.sms, deliveryMethod: DescopeClient.DeliveryMethods.SMS }; } if (req.body.whatsapp) { - return { identifier: req.body.whatsapp, deliveryMethod: DescopeClient.DeliveryMethods.whatsapp }; + return { + identifier: req.body.whatsapp, + deliveryMethod: DescopeClient.DeliveryMethods.whatsapp, + }; } return { identifier: '', deliveryMethod: DescopeClient.DeliveryMethods.email }; }; diff --git a/examples/commonjs/package-lock.json b/examples/commonjs/package-lock.json index 0e12c8c4..01113fd8 100644 --- a/examples/commonjs/package-lock.json +++ b/examples/commonjs/package-lock.json @@ -18,8 +18,8 @@ "version": "1.0.4-alpha.6", "license": "MIT", "dependencies": { - "@descope/core-js-sdk": "0.0.41-alpha.10", - "jose": "4.8.1", + "@descope/core-js-sdk": "0.0.41-alpha.24", + "jose": "4.10.0", "node-fetch": "2.6.7" }, "devDependencies": { @@ -50,11 +50,14 @@ "husky": "^8.0.1", "jest": "^28.1.0", "jsdoc": "^3.6.10", + "lint-staged": "^13.0.3", "nock": "^13.2.4", "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "rollup": "^2.62.0", "rollup-plugin-auto-external": "^2.0.0", "rollup-plugin-browsersync": "^1.3.3", + "rollup-plugin-define": "^1.0.1", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-dts": "^4.2.2", "rollup-plugin-esbuild": "^4.9.1", @@ -67,6 +70,9 @@ }, "engines": { "node": ">= 12.0.0" + }, + "peerDependencies": { + "tslib": ">=1.14.1" } }, "../../node_modules/@ampproject/remapping": { @@ -7481,8 +7487,7 @@ "../../node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "../../node_modules/tsutils": { "version": "3.21.0", @@ -8370,7 +8375,7 @@ "@descope/node-sdk": { "version": "file:../..", "requires": { - "@descope/core-js-sdk": "0.0.41-alpha.10", + "@descope/core-js-sdk": "0.0.41-alpha.24", "@rollup/plugin-commonjs": "^22.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.3.0", @@ -8397,14 +8402,17 @@ "eslint-plugin-prettier": "^4.0.0", "husky": "^8.0.1", "jest": "^28.1.0", - "jose": "4.8.1", + "jose": "4.10.0", "jsdoc": "^3.6.10", + "lint-staged": "^13.0.3", "nock": "^13.2.4", "node-fetch": "2.6.7", "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "rollup": "^2.62.0", "rollup-plugin-auto-external": "^2.0.0", "rollup-plugin-browsersync": "^1.3.3", + "rollup-plugin-define": "^1.0.1", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-dts": "^4.2.2", "rollup-plugin-esbuild": "^4.9.1", @@ -13904,8 +13912,7 @@ } }, "jose": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.8.1.tgz", + "version": "https://registry.npmjs.org/jose/-/jose-4.8.1.tgz", "integrity": "sha512-+/hpTbRcCw9YC0TOfN1W47pej4a9lRmltdOVdRLz5FP5UvUq3CenhXjQK7u/8NdMIIShMXYAh9VLPhc7TjhvFw==" }, "joycon": { @@ -15982,8 +15989,7 @@ "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "tsutils": { "version": "3.21.0", diff --git a/examples/demo.html b/examples/demo.html index f41ccfc1..e523bc75 100644 --- a/examples/demo.html +++ b/examples/demo.html @@ -1,241 +1,253 @@ + + + Descope SDK Web Page + + - - - - - -
-
-

Webauthn

- -
- - -
-
-
- + .box { + background: white; + width: 300px; + border-radius: 6px; + margin: 0 auto 0 auto; + padding: 10px; + border: #2980b9 4px solid; + display: flex; + flex-direction: column; + } + + input { + height: 20px; + padding: 8px; + font-size: 1em; + border: 1px solid; + margin-bottom: 10px; + } + + button { + padding: 5px; + width: 125px; + color: white; + } + + #register { + background: #2ecc71; + } + + #login { + background: #3498db; + } + + + + + +
+
+

Webauthn

+ +
+ + +
+
+
+ + diff --git a/examples/es6/README b/examples/es6/README index 870f54eb..113e461f 100644 --- a/examples/es6/README +++ b/examples/es6/README @@ -7,11 +7,13 @@ You can run the application using Docker. ### Docker build the image: + ``` docker build . --tag node-example ``` run the image: + ``` docker run -d -e DESCOPE_PROJECT_ID=${PROJECT_ID} -p 443:443 node-example -``` \ No newline at end of file +``` diff --git a/examples/es6/package-lock.json b/examples/es6/package-lock.json index 14cdd26f..b3702b6c 100644 --- a/examples/es6/package-lock.json +++ b/examples/es6/package-lock.json @@ -67,8 +67,8 @@ "version": "1.0.4-alpha.6", "license": "MIT", "dependencies": { - "@descope/core-js-sdk": "0.0.41-alpha.10", - "jose": "4.8.1", + "@descope/core-js-sdk": "0.0.41-alpha.24", + "jose": "4.10.0", "node-fetch": "2.6.7" }, "devDependencies": { @@ -99,11 +99,14 @@ "husky": "^8.0.1", "jest": "^28.1.0", "jsdoc": "^3.6.10", + "lint-staged": "^13.0.3", "nock": "^13.2.4", "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "rollup": "^2.62.0", "rollup-plugin-auto-external": "^2.0.0", "rollup-plugin-browsersync": "^1.3.3", + "rollup-plugin-define": "^1.0.1", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-dts": "^4.2.2", "rollup-plugin-esbuild": "^4.9.1", @@ -116,6 +119,9 @@ }, "engines": { "node": ">= 12.0.0" + }, + "peerDependencies": { + "tslib": ">=1.14.1" } }, "../../dist": { @@ -1757,7 +1763,7 @@ "@descope/node-sdk": { "version": "file:../..", "requires": { - "@descope/core-js-sdk": "0.0.41-alpha.10", + "@descope/core-js-sdk": "0.0.41-alpha.24", "@rollup/plugin-commonjs": "^22.0.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.3.0", @@ -1784,14 +1790,17 @@ "eslint-plugin-prettier": "^4.0.0", "husky": "^8.0.1", "jest": "^28.1.0", - "jose": "4.8.1", + "jose": "4.10.0", "jsdoc": "^3.6.10", + "lint-staged": "^13.0.3", "nock": "^13.2.4", "node-fetch": "2.6.7", "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "rollup": "^2.62.0", "rollup-plugin-auto-external": "^2.0.0", "rollup-plugin-browsersync": "^1.3.3", + "rollup-plugin-define": "^1.0.1", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-dts": "^4.2.2", "rollup-plugin-esbuild": "^4.9.1", diff --git a/examples/es6/rollup.config.js b/examples/es6/rollup.config.js index ce79c3f3..9f351be1 100644 --- a/examples/es6/rollup.config.js +++ b/examples/es6/rollup.config.js @@ -2,26 +2,26 @@ import typescript from '@rollup/plugin-typescript'; import del from 'rollup-plugin-delete'; import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; -import json from '@rollup/plugin-json' +import json from '@rollup/plugin-json'; export default [ - { - input: './src/index.ts', - output: [ - { - file: 'dist/index.js', - format: 'es', - sourcemap: true, - } - ], - plugins: [ - del({ targets: 'dist' }), - typescript({ - tsconfig: './tsconfig.json' - }), - commonjs(), - resolve(), - json() - ] - } + { + input: './src/index.ts', + output: [ + { + file: 'dist/index.js', + format: 'es', + sourcemap: true, + }, + ], + plugins: [ + del({ targets: 'dist' }), + typescript({ + tsconfig: './tsconfig.json', + }), + commonjs(), + resolve(), + json(), + ], + }, ]; diff --git a/examples/es6/src/index.ts b/examples/es6/src/index.ts index 32ad2a62..26d9c6ba 100644 --- a/examples/es6/src/index.ts +++ b/examples/es6/src/index.ts @@ -1,257 +1,286 @@ import { SdkResponse } from '@descope/core-js-sdk'; -import express, { Request, Response, NextFunction } from 'express' -import DescopeClient from '@descope/node-sdk' -import type { DeliveryMethod, OAuthProvider } from '@descope/node-sdk' -import * as fs from 'fs' -import * as https from 'https' +import express, { Request, Response, NextFunction } from 'express'; +import DescopeClient from '@descope/node-sdk'; +import type { DeliveryMethod, OAuthProvider } from '@descope/node-sdk'; +import { readFileSync } from 'fs'; +import { createServer } from 'https'; import path from 'path'; import process from 'process'; import bodyParser from 'body-parser'; -const app = express() -app.use(bodyParser.json()) -const port = 443 +const app = express(); +app.use(bodyParser.json()); +const port = 443; const options = { - key: fs.readFileSync(path.resolve('./server.key')), - cert: fs.readFileSync(path.resolve('./server.crt')), -} + key: readFileSync(path.resolve('./server.key')), + cert: readFileSync(path.resolve('./server.crt')), +}; const clientAuth = { - auth: DescopeClient({ projectId: process.env.DESCOPE_PROJECT_ID || '', baseUrl: process.env.DESCOPE_API_BASE_URL, logger: console }), -} + auth: DescopeClient({ + projectId: process.env.DESCOPE_PROJECT_ID || '', + baseUrl: process.env.DESCOPE_API_BASE_URL, + logger: console, + }), +}; const authMiddleware = async (req: Request, res: Response, next: NextFunction) => { try { - const cookies = parseCookies(req) - const out = await clientAuth.auth.validateSession(cookies[DescopeClient.SessionTokenCookieName], cookies[DescopeClient.RefreshTokenCookieName]) + const cookies = parseCookies(req); + const out = await clientAuth.auth.validateSession( + cookies[DescopeClient.SessionTokenCookieName], + cookies[DescopeClient.RefreshTokenCookieName], + ); if (out?.cookies) { - res.set('Set-Cookie', out.cookies) + res.set('Set-Cookie', out.cookies); } - next() + next(); } catch (e) { res.status(401).json({ error: new Error('Unauthorized!'), - }) + }); } -} +}; -const returnOK = (res: Response, out: SdkResponse) => { +const returnOK = (res: Response, out: SdkResponse) => { res.setHeader('Content-Type', 'application/json'); if (!out.ok) { - res.status(400).send(out.error) + res.status(400).send(out.error); } else if (out.data) { - res.status(200).send(out.data) + res.status(200).send(out.data); } else { - res.sendStatus(200) + res.sendStatus(200); } -} +}; -const returnCookies = (res: Response, out: SdkResponse) => { +const returnCookies = (res: Response, out: SdkResponse) => { if (out.ok && out.data?.cookies) { - res.set('Set-Cookie', out.data.cookies) + res.set('Set-Cookie', out.data.cookies); res.setHeader('Content-Type', 'application/json'); - res.status(200).send(out.data) + res.status(200).send(out.data); } else { - res.sendStatus(401) + res.sendStatus(401); } -} +}; app.post('/otp/signup', async (req: Request, res: Response) => { - const { identifier, deliveryMethod } = getMethodAndIdentifier(req) + const { identifier, deliveryMethod } = getMethodAndIdentifier(req); try { - const out = await clientAuth.auth.otp.signUp[deliveryMethod](identifier) - returnOK(res, out) + const out = await clientAuth.auth.otp.signUp[deliveryMethod](identifier); + returnOK(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/otp/signin', async (req: Request, res: Response) => { - const { identifier, deliveryMethod } = getMethodAndIdentifier(req) + const { identifier, deliveryMethod } = getMethodAndIdentifier(req); try { - const out = await clientAuth.auth.otp.signIn[deliveryMethod](identifier) - returnOK(res, out) + const out = await clientAuth.auth.otp.signIn[deliveryMethod](identifier); + returnOK(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/otp/verify', async (req: Request, res: Response) => { - const { identifier, deliveryMethod } = getMethodAndIdentifier(req) - const code = req.body.code as string + const { identifier, deliveryMethod } = getMethodAndIdentifier(req); + const code = req.body.code as string; try { - const out = await clientAuth.auth.otp.verify[deliveryMethod](identifier, code) - returnCookies(res, out) + const out = await clientAuth.auth.otp.verify[deliveryMethod](identifier, code); + returnCookies(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/totp/signup', async (req: Request, res: Response) => { - const { identifier } = getMethodAndIdentifier(req) + const { identifier } = getMethodAndIdentifier(req); try { - const out = await clientAuth.auth.totp.signUp(identifier) - var img = Buffer.from(out.data?.image, 'base64'); + const out = await clientAuth.auth.totp.signUp(identifier); + const img = Buffer.from(out?.data?.image!, 'base64'); res.writeHead(200, { 'Content-Type': 'image/png', - 'Content-Length': img.length + 'Content-Length': img.length, }); - res.end(img); + res.end(img); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/totp/verify', async (req: Request, res: Response) => { - const { identifier } = getMethodAndIdentifier(req) - const code = req.body.code as string + const { identifier } = getMethodAndIdentifier(req); + const code = req.body.code as string; try { - const out = await clientAuth.auth.totp.verify(identifier, code) - returnCookies(res, out) + const out = await clientAuth.auth.totp.verify(identifier, code); + returnCookies(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); -app.use('/webauthn', express.static('../demo.html')) +app.use('/webauthn', express.static('../demo.html')); app.post('/webauthn/signup/start', async (req: Request, res: Response) => { try { - const credentials = await clientAuth.auth.webauthn.signUp.start(req.body.externalID, req.query.origin as string, req.body.displayName); - returnOK(res, credentials) + const credentials = await clientAuth.auth.webauthn.signUp.start( + req.body.externalID, + req.query.origin as string, + req.body.displayName, + ); + returnOK(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/signup/finish', async (req: Request, res: Response) => { try { - const credentials = await clientAuth.auth.webauthn.signUp.finish(req.body.transactionId, req.body.response); - returnCookies(res, credentials) + const credentials = await clientAuth.auth.webauthn.signUp.finish( + req.body.transactionId, + req.body.response, + ); + returnCookies(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/signin/start', async (req: Request, res: Response) => { try { - const credentials = await clientAuth.auth.webauthn.signIn.start(req.query.id as string, req.query.origin as string); - returnOK(res, credentials) + const credentials = await clientAuth.auth.webauthn.signIn.start( + req.query.id as string, + req.query.origin as string, + ); + returnOK(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/signin/finish', async (req: Request, res: Response) => { try { - const credentials = await clientAuth.auth.webauthn.signIn.finish(req.body.transactionId, req.body.response); - returnCookies(res, credentials) + const credentials = await clientAuth.auth.webauthn.signIn.finish( + req.body.transactionId, + req.body.response, + ); + returnCookies(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/add/start', authMiddleware, async (req: Request, res: Response) => { try { - const cookies = parseCookies(req) - const credentials = await clientAuth.auth.webauthn.add.start(req.query.id as string, req.query.origin as string, cookies[DescopeClient.RefreshTokenCookieName]); - returnOK(res, credentials) + const cookies = parseCookies(req); + const credentials = await clientAuth.auth.webauthn.update.start( + req.query.id as string, + req.query.origin as string, + cookies[DescopeClient.RefreshTokenCookieName], + ); + returnOK(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/webauthn/add/finish', authMiddleware, async (req: Request, res: Response) => { try { - const credentials = await clientAuth.auth.webauthn.add.finish(req.body.transactionId, req.body.response); - returnCookies(res, credentials) + const credentials = await clientAuth.auth.webauthn.update.finish( + req.body.transactionId, + req.body.response, + ); + returnCookies(res, credentials); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); app.post('/oauth', async (req: Request, res: Response) => { - const provider: OAuthProvider = (req.body.provider as OAuthProvider) + const provider: OAuthProvider = req.body.provider as OAuthProvider; try { - const out = await clientAuth.auth.oauth.start[provider](`https://localhost:${port}/oauth/finish`) - res.status(200).send(out.data.url) + const out = await clientAuth.auth.oauth.start[provider]( + `https://localhost:${port}/oauth/finish`, + ); + res.status(200).send(out?.data?.url); } catch (error) { - console.log(error) - res.sendStatus(500) + console.log(error); + res.sendStatus(500); } -}) +}); app.get('/oauth/finish', async (req: Request, res: Response) => { - const code = req.query.code as string + const code = req.query.code as string; try { - const out = await clientAuth.auth.oauth.exchange(code) - returnCookies(res, out) + const out = await clientAuth.auth.oauth.exchange(code); + returnCookies(res, out); } catch (error) { - console.log(error) - res.sendStatus(500) + console.log(error); + res.sendStatus(500); } -}) +}); app.post('/api/private', authMiddleware, (_unused: Request, res: Response) => { - console.log("Private API") - res.sendStatus(200) -}) + console.log('Private API'); + res.sendStatus(200); +}); app.post('/logout', authMiddleware, async (req: Request, res: Response) => { try { - const cookies = parseCookies(req) - const out = await clientAuth.auth.logout(cookies['DS']) - returnCookies(res, out) + const cookies = parseCookies(req); + const out = await clientAuth.auth.logout(cookies.DS); + returnCookies(res, out); } catch (error) { - console.log(error) - res.sendStatus(401) + console.log(error); + res.sendStatus(401); } -}) +}); -https.createServer(options, app).listen(port, () => { - console.log(`Example app listening on port ${port}`) -}) +createServer(options, app).listen(port, () => { + console.log(`Example app listening on port ${port}`); +}); const getMethodAndIdentifier = ( req: Request, ): { identifier: string; deliveryMethod: DeliveryMethod } => { if (req.body.email) { - return { identifier: req.body.email as string, deliveryMethod: 'email' } + return { identifier: req.body.email as string, deliveryMethod: 'email' }; } if (req.body.sms) { - return { identifier: req.body.sms as string, deliveryMethod: 'sms' } + return { identifier: req.body.sms as string, deliveryMethod: 'sms' }; } if (req.body.whatsapp) { - return { identifier: req.body.whatsapp as string, deliveryMethod: 'whatsapp' } + return { identifier: req.body.whatsapp as string, deliveryMethod: 'whatsapp' }; } - return { identifier: '', deliveryMethod: 'email' } -} + return { identifier: '', deliveryMethod: 'email' }; +}; const parseCookies = (request: Request) => { - const list: { [key: string]: string } = {} - const cookieHeader = request.headers?.cookie - if (!cookieHeader) return list + const list: { [key: string]: string } = {}; + const cookieHeader = request.headers?.cookie; + if (!cookieHeader) return list; - cookieHeader.split(`;`).forEach(function (cookie: string) { - let [name, ...rest] = cookie.split(`=`) - name = name?.trim() - if (!name) return - const value = rest.join(`=`).trim() - if (!value) return - list[name] = decodeURIComponent(value) - }) + cookieHeader.split(`;`).forEach((cookie: string) => { + let [name, ...rest] = cookie.split(`=`); + name = name?.trim(); + if (!name) return; + const value = rest.join(`=`).trim(); + if (!value) return; + list[name] = decodeURIComponent(value); + }); - return list -} + return list; +}; diff --git a/examples/es6/tsconfig.json b/examples/es6/tsconfig.json index 17a21589..38e19c69 100644 --- a/examples/es6/tsconfig.json +++ b/examples/es6/tsconfig.json @@ -1,15 +1,15 @@ { - "compilerOptions": { - "outDir": "./dist", - "allowJs": true, - "target": "es6", - "module": "es6", - "rootDir": "./src", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "moduleResolution": "Node" - }, - "include": ["src/**/*"] - } \ No newline at end of file + "compilerOptions": { + "outDir": "./dist", + "allowJs": true, + "target": "es6", + "module": "es6", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "moduleResolution": "Node" + }, + "include": ["src/**/*"] +} diff --git a/jest.config.cjs b/jest.config.cjs index c0987d53..a2beeb7e 100644 --- a/jest.config.cjs +++ b/jest.config.cjs @@ -1,21 +1,22 @@ module.exports = { - clearMocks: true, + clearMocks: true, - collectCoverage: true, - coverageDirectory: 'coverage', - collectCoverageFrom: ['lib/**/*.{js,jsx,ts,tsx}'], + collectCoverage: true, + coverageDirectory: 'coverage', + collectCoverageFrom: ['lib/**/*.{js,jsx,ts,tsx}'], - // A set of global variables that need to be available in all test environments - globals: { - 'ts-jest': { - tsconfig: 'tsconfig.json' - } - }, + // A set of global variables that need to be available in all test environments + globals: { + 'ts-jest': { + tsconfig: 'tsconfig.json', + }, + BUILD_VERSION: 'one.two.three', + }, - preset: 'ts-jest', - moduleDirectories: ['node_modules', 'lib'], + preset: 'ts-jest', + moduleDirectories: ['node_modules', 'lib'], - testTimeout: 2000, + testTimeout: 2000, - roots: ['lib'] + roots: ['lib'], }; diff --git a/lib/constants.ts b/lib/constants.ts index 20c5df2b..72e4e2a8 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -1,11 +1,11 @@ // eslint-disable-next-line import/prefer-default-export /** Refresh JWT cookie name */ -export const refreshTokenCookieName = 'DSR' +export const refreshTokenCookieName = 'DSR'; /** Session JWT cookie name */ -export const sessionTokenCookieName = 'DS' +export const sessionTokenCookieName = 'DS'; /** The key of the tenants claims in the claims map */ -export const authorizedTenantsClaimName = 'tenants' +export const authorizedTenantsClaimName = 'tenants'; /** The key of the permissions claims in the claims map either under tenant or top level */ -export const permissionsClaimName = 'permissions' +export const permissionsClaimName = 'permissions'; /** The key of the roles claims in the claims map either under tenant or top level */ -export const rolesClaimName = 'roles' +export const rolesClaimName = 'roles'; diff --git a/lib/helpers.ts b/lib/helpers.ts index 9377f835..ecdcfae3 100644 --- a/lib/helpers.ts +++ b/lib/helpers.ts @@ -1,10 +1,10 @@ -import type { ResponseData, SdkResponse } from '@descope/core-js-sdk' -import { AuthenticationInfo } from './types' +import type { ResponseData, SdkResponse } from '@descope/core-js-sdk'; +import { AuthenticationInfo } from './types'; import { refreshTokenCookieName, sessionTokenCookieName, authorizedTenantsClaimName, -} from './constants' +} from './constants'; /** * Generate a cookie string from given parameters @@ -16,7 +16,7 @@ import { const generateCookie = (name: string, value: string, options?: Record) => `${name}=${value}; Domain=${options?.cookieDomain || ''}; Max-Age=${ options?.cookieMaxAge || '' - }; Path=${options?.cookiePath || '/'}; HttpOnly; SameSite=Strict` + }; Path=${options?.cookiePath || '/'}; HttpOnly; SameSite=Strict`; /** * Parse the cookie string and return the value of the cookie @@ -25,9 +25,9 @@ const generateCookie = (name: string, value: string, options?: Record { - const match = cookie?.match(RegExp(`(?:^|;\\s*)${name}=([^;]*)`)) - return match ? match[1] : null -} + const match = cookie?.match(RegExp(`(?:^|;\\s*)${name}=([^;]*)`)); + return match ? match[1] : null; +}; // eslint-disable-next-line import/prefer-default-export /** @@ -38,31 +38,31 @@ const getCookieValue = (cookie: string | null | undefined, name: string) => { export const withCookie = , U extends Promise>>(fn: (...args: T) => U) => async (...args: T): Promise> => { - const resp = await fn(...args) + const resp = await fn(...args); // istanbul ignore next if (!resp.data) { - return resp + return resp; } // eslint-disable-next-line prefer-const - let { sessionJwt, refreshJwt, ...rest } = resp.data - const cookies = [generateCookie(sessionTokenCookieName, sessionJwt, rest)] + let { sessionJwt, refreshJwt, ...rest } = resp.data; + const cookies = [generateCookie(sessionTokenCookieName, sessionJwt, rest)]; if (!refreshJwt) { if (resp.response?.headers.get('set-cookie')) { refreshJwt = getCookieValue( resp.response?.headers.get('set-cookie'), refreshTokenCookieName, - ) - cookies.push(resp.response?.headers.get('set-cookie')!) + ); + cookies.push(resp.response?.headers.get('set-cookie')!); } } else { - cookies.push(generateCookie(refreshTokenCookieName, refreshJwt, rest)) + cookies.push(generateCookie(refreshTokenCookieName, refreshJwt, rest)); } - return { ...resp, data: { ...resp.data, refreshJwt, cookies } } - } + return { ...resp, data: { ...resp.data, refreshJwt, cookies } }; + }; /** * Wrap given object internal functions (can be deep inside the object) with the given wrapping function @@ -77,30 +77,30 @@ export const wrapWith = >( wrappingFn: Function, // eslint-disable-next-line consistent-return ): void => { - if (!obj) return + if (!obj) return; - const pathSections = typeof path === 'string' ? path.split('.') : path - const section = pathSections.shift() || ('' as keyof T) + const pathSections = typeof path === 'string' ? path.split('.') : path; + const section = pathSections.shift() || ('' as keyof T); if (pathSections.length === 0 || section === '*') { const wrap = (key: keyof T) => { if (key && typeof obj[key] === 'function') { // eslint-disable-next-line no-param-reassign - obj[key] = wrappingFn(obj[key]) + obj[key] = wrappingFn(obj[key]); } else { // istanbul ignore next - throw Error(`cannot wrap value at key "${key.toString()}"`) + throw Error(`cannot wrap value at key "${key.toString()}"`); } - } + }; if (section === '*') { - Object.keys(obj).forEach(wrap) + Object.keys(obj).forEach(wrap); } else { - wrap(section) + wrap(section); } } else { - wrapWith(obj[section], pathSections, wrappingFn) + wrapWith(obj[section], pathSections, wrappingFn); } -} +}; /** * Wrap given object internal functions (can be deep inside the object) with the given wrapping function based on multiple paths. @@ -113,7 +113,7 @@ export const bulkWrapWith = ( obj: Parameters[0], paths: string[], wrappingFn: Parameters[2], -) => paths.forEach((path: string) => wrapWith(obj, path, wrappingFn)) +) => paths.forEach((path: string) => wrapWith(obj, path, wrappingFn)); /** * Get the claim (used for permissions or roles) for a given tenant or top level if tenant is empty @@ -129,6 +129,6 @@ export function getAuthorizationClaimItems( ): string[] { const value = tenant ? authInfo.token[authorizedTenantsClaimName]?.[tenant]?.[claim] - : authInfo.token[claim] - return Array.isArray(value) ? value : [] + : authInfo.token[claim]; + return Array.isArray(value) ? value : []; } diff --git a/lib/index.test.ts b/lib/index.test.ts index 89ace76b..2f19d36b 100644 --- a/lib/index.test.ts +++ b/lib/index.test.ts @@ -1,56 +1,56 @@ -import { JWTResponse, SdkResponse, ExchangeAccessKeyResponse } from '@descope/core-js-sdk' -import { JWK, SignJWT, exportJWK, JWTHeaderParameters, generateKeyPair } from 'jose' -import createSdk from '.' -import { AuthenticationInfo } from './types' +import { JWTResponse, SdkResponse, ExchangeAccessKeyResponse } from '@descope/core-js-sdk'; +import { JWK, SignJWT, exportJWK, JWTHeaderParameters, generateKeyPair } from 'jose'; +import createSdk from '.'; +import { AuthenticationInfo } from './types'; import { refreshTokenCookieName, sessionTokenCookieName, authorizedTenantsClaimName, permissionsClaimName, rolesClaimName, -} from './constants' +} from './constants'; -let validToken: string -let expiredToken: string -let publicKeys: JWK -let permAuthInfo: AuthenticationInfo -let permTenantAuthInfo: AuthenticationInfo +let validToken: string; +let expiredToken: string; +let publicKeys: JWK; +let permAuthInfo: AuthenticationInfo; +let permTenantAuthInfo: AuthenticationInfo; const logger = { log: jest.fn(), error: jest.fn(), debug: jest.fn(), -} +}; const sdk = createSdk({ projectId: 'project-id', logger, -}) +}); const get = (obj: Record, path: string) => - path.split('.').reduce((acc, part) => acc[part], obj) as Function + path.split('.').reduce((acc, part) => acc[part], obj) as Function; const generatePathFromKeys = (obj: Record, path: string) => - Object.keys(get(obj, path)).map((key) => `${path}.${key}`) + Object.keys(get(obj, path)).map((key) => `${path}.${key}`); describe('sdk', () => { beforeAll(async () => { - const { publicKey, privateKey } = await generateKeyPair('ES384') + const { publicKey, privateKey } = await generateKeyPair('ES384'); validToken = await new SignJWT({}) .setProtectedHeader({ alg: 'ES384', kid: '0ad99869f2d4e57f3f71c68300ba84fa' }) .setIssuedAt() .setIssuer('project-id') .setExpirationTime(1981398111) - .sign(privateKey) + .sign(privateKey); expiredToken = await new SignJWT({}) .setProtectedHeader({ alg: 'ES384', kid: '0ad99869f2d4e57f3f71c68300ba84fa' }) .setIssuedAt(1181398100) .setIssuer('project-id') .setExpirationTime(1181398111) - .sign(privateKey) + .sign(privateKey); permAuthInfo = { jwt: 'jwt', token: { [permissionsClaimName]: ['foo', 'bar'], [rolesClaimName]: ['abc', 'xyz'] }, - } + }; permTenantAuthInfo = { jwt: 'jwt', token: { @@ -58,176 +58,176 @@ describe('sdk', () => { kuku: { [permissionsClaimName]: ['foo', 'bar'], [rolesClaimName]: ['abc', 'xyz'] }, }, }, - } - publicKeys = await exportJWK(publicKey) - publicKeys.alg = 'ES384' - publicKeys.kid = '0ad99869f2d4e57f3f71c68300ba84fa' - publicKeys.use = 'sig' + }; + publicKeys = await exportJWK(publicKey); + publicKeys.alg = 'ES384'; + publicKeys.kid = '0ad99869f2d4e57f3f71c68300ba84fa'; + publicKeys.use = 'sig'; jest .spyOn(sdk.httpClient, 'get') - .mockResolvedValue({ json: () => Promise.resolve([publicKeys]) } as Response) - }) + .mockResolvedValue({ json: () => Promise.resolve([publicKeys]) } as Response); + }); afterEach(() => { - jest.clearAllMocks() - }) + jest.clearAllMocks(); + }); describe('validateToken', () => { it('should return the token payload when valid', async () => { - const resp = await sdk.validateJwt(validToken) + const resp = await sdk.validateJwt(validToken); expect(resp).toMatchObject({ token: { exp: 1981398111, iss: 'project-id', }, - }) - }) + }); + }); it('should reject with a proper error message when token expired', async () => { await expect(sdk.validateJwt(expiredToken)).rejects.toThrow( '"exp" claim timestamp check failed', - ) - }) - }) + ); + }); + }); describe('getKey', () => { it('should throw an error when key does not exist', async () => { await expect(sdk.getKey({ kid: 'unknown-key' } as JWTHeaderParameters)).rejects.toThrow( 'failed to fetch matching key', - ) - }) + ); + }); it('should return the key from cache if exists', async () => { const newSdk = createSdk({ projectId: 'project-id', logger, - }) + }); jest .spyOn(newSdk.httpClient, 'get') - .mockResolvedValue({ json: () => Promise.resolve([publicKeys]) } as Response) + .mockResolvedValue({ json: () => Promise.resolve([publicKeys]) } as Response); - await newSdk.getKey({ kid: publicKeys.kid } as JWTHeaderParameters) - await newSdk.getKey({ kid: publicKeys.kid } as JWTHeaderParameters) + await newSdk.getKey({ kid: publicKeys.kid } as JWTHeaderParameters); + await newSdk.getKey({ kid: publicKeys.kid } as JWTHeaderParameters); - expect(newSdk.httpClient.get).toHaveBeenCalledTimes(1) - }) + expect(newSdk.httpClient.get).toHaveBeenCalledTimes(1); + }); it('should throw an error when kid is empty', async () => { await expect(sdk.getKey({ kid: '' } as JWTHeaderParameters)).rejects.toThrow( 'header.kid must not be empty', - ) - }) - }) + ); + }); + }); describe('ValidateSession', () => { it('should throw an error when both session and refresh tokens are empty', async () => { await expect(sdk.validateSession('', '')).rejects.toThrow( 'both refresh token and session token are empty', - ) - }) + ); + }); it('should return the token when session token is valid', async () => { await expect(sdk.validateSession(validToken, '')).resolves.toMatchObject({ token: { exp: 1981398111, iss: 'project-id' }, - }) - }) + }); + }); it('should throw an error when session token expired and no refresh token', async () => { await expect(sdk.validateSession(expiredToken, '')).rejects.toThrow( 'could not validate tokens', - ) - }) + ); + }); it('should throw an error when both refresh & session tokens expired', async () => { await expect(sdk.validateSession(expiredToken, expiredToken)).rejects.toThrow( 'could not validate tokens', - ) - }) + ); + }); it('should refresh session token when it expired and refresh token is valid', async () => { const spyRefresh = jest.spyOn(sdk, 'refresh').mockResolvedValueOnce({ ok: true, data: { sessionJwt: validToken }, - } as SdkResponse) + } as SdkResponse); await expect(sdk.validateSession(expiredToken, validToken)).resolves.toHaveProperty( 'jwt', validToken, - ) - expect(spyRefresh).toHaveBeenCalledWith(validToken) - }) + ); + expect(spyRefresh).toHaveBeenCalledWith(validToken); + }); it('should return the token when refresh token is valid', async () => { const spyRefresh = jest.spyOn(sdk, 'refresh').mockResolvedValueOnce({ ok: true, data: { sessionJwt: validToken }, - } as SdkResponse) + } as SdkResponse); - await expect(sdk.validateSession('', validToken)).resolves.toHaveProperty('jwt', validToken) - expect(spyRefresh).toHaveBeenCalledWith(validToken) - }) - }) + await expect(sdk.validateSession('', validToken)).resolves.toHaveProperty('jwt', validToken); + expect(spyRefresh).toHaveBeenCalledWith(validToken); + }); + }); describe('exchangeAccessKey', () => { it('should fail when the server call throws', async () => { - const spyExchange = jest.spyOn(sdk.accessKey, 'exchange').mockRejectedValueOnce('error') - await expect(sdk.exchangeAccessKey('key')).rejects.toThrow('could not exchange access key') - expect(spyExchange).toHaveBeenCalledWith('key') - }) + const spyExchange = jest.spyOn(sdk.accessKey, 'exchange').mockRejectedValueOnce('error'); + await expect(sdk.exchangeAccessKey('key')).rejects.toThrow('could not exchange access key'); + expect(spyExchange).toHaveBeenCalledWith('key'); + }); it('should fail when getting an unexpected response from the server', async () => { const spyExchange = jest .spyOn(sdk.accessKey, 'exchange') - .mockResolvedValueOnce({ data: {} } as SdkResponse) - await expect(sdk.exchangeAccessKey('key')).rejects.toThrow('could not exchange access key') - expect(spyExchange).toHaveBeenCalledWith('key') - }) + .mockResolvedValueOnce({ data: {} } as SdkResponse); + await expect(sdk.exchangeAccessKey('key')).rejects.toThrow('could not exchange access key'); + expect(spyExchange).toHaveBeenCalledWith('key'); + }); it('should fail when the session token the server returns is invalid', async () => { const spyExchange = jest.spyOn(sdk.accessKey, 'exchange').mockResolvedValueOnce({ data: { sessionJwt: expiredToken }, - } as SdkResponse) - await expect(sdk.exchangeAccessKey('key')).rejects.toThrow('could not exchange access key') - expect(spyExchange).toHaveBeenCalledWith('key') - }) + } as SdkResponse); + await expect(sdk.exchangeAccessKey('key')).rejects.toThrow('could not exchange access key'); + expect(spyExchange).toHaveBeenCalledWith('key'); + }); it('should return the same session token it got from the server', async () => { const spyExchange = jest.spyOn(sdk.accessKey, 'exchange').mockResolvedValueOnce({ data: { sessionJwt: validToken }, - } as SdkResponse) + } as SdkResponse); const expected: AuthenticationInfo = { jwt: validToken, token: { exp: 1981398111, iss: 'project-id' }, - } - await expect(sdk.exchangeAccessKey('key')).resolves.toMatchObject(expected) - expect(spyExchange).toHaveBeenCalledWith('key') - }) - }) + }; + await expect(sdk.exchangeAccessKey('key')).resolves.toMatchObject(expected); + expect(spyExchange).toHaveBeenCalledWith('key'); + }); + }); describe('validatePermissionsRoles', () => { it('should always succeed with empty requirements', () => { - expect(sdk.validatePermissions(permAuthInfo, [])).toStrictEqual(true) - expect(sdk.validateTenantPermissions(permTenantAuthInfo, 'kuku', [])).toStrictEqual(true) - expect(sdk.validateRoles(permAuthInfo, [])).toStrictEqual(true) - expect(sdk.validateTenantRoles(permTenantAuthInfo, 'kuku', [])).toStrictEqual(true) - }) + expect(sdk.validatePermissions(permAuthInfo, [])).toStrictEqual(true); + expect(sdk.validateTenantPermissions(permTenantAuthInfo, 'kuku', [])).toStrictEqual(true); + expect(sdk.validateRoles(permAuthInfo, [])).toStrictEqual(true); + expect(sdk.validateTenantRoles(permTenantAuthInfo, 'kuku', [])).toStrictEqual(true); + }); it('should succeed when requirements are met', () => { - expect(sdk.validatePermissions(permAuthInfo, ['foo'])).toStrictEqual(true) + expect(sdk.validatePermissions(permAuthInfo, ['foo'])).toStrictEqual(true); expect( sdk.validateTenantPermissions(permTenantAuthInfo, 'kuku', ['foo', 'bar']), - ).toStrictEqual(true) - expect(sdk.validateRoles(permAuthInfo, ['abc'])).toStrictEqual(true) + ).toStrictEqual(true); + expect(sdk.validateRoles(permAuthInfo, ['abc'])).toStrictEqual(true); expect(sdk.validateTenantRoles(permTenantAuthInfo, 'kuku', ['abc', 'xyz'])).toStrictEqual( true, - ) - }) + ); + }); it('should fail when wrong function is used', () => { - expect(sdk.validatePermissions(permTenantAuthInfo, ['foo'])).toStrictEqual(false) - expect(sdk.validateTenantPermissions(permAuthInfo, 'kuku', ['foo'])).toStrictEqual(false) - expect(sdk.validateRoles(permTenantAuthInfo, ['abc'])).toStrictEqual(false) - expect(sdk.validateTenantRoles(permAuthInfo, 'kuku', ['abc'])).toStrictEqual(false) - }) + expect(sdk.validatePermissions(permTenantAuthInfo, ['foo'])).toStrictEqual(false); + expect(sdk.validateTenantPermissions(permAuthInfo, 'kuku', ['foo'])).toStrictEqual(false); + expect(sdk.validateRoles(permTenantAuthInfo, ['abc'])).toStrictEqual(false); + expect(sdk.validateTenantRoles(permAuthInfo, 'kuku', ['abc'])).toStrictEqual(false); + }); it('should fail when requirements are not met', () => { - expect(sdk.validatePermissions(permAuthInfo, ['foo', 'bar', 'qux'])).toStrictEqual(false) + expect(sdk.validatePermissions(permAuthInfo, ['foo', 'bar', 'qux'])).toStrictEqual(false); expect( sdk.validateTenantPermissions(permTenantAuthInfo, 'kuku', ['foo', 'bar', 'qux']), - ).toStrictEqual(false) - expect(sdk.validateRoles(permAuthInfo, ['abc', 'xyz', 'tuv'])).toStrictEqual(false) + ).toStrictEqual(false); + expect(sdk.validateRoles(permAuthInfo, ['abc', 'xyz', 'tuv'])).toStrictEqual(false); expect( sdk.validateTenantRoles(permTenantAuthInfo, 'kuku', ['abc', 'xyz', 'tuv']), - ).toStrictEqual(false) - }) - }) + ).toStrictEqual(false); + }); + }); describe('withCookies', () => { describe('when no cookie', () => { @@ -242,18 +242,18 @@ describe('sdk', () => { 'webauthn.signIn.finish', 'webauthn.signUp.finish', 'refresh', - ] + ]; it.each(paths)('should generate cookie from body jwt for %s', async (path) => { - const data = { sessionJwt: 'sessionJwt', refreshJwt: 'refreshJwt' } + const data = { sessionJwt: 'sessionJwt', refreshJwt: 'refreshJwt' }; jest.spyOn(sdk.httpClient, 'post').mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(data), - } as Response) + } as Response); jest.spyOn(sdk.httpClient, 'get').mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(data), - } as Response) + } as Response); await expect(get(sdk, path)('1', '2', '3')).resolves.toEqual( expect.objectContaining({ @@ -265,17 +265,17 @@ describe('sdk', () => { ], }, }), - ) - }) + ); + }); it.each(paths)('should generate jwt from cookie for %s', async (path) => { - const data = { sessionJwt: 'sessionJwt' } - const cookie = `${refreshTokenCookieName}=refreshJwt; Domain=; Max-Age=; Path=/; HttpOnly; SameSite=Strict` + const data = { sessionJwt: 'sessionJwt' }; + const cookie = `${refreshTokenCookieName}=refreshJwt; Domain=; Max-Age=; Path=/; HttpOnly; SameSite=Strict`; jest.spyOn(sdk.httpClient, 'post').mockResolvedValueOnce({ ok: true, json: () => Promise.resolve(data), headers: new Headers({ 'set-cookie': cookie }), - } as Response) + } as Response); await expect(get(sdk, path)('1', '2', '3')).resolves.toEqual( expect.objectContaining({ @@ -288,8 +288,32 @@ describe('sdk', () => { ], }, }), - ) - }) - }) - }) -}) + ); + }); + }); + }); + + describe('hooks', () => { + it('should add descope headers to request', async () => { + jest.resetModules(); + const coreSdk = jest.fn(); + jest.doMock('@descope/core-js-sdk', () => coreSdk); + const createNodeSdk = require('.').default; // eslint-disable-line + + createNodeSdk({ + projectId: 'project-id', + logger, + }); + + const returnedConf = coreSdk.mock.calls[0][0].hooks.beforeRequest({}); + + expect(returnedConf).toEqual({ + headers: { + 'x-descope-sdk-name': 'nodejs', + 'x-descope-sdk-node-version': process?.versions?.node || '', + 'x-descope-sdk-version': 'one.two.three', + }, + }); + }); + }); +}); diff --git a/lib/index.ts b/lib/index.ts index 8250f76d..635265bc 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -1,29 +1,47 @@ -import createSdk, { SdkResponse, ExchangeAccessKeyResponse } from '@descope/core-js-sdk' -import { KeyLike, jwtVerify, JWK, JWTHeaderParameters, importJWK } from 'jose' -import fetch, { Headers, Response, Request } from 'node-fetch' -import { bulkWrapWith, withCookie, getAuthorizationClaimItems } from './helpers' -import { AuthenticationInfo } from './types' +import createSdk, { + SdkResponse, + ExchangeAccessKeyResponse, + RequestConfig, +} from '@descope/core-js-sdk'; +import { KeyLike, jwtVerify, JWK, JWTHeaderParameters, importJWK } from 'jose'; +import fetch, { Headers, Response, Request } from 'node-fetch'; +import { bulkWrapWith, withCookie, getAuthorizationClaimItems } from './helpers'; +import { AuthenticationInfo } from './types'; import { refreshTokenCookieName, sessionTokenCookieName, permissionsClaimName, rolesClaimName, -} from './constants' +} from './constants'; + +declare const BUILD_VERSION: string; /* istanbul ignore next */ if (!globalThis.fetch) { // @ts-ignore - globalThis.fetch = fetch + globalThis.fetch = fetch; // @ts-ignore - globalThis.Headers = Headers + globalThis.Headers = Headers; // @ts-ignore - globalThis.Request = Request + globalThis.Request = Request; // @ts-ignore - globalThis.Response = Response + globalThis.Response = Response; } const nodeSdk = (...args: Parameters) => { - const coreSdk = createSdk(...args) + const funcArgs: typeof args = [...args]; + funcArgs[0].hooks = funcArgs[0].hooks || {}; + const origBeforeRequest = funcArgs[0].hooks.beforeRequest; + funcArgs[0].hooks.beforeRequest = (config: RequestConfig) => { + const conf = config; + conf.headers = { + 'x-descope-sdk-name': 'nodejs', + 'x-descope-sdk-node-version': process?.versions?.node || '', + 'x-descope-sdk-version': BUILD_VERSION, + }; + return origBeforeRequest?.(conf) || conf; + }; + const coreSdk = createSdk(...funcArgs); bulkWrapWith( coreSdk, @@ -40,43 +58,43 @@ const nodeSdk = (...args: Parameters) => { 'refresh', ], withCookie, - ) + ); - const { projectId, logger } = args[0] + const { projectId, logger } = args[0]; - const keys: Record = {} + const keys: Record = {}; /** Fetch the public keys (JWKs) from Descope for the configured project */ const fetchKeys = async () => { const publicKeys: JWK[] = await coreSdk.httpClient .get(`v1/keys/${projectId}`) - .then((resp) => resp.json()) - if (!Array.isArray(publicKeys)) return {} + .then((resp) => resp.json()); + if (!Array.isArray(publicKeys)) return {}; const kidJwksPairs = await Promise.all( publicKeys.map(async (key) => [key.kid, await importJWK(key)]), - ) + ); return kidJwksPairs.reduce( (acc, [kid, jwk]) => (kid ? { ...acc, [kid.toString()]: jwk } : acc), {}, - ) - } + ); + }; const sdk = { ...coreSdk, /** Get the key that can validate the given JWT KID in the header. Can retrieve the public key from local cache or from Descope. */ async getKey(header: JWTHeaderParameters): Promise { - if (!header?.kid) throw Error('header.kid must not be empty') + if (!header?.kid) throw Error('header.kid must not be empty'); - if (keys[header.kid]) return keys[header.kid] + if (keys[header.kid]) return keys[header.kid]; // do we need to fetch once or every time? - Object.assign(keys, await fetchKeys()) + Object.assign(keys, await fetchKeys()); - if (!keys[header.kid]) throw Error('failed to fetch matching key') + if (!keys[header.kid]) throw Error('failed to fetch matching key'); - return keys[header.kid] + return keys[header.kid]; }, /** @@ -86,9 +104,9 @@ const nodeSdk = (...args: Parameters) => { */ async validateJwt(jwt: string): Promise { // Do not hard-code the algo because library does not support `None` so all are valid - const res = await jwtVerify(jwt, sdk.getKey, { issuer: projectId, clockTolerance: 5 }) + const res = await jwtVerify(jwt, sdk.getKey, { issuer: projectId, clockTolerance: 5 }); - return { jwt, token: res.payload } + return { jwt, token: res.payload }; }, /** @@ -103,35 +121,35 @@ const nodeSdk = (...args: Parameters) => { refreshToken?: string, ): Promise { if (!sessionToken && !refreshToken) - throw Error('both refresh token and session token are empty') + throw Error('both refresh token and session token are empty'); if (sessionToken) { try { - const token = await sdk.validateJwt(sessionToken) - return token + const token = await sdk.validateJwt(sessionToken); + return token; } catch (error) { if (!refreshToken) { - logger?.error('failed to validate session token and no refresh token provided', error) - throw Error('could not validate tokens') + logger?.error('failed to validate session token and no refresh token provided', error); + throw Error('could not validate tokens'); } } } if (refreshToken) { try { - await sdk.validateJwt(refreshToken) - const jwtResp = await sdk.refresh(refreshToken) + await sdk.validateJwt(refreshToken); + const jwtResp = await sdk.refresh(refreshToken); if (jwtResp.ok) { - const token = await sdk.validateJwt(jwtResp.data?.sessionJwt) - return token + const token = await sdk.validateJwt(jwtResp.data?.sessionJwt); + return token; } - throw Error(jwtResp.error?.message) + throw Error(jwtResp.error?.message); } catch (refreshTokenErr) { - logger?.error('failed to validate refresh token', refreshTokenErr) - throw Error('could not validate tokens') + logger?.error('failed to validate refresh token', refreshTokenErr); + throw Error('could not validate tokens'); } } /* istanbul ignore next */ - throw Error('could not validate token') + throw Error('could not validate token'); }, /** @@ -140,28 +158,28 @@ const nodeSdk = (...args: Parameters) => { * @returns AuthneticationInfo with session JWT data */ async exchangeAccessKey(accessKey: string): Promise { - if (!accessKey) throw Error('access key must not be empty') + if (!accessKey) throw Error('access key must not be empty'); - let resp: SdkResponse + let resp: SdkResponse; try { - resp = await sdk.accessKey.exchange(accessKey) + resp = await sdk.accessKey.exchange(accessKey); } catch (error) { - logger?.error('failed to exchange access key', error) - throw Error('could not exchange access key') + logger?.error('failed to exchange access key', error); + throw Error('could not exchange access key'); } - const { sessionJwt } = resp.data + const { sessionJwt } = resp.data; if (!sessionJwt) { - logger?.error('failed to parse exchange access key response') - throw Error('could not exchange access key') + logger?.error('failed to parse exchange access key response'); + throw Error('could not exchange access key'); } try { - const token = await sdk.validateJwt(sessionJwt) - return token + const token = await sdk.validateJwt(sessionJwt); + return token; } catch (error) { - logger?.error('failed to parse jwt from access key', error) - throw Error('could not exchange access key') + logger?.error('failed to parse jwt from access key', error); + throw Error('could not exchange access key'); } }, @@ -172,7 +190,7 @@ const nodeSdk = (...args: Parameters) => { * @returns true if all permissions exist, false otherwise */ validatePermissions(authInfo: AuthenticationInfo, permissions: string[]): boolean { - return sdk.validateTenantPermissions(authInfo, null, permissions) + return sdk.validateTenantPermissions(authInfo, null, permissions); }, /** @@ -186,8 +204,8 @@ const nodeSdk = (...args: Parameters) => { tenant: string, permissions: string[], ): boolean { - const granted = getAuthorizationClaimItems(authInfo, permissionsClaimName, tenant) - return permissions.every((perm) => granted.includes(perm)) + const granted = getAuthorizationClaimItems(authInfo, permissionsClaimName, tenant); + return permissions.every((perm) => granted.includes(perm)); }, /** @@ -197,7 +215,7 @@ const nodeSdk = (...args: Parameters) => { * @returns true if all roles exist, false otherwise */ validateRoles(authInfo: AuthenticationInfo, roles: string[]): boolean { - return sdk.validateTenantRoles(authInfo, null, roles) + return sdk.validateTenantRoles(authInfo, null, roles); }, /** @@ -207,13 +225,13 @@ const nodeSdk = (...args: Parameters) => { * @returns true if all roles exist, false otherwise */ validateTenantRoles(authInfo: AuthenticationInfo, tenant: string, roles: string[]): boolean { - const membership = getAuthorizationClaimItems(authInfo, rolesClaimName, tenant) - return roles.every((role) => membership.includes(role)) + const membership = getAuthorizationClaimItems(authInfo, rolesClaimName, tenant); + return roles.every((role) => membership.includes(role)); }, - } + }; - return sdk -} + return sdk; +}; /** Descope SDK client with delivery methods enum. * @@ -232,15 +250,15 @@ const nodeSdk = (...args: Parameters) => { * ``` */ const sdkWithAttributes = nodeSdk as typeof nodeSdk & { - DeliveryMethods: typeof createSdk.DeliveryMethods - RefreshTokenCookieName: typeof refreshTokenCookieName - SessionTokenCookieName: typeof sessionTokenCookieName -} + DeliveryMethods: typeof createSdk.DeliveryMethods; + RefreshTokenCookieName: typeof refreshTokenCookieName; + SessionTokenCookieName: typeof sessionTokenCookieName; +}; -sdkWithAttributes.DeliveryMethods = createSdk.DeliveryMethods -sdkWithAttributes.RefreshTokenCookieName = refreshTokenCookieName -sdkWithAttributes.SessionTokenCookieName = sessionTokenCookieName +sdkWithAttributes.DeliveryMethods = createSdk.DeliveryMethods; +sdkWithAttributes.RefreshTokenCookieName = refreshTokenCookieName; +sdkWithAttributes.SessionTokenCookieName = sessionTokenCookieName; -export default sdkWithAttributes +export default sdkWithAttributes; -export type { DeliveryMethod, OAuthProvider } from '@descope/core-js-sdk' +export type { DeliveryMethod, OAuthProvider } from '@descope/core-js-sdk'; diff --git a/lib/types.ts b/lib/types.ts index ef0ec061..17d6c657 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -1,14 +1,14 @@ /** Parsed JWT token */ interface Token { - sub?: string - exp?: number - iss?: string - [claim: string]: unknown + sub?: string; + exp?: number; + iss?: string; + [claim: string]: unknown; } /** All information regarding token including the raw JWT, parsed JWT and cookies */ export interface AuthenticationInfo { - jwt: string - token: Token - cookies?: string[] + jwt: string; + token: Token; + cookies?: string[]; } diff --git a/package-lock.json b/package-lock.json index c9c4a3e2..51569fcc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.4-alpha.6", "license": "MIT", "dependencies": { - "@descope/core-js-sdk": "0.0.41-alpha.22", + "@descope/core-js-sdk": "0.0.41-alpha.24", "jose": "4.10.0", "node-fetch": "2.6.7" }, @@ -41,11 +41,14 @@ "husky": "^8.0.1", "jest": "^28.1.0", "jsdoc": "^3.6.10", + "lint-staged": "^13.0.3", "nock": "^13.2.4", "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "rollup": "^2.62.0", "rollup-plugin-auto-external": "^2.0.0", "rollup-plugin-browsersync": "^1.3.3", + "rollup-plugin-define": "^1.0.1", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-dts": "^4.2.2", "rollup-plugin-esbuild": "^4.9.1", @@ -590,9 +593,9 @@ } }, "node_modules/@descope/core-js-sdk": { - "version": "0.0.41-alpha.22", - "resolved": "https://registry.npmjs.org/@descope/core-js-sdk/-/core-js-sdk-0.0.41-alpha.22.tgz", - "integrity": "sha512-E4kXPWOyrg3+Gy8GkeDaYDXoeXiVRyWauxTLvv0dKA36EEvBnh8nMc6AdbCk7zSzIQbuamu5d3qUzTS2vpCJDA==", + "version": "0.0.41-alpha.24", + "resolved": "https://registry.npmjs.org/@descope/core-js-sdk/-/core-js-sdk-0.0.41-alpha.24.tgz", + "integrity": "sha512-bixKM8KuBnANzGXUD64xKQuVjjl9I10XsXfLNLSFrV6KLyzfwVhkHfFnfZiv02h6vWsi+U5KOGUtgXc8Ncigag==", "dependencies": { "jwt-decode": "3.1.2", "lodash.get": "4.4.2" @@ -2687,6 +2690,15 @@ "node": ">=6.0" } }, + "node_modules/array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/array-includes": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", @@ -2733,6 +2745,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ast-matcher": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ast-matcher/-/ast-matcher-1.1.1.tgz", + "integrity": "sha512-wQPAp09kPFRQsOijM2Blfg4lH6B9MIhIUrhFtDdhD/1JFhPmfg2/+WAjViVYl3N7EwleHI+q/enTHjaDrv+wEw==", + "dev": true + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/async": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", @@ -3312,6 +3348,84 @@ "node": ">=6" } }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/cli-truncate/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -3354,6 +3468,12 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3366,6 +3486,15 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "dev": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -3689,6 +3818,12 @@ "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", "dev": true }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/easy-extender": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", @@ -3752,6 +3887,15 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/engine.io": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz", @@ -7976,153 +8120,416 @@ "uc.micro": "^1.0.1" } }, - "node_modules/livereload": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", - "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==", + "node_modules/lint-staged": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.3.tgz", + "integrity": "sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==", "dev": true, "dependencies": { - "chokidar": "^3.5.0", - "livereload-js": "^3.3.1", - "opts": ">= 1.2.0", - "ws": "^7.4.3" + "cli-truncate": "^3.1.0", + "colorette": "^2.0.17", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^6.1.0", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.1.1" }, "bin": { - "livereload": "bin/livereload.js" + "lint-staged": "bin/lint-staged.js" }, "engines": { - "node": ">=8.0.0" + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" } }, - "node_modules/livereload-js": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.4.1.tgz", - "integrity": "sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==", - "dev": true - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "node_modules/lint-staged/node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", "dev": true, "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "node_modules/lint-staged/node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", "dev": true, - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, "engines": { - "node": ">=4" + "node": ">=12.20.0" } }, - "node_modules/load-json-file/node_modules/pify": { + "node_modules/lint-staged/node_modules/is-stream": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", "dev": true, "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/load-json-file/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==", + "node_modules/lint-staged/node_modules/lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", "dev": true, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/localtunnel": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.2.tgz", - "integrity": "sha512-n418Cn5ynvJd7m/N1d9WVJISLJF/ellZnfsLnx8WBWGzxv/ntNcFkJ1o6se5quUhCplfLGBNL5tYHiq5WF3Nug==", + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", "dev": true, "dependencies": { - "axios": "0.21.4", - "debug": "4.3.2", - "openurl": "1.1.1", - "yargs": "17.1.1" + "path-key": "^4.0.0" }, - "bin": { - "lt": "bin/lt.js" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=8.3.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/localtunnel/node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", "dev": true, "dependencies": { - "ms": "2.1.2" + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">=6.0" + "node": ">=12" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" }, "peerDependenciesMeta": { - "supports-color": { + "enquirer": { "optional": true } } }, - "node_modules/localtunnel/node_modules/yargs": { - "version": "17.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz", - "integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==", + "node_modules/listr2/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=12" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/localtunnel/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/listr2/node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, "engines": { - "node": ">=10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "node_modules/listr2/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=4" + "node": ">=7.0.0" } }, - "node_modules/lodash": { - "version": "4.17.21", + "node_modules/listr2/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/listr2/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/rxjs": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", + "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "dev": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/livereload": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", + "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.0", + "livereload-js": "^3.3.1", + "opts": ">= 1.2.0", + "ws": "^7.4.3" + }, + "bin": { + "livereload": "bin/livereload.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/livereload-js": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.4.1.tgz", + "integrity": "sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/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==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/localtunnel": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/localtunnel/-/localtunnel-2.0.2.tgz", + "integrity": "sha512-n418Cn5ynvJd7m/N1d9WVJISLJF/ellZnfsLnx8WBWGzxv/ntNcFkJ1o6se5quUhCplfLGBNL5tYHiq5WF3Nug==", + "dev": true, + "dependencies": { + "axios": "0.21.4", + "debug": "4.3.2", + "openurl": "1.1.1", + "yargs": "17.1.1" + }, + "bin": { + "lt": "bin/lt.js" + }, + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/localtunnel/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/localtunnel/node_modules/yargs": { + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.1.1.tgz", + "integrity": "sha512-c2k48R0PwKIqKhPMWjeiF6y2xY/gPMUlro0sgxqXpbOIohWiLNXWslsootttv7E1e73QPAMQSg5FeySbVcpsPQ==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/localtunnel/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/lodash": { + "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true @@ -8150,6 +8557,88 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-update/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -8345,12 +8834,37 @@ "node": ">=10" } }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "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/multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "dependencies": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -8799,6 +9313,18 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -8910,61 +9436,268 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "28.1.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.1.tgz", + "integrity": "sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^28.0.2", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-quick": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.3.tgz", + "integrity": "sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==", + "dev": true, + "dependencies": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + }, + "bin": { + "pretty-quick": "bin/pretty-quick.js" + }, + "engines": { + "node": ">=10.13" + }, + "peerDependencies": { + "prettier": ">=2.0.0" + } + }, + "node_modules/pretty-quick/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/pretty-quick/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/pretty-quick/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/pretty-quick/node_modules/execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/pretty-quick/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-quick/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true, + "engines": { + "node": ">=8.12.0" + } + }, + "node_modules/pretty-quick/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "node_modules/pretty-quick/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "bin": { - "prettier": "bin-prettier.js" + "dependencies": { + "p-try": "^2.0.0" }, "engines": { - "node": ">=10.13.0" + "node": ">=6" }, "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "node_modules/pretty-quick/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "fast-diff": "^1.1.2" + "p-limit": "^2.2.0" }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, - "node_modules/pretty-format": { - "version": "28.1.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-28.1.1.tgz", - "integrity": "sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw==", + "node_modules/pretty-quick/node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, - "dependencies": { - "@jest/schemas": "^28.0.2", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, "engines": { - "node": "^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0" + "node": ">=6" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/pretty-quick/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==", "dev": true, "engines": { - "node": ">=10" + "node": ">=8" + } + }, + "node_modules/pretty-quick/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "engines": { + "node": ">=8" } }, "node_modules/prompts": { @@ -8989,6 +9722,16 @@ "node": ">= 8" } }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -9265,6 +10008,19 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -9275,6 +10031,12 @@ "node": ">=0.10.0" } }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -9341,6 +10103,42 @@ "browser-sync": "^2.26.14" } }, + "node_modules/rollup-plugin-define": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-define/-/rollup-plugin-define-1.0.1.tgz", + "integrity": "sha512-SM/CKFpLvWq5xBEf84ff/ooT3KodXPVITCkRliyNccuq8SZMpzthN/Bp7JkWScbGTX5lo1SF3cjxKKDjnnFCuA==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^4.0.0", + "ast-matcher": "^1.1.1", + "escape-string-regexp": "^4.0.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/rollup-plugin-define/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rollup-plugin-define/node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, "node_modules/rollup-plugin-delete": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/rollup-plugin-delete/-/rollup-plugin-delete-2.0.0.tgz", @@ -9811,6 +10609,46 @@ "node": "^14.0.0 || ^16.0.0 || >=18.0.0" } }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/socket.io": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz", @@ -9991,6 +10829,15 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -10327,6 +11174,12 @@ "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, "node_modules/tiny-glob": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", @@ -10916,6 +11769,15 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", + "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", + "dev": true, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.5.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", @@ -11352,9 +12214,9 @@ } }, "@descope/core-js-sdk": { - "version": "0.0.41-alpha.22", - "resolved": "https://registry.npmjs.org/@descope/core-js-sdk/-/core-js-sdk-0.0.41-alpha.22.tgz", - "integrity": "sha512-E4kXPWOyrg3+Gy8GkeDaYDXoeXiVRyWauxTLvv0dKA36EEvBnh8nMc6AdbCk7zSzIQbuamu5d3qUzTS2vpCJDA==", + "version": "0.0.41-alpha.24", + "resolved": "https://registry.npmjs.org/@descope/core-js-sdk/-/core-js-sdk-0.0.41-alpha.24.tgz", + "integrity": "sha512-bixKM8KuBnANzGXUD64xKQuVjjl9I10XsXfLNLSFrV6KLyzfwVhkHfFnfZiv02h6vWsi+U5KOGUtgXc8Ncigag==", "requires": { "jwt-decode": "3.1.2", "lodash.get": "4.4.2" @@ -12966,6 +13828,12 @@ "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", "dev": true }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, "array-includes": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.5.tgz", @@ -12997,6 +13865,24 @@ "es-shim-unscopables": "^1.0.0" } }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "ast-matcher": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ast-matcher/-/ast-matcher-1.1.1.tgz", + "integrity": "sha512-wQPAp09kPFRQsOijM2Blfg4lH6B9MIhIUrhFtDdhD/1JFhPmfg2/+WAjViVYl3N7EwleHI+q/enTHjaDrv+wEw==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, "async": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", @@ -13439,6 +14325,59 @@ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, "cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -13477,6 +14416,12 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -13486,6 +14431,12 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.4.1.tgz", + "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", + "dev": true + }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -13742,6 +14693,12 @@ "integrity": "sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==", "dev": true }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "easy-extender": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/easy-extender/-/easy-extender-2.3.4.tgz", @@ -13790,6 +14747,15 @@ "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, "engine.io": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.0.tgz", @@ -16799,6 +17765,181 @@ "uc.micro": "^1.0.1" } }, + "lint-staged": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.0.3.tgz", + "integrity": "sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==", + "dev": true, + "requires": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.17", + "commander": "^9.3.0", + "debug": "^4.3.4", + "execa": "^6.1.0", + "lilconfig": "2.0.5", + "listr2": "^4.0.5", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-inspect": "^1.12.2", + "pidtree": "^0.6.0", + "string-argv": "^0.3.1", + "yaml": "^2.1.1" + }, + "dependencies": { + "execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "lilconfig": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", + "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + } + } + }, + "listr2": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", + "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", + "dev": true, + "requires": { + "cli-truncate": "^2.1.0", + "colorette": "^2.0.16", + "log-update": "^4.0.0", + "p-map": "^4.0.0", + "rfdc": "^1.3.0", + "rxjs": "^7.5.5", + "through": "^2.3.8", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "requires": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rxjs": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz", + "integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==", + "dev": true, + "requires": { + "tslib": "^2.1.0" + } + }, + "slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + } + } + }, "livereload": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", @@ -16936,6 +18077,66 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "log-update": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", + "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.3.0", + "cli-cursor": "^3.1.0", + "slice-ansi": "^4.0.0", + "wrap-ansi": "^6.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + } + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -17083,12 +18284,31 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, + "mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true + }, "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 }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + } + }, "nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", @@ -17419,6 +18639,12 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true + }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -17536,6 +18762,152 @@ } } }, + "pretty-quick": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-3.1.3.tgz", + "integrity": "sha512-kOCi2FJabvuh1as9enxYmrnBC6tVMoVOenMaBqRfsvBHB0cbpYHjdQEpSglpASDFEXVwplpcGR4CLEaisYAFcA==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "execa": "^4.0.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.5", + "multimatch": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "execa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", + "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "human-signals": "^1.1.1", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.0", + "onetime": "^5.1.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "human-signals": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", + "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "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==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -17552,6 +18924,16 @@ "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", "dev": true }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -17757,12 +19139,28 @@ } } }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -17810,6 +19208,35 @@ "browser-sync": "^2.26.14" } }, + "rollup-plugin-define": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-define/-/rollup-plugin-define-1.0.1.tgz", + "integrity": "sha512-SM/CKFpLvWq5xBEf84ff/ooT3KodXPVITCkRliyNccuq8SZMpzthN/Bp7JkWScbGTX5lo1SF3cjxKKDjnnFCuA==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^4.0.0", + "ast-matcher": "^1.1.1", + "escape-string-regexp": "^4.0.0", + "magic-string": "^0.25.7" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + } + } + }, "rollup-plugin-delete": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/rollup-plugin-delete/-/rollup-plugin-delete-2.0.0.tgz", @@ -18189,6 +19616,30 @@ "picocolors": "^1.0.0" } }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + } + } + }, "socket.io": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.1.tgz", @@ -18345,6 +19796,12 @@ } } }, + "string-argv": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", + "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", + "dev": true + }, "string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -18600,6 +20057,12 @@ "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, "tiny-glob": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", @@ -19009,6 +20472,12 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yaml": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz", + "integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==", + "dev": true + }, "yargs": { "version": "17.5.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", diff --git a/package.json b/package.json index edc15f51..7f578d59 100644 --- a/package.json +++ b/package.json @@ -23,15 +23,22 @@ }, "scripts": { "build": "rimraf dist && rollup -c", + "prepare": "husky install", "quick": "npm i && npm run build && cd examples/es6/ && npm i && npm run generateCerts && npm start", - "format": "prettier --write lib", - "check-format": "prettier --check lib", + "format": "prettier . --write --ignore-path .gitignore", + "format-check": "prettier . --check --ignore-path .gitignore", + "format-lint": "pretty-quick --staged --ignore-path .gitignore && lint-staged", "size": "npm run build && size-limit", "lint": "eslint lib/**/*.ts --fix", "leaks": "bash ./scripts/gitleaks/gitleaks.sh", "test": "jest --forceExit --coverage --ci --detectOpenHandles .*test.*", "prepublishOnly": "npm run build" }, + "lint-staged": { + "+(src|lib)/**/*.{js,ts,jsx,tsx}": [ + "npm run lint" + ] + }, "author": "Descope", "bugs": { "url": "git://github.com/descope/node-sdk/issues" @@ -69,11 +76,14 @@ "husky": "^8.0.1", "jest": "^28.1.0", "jsdoc": "^3.6.10", + "lint-staged": "^13.0.3", "nock": "^13.2.4", "prettier": "^2.7.1", + "pretty-quick": "^3.1.3", "rollup": "^2.62.0", "rollup-plugin-auto-external": "^2.0.0", "rollup-plugin-browsersync": "^1.3.3", + "rollup-plugin-define": "^1.0.1", "rollup-plugin-delete": "^2.0.0", "rollup-plugin-dts": "^4.2.2", "rollup-plugin-esbuild": "^4.9.1", @@ -85,7 +95,7 @@ "typescript": "^4.6.4" }, "dependencies": { - "@descope/core-js-sdk": "0.0.41-alpha.22", + "@descope/core-js-sdk": "0.0.41-alpha.24", "jose": "4.10.0", "node-fetch": "2.6.7" }, diff --git a/rollup.config.js b/rollup.config.js index b318d098..b2376074 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,71 +4,78 @@ import { terser } from 'rollup-plugin-terser'; import dts from 'rollup-plugin-dts'; import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; -import json from "@rollup/plugin-json"; -import fs from 'fs' +import json from '@rollup/plugin-json'; +import fs from 'fs'; +import define from 'rollup-plugin-define'; const packageJson = require('./package.json'); const plugins = [ - typescript({ - tsconfig: './tsconfig.json' - }), - json(), - commonjs(), - resolve(), - terser() -] -const input = './lib/index.ts' -const external = (id) => !id.startsWith('\0') && !id.startsWith('.') && !id.startsWith('/') + define({ + replacements: { + BUILD_VERSION: JSON.stringify(require('./package.json').version), + }, + }), + typescript({ + tsconfig: './tsconfig.json', + }), + json(), + commonjs(), + resolve(), + terser(), +]; +const input = './lib/index.ts'; +const external = (id) => !id.startsWith('\0') && !id.startsWith('.') && !id.startsWith('/'); export default [ - { - input, - output: - { - file: packageJson.main, - format: 'cjs', - sourcemap: true, - exports: 'default', - }, - plugins, - external - }, - { - input, - output: - { - file: packageJson.module, - format: 'esm', - sourcemap: true, - }, - plugins, - external - }, - { - input, - output: - { - file: 'dist/index.umd.js', - format: 'umd', - sourcemap: true, - name: 'descopeSdk' - }, - plugins, - }, + { + input, + output: { + file: packageJson.main, + format: 'cjs', + sourcemap: true, + exports: 'default', + }, + plugins, + external, + }, + { + input, + output: { + file: packageJson.module, + format: 'esm', + sourcemap: true, + }, + plugins, + external, + }, + { + input, + output: { + file: 'dist/index.umd.js', + format: 'umd', + sourcemap: true, + name: 'descopeSdk', + }, + plugins, + }, - { - input: './dist/lib/index.d.ts', - output: [{ file: packageJson.types, format: 'esm' }], - plugins: [dts(), del({ hook: 'buildEnd', targets: ['./dist/lib', './dist/cjs/lib'] }), cjsPackage()] - } + { + input: './dist/lib/index.d.ts', + output: [{ file: packageJson.types, format: 'esm' }], + plugins: [ + dts(), + del({ hook: 'buildEnd', targets: ['./dist/lib', './dist/cjs/lib'] }), + cjsPackage(), + ], + }, ]; function cjsPackage() { - return { - name: 'cjsPackage', - buildEnd: () => { - fs.writeFileSync('./dist/cjs/package.json', JSON.stringify({ type: 'commonjs' })) - } - } -} \ No newline at end of file + return { + name: 'cjsPackage', + buildEnd: () => { + fs.writeFileSync('./dist/cjs/package.json', JSON.stringify({ type: 'commonjs' })); + }, + }; +} diff --git a/tsconfig.json b/tsconfig.json index 04cf6800..720e1c52 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,21 +1,21 @@ { - "compilerOptions": { - "rootDir": ".", - "target": "es2017", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": false, - "skipLibCheck": true, - "strict": false, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "declaration": true, - "declarationDir": "dts", - "typeRoots": ["./node_modules/@types"] - }, + "compilerOptions": { + "rootDir": ".", + "target": "es2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": false, + "skipLibCheck": true, + "strict": false, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "declaration": true, + "declarationDir": "dts", + "typeRoots": ["./node_modules/@types"] + }, - "include": ["**/*.ts"], - "exclude": ["node_modules", "build", "dist", "test", "examples"] + "include": ["**/*.ts"], + "exclude": ["node_modules", "build", "dist", "test"] }