From dc21479a1a03a1a8eb48a21a16366354b640e440 Mon Sep 17 00:00:00 2001 From: Radu-Cristian Popa Date: Mon, 22 Jan 2024 08:10:06 +0200 Subject: [PATCH] Update README, ESLint and Prettier configs --- .eslintignore | 1 + .eslintrc.js | 57 ++ .eslintrc.json | 97 --- .github/actions/constants.cjs | 10 +- .github/actions/delete-artifacts.cjs | 40 +- .github/actions/get-workflow-artifacts.cjs | 76 +-- .prettierignore | 2 + .prettierrc.js | 13 + .prettierrc.json | 10 - README.md | 45 +- jest.config.ts | 2 +- package.json | 21 +- packages/extension/.eslintrc.js | 33 + packages/extension/jest.config.ts | 4 +- packages/extension/jest.setup.ts | 6 +- packages/extension/package.json | 10 +- packages/extension/scripts/dev.sh | 2 +- .../extension/src/_locales/en/messages.json | 24 +- packages/extension/src/background/config.ts | 8 +- .../src/background/grant/confirmPayment.ts | 30 +- .../src/background/grant/createQuote.ts | 28 +- .../grant/getContinuationRequest.ts | 22 +- .../src/background/grant/getHeaders.ts | 2 +- .../grant/getIcomingPaymentGrant.ts | 22 +- .../grant/getIncomingPaymentUrlId.ts | 20 +- .../grant/getOutgoingPaymentGrant.ts | 24 +- .../src/background/grant/getQuoteGrant.ts | 22 +- .../extension/src/background/grant/index.ts | 20 +- .../src/background/grant/rotateToken.ts | 20 +- .../extension/src/background/grantFlow.ts | 100 +-- packages/extension/src/background/index.ts | 160 ++--- .../extension/src/background/requestConfig.ts | 26 +- .../Popup/PopupFooter/PopupFooter.tsx | 10 +- .../src/components/Popup/PopupFooter/index.ts | 2 +- .../Popup/PopupHeader/PopupHeader.tsx | 16 +- .../src/components/Popup/PopupHeader/index.ts | 2 +- .../src/components/__tests__/button.test.tsx | 64 +- .../src/components/__tests__/input.test.tsx | 68 +- .../src/components/__tests__/switch.test.tsx | 92 +-- packages/extension/src/components/button.tsx | 21 +- packages/extension/src/components/icons.tsx | 19 +- packages/extension/src/components/input.tsx | 18 +- packages/extension/src/components/label.tsx | 14 +- .../src/components/loading-spinner.tsx | 14 +- packages/extension/src/components/switch.tsx | 14 +- packages/extension/src/content/index.tsx | 28 +- .../extension/src/content/linksObserver.ts | 22 +- .../extension/src/content/messageListener.ts | 28 +- .../extension/src/content/monetization.tsx | 14 +- .../extension/src/manifest/chrome-v3.json | 72 +-- packages/extension/src/manifest/chrome.json | 56 +- packages/extension/src/manifest/edge.json | 50 +- .../extension/src/manifest/firefox-v3.json | 86 +-- packages/extension/src/manifest/firefox.json | 68 +- packages/extension/src/manifest/opera.json | 50 +- packages/extension/src/popup/Popup.scss | 2 +- packages/extension/src/popup/Popup.tsx | 114 ++-- packages/extension/src/popup/index.html | 16 +- packages/extension/src/popup/index.tsx | 12 +- packages/extension/src/types/message.d.ts | 8 +- packages/extension/src/types/openControl.d.ts | 12 +- packages/extension/src/types/response.d.ts | 8 +- packages/extension/src/utils/cn.ts | 6 +- .../monetizationTagManager/CustomError.ts | 8 +- .../MonetizationTagManager.ts | 292 ++++----- .../src/utils/monetizationTagManager/index.ts | 30 +- .../utils/monetizationTagManager/mozClone.ts | 14 +- .../resolvePaymentEndpoint.ts | 22 +- .../whenDocumentReady.ts | 6 +- packages/extension/src/utils/polyfill.ts | 2 +- packages/extension/src/utils/sendMessages.ts | 24 +- packages/extension/src/utils/storage.ts | 4 +- packages/extension/tailwind.config.ts | 4 +- packages/extension/webpack.config.ts | 24 +- packages/extension/webpack.config.utils.ts | 93 +-- packages/server/.eslintrc.js | 5 + packages/server/package.json | 12 +- packages/server/src/index.ts | 56 +- pnpm-lock.yaml | 586 ++++++++---------- tsconfig.json | 2 +- 80 files changed, 1537 insertions(+), 1610 deletions(-) create mode 100644 .eslintrc.js delete mode 100644 .eslintrc.json create mode 100644 .prettierrc.js delete mode 100644 .prettierrc.json create mode 100644 packages/extension/.eslintrc.js create mode 100644 packages/server/.eslintrc.js diff --git a/.eslintignore b/.eslintignore index 9c2bae7c..a5e0897b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ !.github node_modules/ dist +*/dist diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..93e509c3 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,57 @@ +module.exports = { + root: true, + env: { + es2020: true, + browser: true, + node: true, + }, + extends: [ + 'plugin:@typescript-eslint/recommended', + 'eslint:recommended', + 'plugin:import/typescript', + 'plugin:jsx-a11y/recommended', + 'plugin:@typescript-eslint/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + sourceType: 'module', + ecmaVersion: 2020, + ecmaFeatures: { jsx: true }, + }, + plugins: [ + 'html', + 'node', + 'cypress', + '@typescript-eslint', + 'jest', + '@typescript-eslint', + 'simple-import-sort', + ], + rules: { + 'no-param-reassign': 'error', + 'no-use-before-define': 'off', + 'no-underscore-dangle': 'off', + 'no-implicit-coercion': ['error', { allow: ['!!'] }], + 'block-scoped-var': 'error', + 'no-shadow': 'warn', + 'no-unsafe-optional-chaining': ['error', { disallowArithmeticOperators: true }], + 'no-unused-vars': ['error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + 'no-return-assign': 'warn', + 'consistent-return': 'off', + 'no-redeclare': 'error', + 'simple-import-sort/imports': 'error', + 'simple-import-sort/exports': 'error', + 'import/prefer-default-export': 'off', + 'jsx-a11y/anchor-is-valid': 'warn', + 'jsx-a11y/no-noninteractive-tabindex': 'warn', + 'jsx-a11y/tabindex-no-positive': 'warn', + 'jsx-a11y/click-events-have-key-events': 'warn', + 'jsx-a11y/no-static-element-interactions': 'warn', + 'jsx-a11y/no-noninteractive-element-interactions': 'warn', + // TODO: Re-ctivate rule when we have a custom logger + 'no-console': 'off', + 'no-empty': ['error', { allowEmptyCatch: true }], + '@typescript-eslint/no-explicit-any': 'off', + }, + ignorePatterns: ['**/dist/**', '**/dev/**', '**/coverage/**', '**/temp/**'], +}; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index ca9b8c95..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "env": { - "es2020": true, - "browser": true, - "node": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:prettier/recommended", - "eslint:recommended", - "plugin:react/recommended", - "plugin:react-hooks/recommended", - "plugin:import/typescript", - "plugin:jsx-a11y/recommended", - "plugin:cypress/recommended", - "prettier", - "plugin:jest/recommended", - "plugin:@typescript-eslint/recommended" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "sourceType": "module", - "ecmaVersion": 2020, - "ecmaFeatures": { "jsx": true } - }, - "plugins": [ - "html", - "prettier", - "react", - "node", - "react-hooks", - "cypress", - "@typescript-eslint", - "jest", - "@typescript-eslint", - "simple-import-sort" - ], - "settings": { - "react": { - "version": "detect" - } - }, - "rules": { - "semi": "off", - "prettier/prettier": "error", - "maxWarnings": "off", - "react/self-closing-comp": [ - "error", - { - "component": true, - "html": true - } - ], - "react/prop-types": "off", - "no-param-reassign": "error", - "no-use-before-define": "off", - "no-underscore-dangle": "off", - "no-implicit-coercion": ["error", { "allow": ["!!"] }], - "block-scoped-var": "error", - "no-shadow": "warn", - "no-unsafe-optional-chaining": ["error", { "disallowArithmeticOperators": true }], - "no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }], - "no-return-assign": "warn", - "consistent-return": "off", - "no-redeclare": "error", - "simple-import-sort/imports": "error", - "simple-import-sort/exports": "error", - "react/jsx-props-no-spreading": "off", - "import/prefer-default-export": "off", - "jsx-a11y/anchor-is-valid": "warn", - "jsx-a11y/no-noninteractive-tabindex": "warn", - "jsx-a11y/tabindex-no-positive": "warn", - "jsx-a11y/click-events-have-key-events": "warn", - "jsx-a11y/no-static-element-interactions": "warn", - "jsx-a11y/no-noninteractive-element-interactions": "warn", - "no-console": "warn", - "no-empty": ["error", { "allowEmptyCatch": true }], - "react-hooks/rules-of-hooks": "error", - "react-hooks/exhaustive-deps": "error", - "react/react-in-jsx-scope": "off", - "react/jsx-uses-react": "off", - "@typescript-eslint/no-explicit-any": "off" - }, - "overrides": [ - { - "files": [".*rc.js", ".*rc.cjs", "*.config.js", "*.config.cjs"], - "env": { - "node": true - } - } - ], - "ignorePatterns": ["dist/**", "dev/**", "coverage/**"], - "globals": { - "chrome": true, - "browser": true - } -} diff --git a/.github/actions/constants.cjs b/.github/actions/constants.cjs index aeb9b973..82bcbe5f 100644 --- a/.github/actions/constants.cjs +++ b/.github/actions/constants.cjs @@ -1,10 +1,10 @@ const BADGE = - 'Badge' -const BROWSERS = ['chrome', 'firefox', 'opera', 'edge'] + 'Badge'; +const BROWSERS = ['chrome', 'firefox', 'opera', 'edge']; const COLORS = { green: '3fb950', red: 'd73a49', -} +}; const TEMPLATE_VARS = { tableBody: '{{ TABLE_BODY }}', sha: '{{ SHA }}', @@ -12,11 +12,11 @@ const TEMPLATE_VARS = { badgeColor: '{{ BADGE_COLOR }}', badgeLabel: '{{ BADGE_LABEL }}', jobLogs: '{{ JOB_LOGS }}', -} +}; module.exports = { BADGE, BROWSERS, COLORS, TEMPLATE_VARS, -} +}; diff --git a/.github/actions/delete-artifacts.cjs b/.github/actions/delete-artifacts.cjs index 216bc033..2a891330 100644 --- a/.github/actions/delete-artifacts.cjs +++ b/.github/actions/delete-artifacts.cjs @@ -1,25 +1,25 @@ /* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable no-console */ -const { BROWSERS } = require('./constants.cjs') +const { BROWSERS } = require('./constants.cjs'); async function getBrowserArfifacts({ github, owner, repo, name }) { - const artifacts = [] + const artifacts = []; const result = await github.rest.actions.listArtifactsForRepo({ owner, repo, name, - }) + }); for (let i = 0; i < result.data.total_count; i++) { - artifacts.push(result.data.artifacts[i].id) + artifacts.push(result.data.artifacts[i].id); } - return artifacts + return artifacts; } async function getPRArtifacts({ github, owner, repo, prNumber }) { - const promises = [] - const artifacts = [] + const promises = []; + const artifacts = []; BROWSERS.forEach(browser => promises.push( @@ -30,27 +30,27 @@ async function getPRArtifacts({ github, owner, repo, prNumber }) { name: `${prNumber}-${browser}`, }), ), - ) + ); - const data = await Promise.all(promises) + const data = await Promise.all(promises); for (let i = 0; i < data.length; i++) { - artifacts.push.apply(artifacts, data[i]) + artifacts.push.apply(artifacts, data[i]); } - return artifacts + return artifacts; } module.exports = async ({ github, context, core }) => { if (context.payload.action !== 'closed') { - core.setFailed('This action only works on closed PRs.') + core.setFailed('This action only works on closed PRs.'); } - const { owner, repo } = context.repo - const prNumber = context.payload.number - const promises = [] + const { owner, repo } = context.repo; + const prNumber = context.payload.number; + const promises = []; - const artifacts = await getPRArtifacts({ github, owner, repo, prNumber }) + const artifacts = await getPRArtifacts({ github, owner, repo, prNumber }); for (let i = 0; i < artifacts.length; i++) { promises.push( @@ -59,9 +59,9 @@ module.exports = async ({ github, context, core }) => { repo, artifact_id: artifacts[i], }), - ) + ); } - await Promise.all(promises) - console.log(`Deleted ${artifacts.length} artifacts for PR #${prNumber}.`) -} + await Promise.all(promises); + console.log(`Deleted ${artifacts.length} artifacts for PR #${prNumber}.`); +}; diff --git a/.github/actions/get-workflow-artifacts.cjs b/.github/actions/get-workflow-artifacts.cjs index e6ada883..2db0e7e3 100644 --- a/.github/actions/get-workflow-artifacts.cjs +++ b/.github/actions/get-workflow-artifacts.cjs @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-var-requires */ /* eslint-disable no-console */ -const fs = require('node:fs/promises') -const { COLORS, TEMPLATE_VARS, BADGE } = require('./constants.cjs') +const fs = require('node:fs/promises'); +const { COLORS, TEMPLATE_VARS, BADGE } = require('./constants.cjs'); const ARTIFACTS_DATA = { chrome: { @@ -24,73 +24,73 @@ const ARTIFACTS_DATA = { url: null, size: null, }, -} +}; function getBadge(conclusion, badgeColor, badgeLabel) { return BADGE.replace(TEMPLATE_VARS.conslusion, conclusion) .replace(TEMPLATE_VARS.badgeColor, badgeColor) - .replace(TEMPLATE_VARS.badgeLabel, badgeLabel) + .replace(TEMPLATE_VARS.badgeLabel, badgeLabel); } function formatBytes(bytes, decimals = 2) { - if (!Number(bytes)) return '0B' - const k = 1024 - const dm = decimals < 0 ? 0 : decimals - const sizes = ['B', 'KB', 'MB', 'GB'] - const i = Math.floor(Math.log(bytes) / Math.log(k)) - return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))}${sizes[i]}` + if (!Number(bytes)) return '0B'; + const k = 1024; + const dm = decimals < 0 ? 0 : decimals; + const sizes = ['B', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))}${sizes[i]}`; } module.exports = async ({ github, context, core }) => { - const { owner, repo } = context.repo - const baseUrl = context.payload.repository.html_url - const suiteId = context.payload.workflow_run.check_suite_id - const runId = context.payload.workflow_run.id - const conclusion = context.payload.workflow_run.conclusion - const sha = context.payload.workflow_run.pull_requests[0].head.sha - const prNumber = context.payload.workflow_run.pull_requests[0].number - const jobLogsUrl = `${baseUrl}/actions/runs/${context.payload.workflow_run.id}` - const template = await fs.readFile('./.github/actions/templates/build-status.md', 'utf8') - const tableRows = [] + const { owner, repo } = context.repo; + const baseUrl = context.payload.repository.html_url; + const suiteId = context.payload.workflow_run.check_suite_id; + const runId = context.payload.workflow_run.id; + const conclusion = context.payload.workflow_run.conclusion; + const sha = context.payload.workflow_run.pull_requests[0].head.sha; + const prNumber = context.payload.workflow_run.pull_requests[0].number; + const jobLogsUrl = `${baseUrl}/actions/runs/${context.payload.workflow_run.id}`; + const template = await fs.readFile('./.github/actions/templates/build-status.md', 'utf8'); + const tableRows = []; - core.setOutput('conclusion', conclusion) + core.setOutput('conclusion', conclusion); if (conclusion === 'cancelled') { - return + return; } const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ owner, repo, run_id: runId, - }) + }); artifacts.data.artifacts.forEach(artifact => { - const [, key] = artifact.name.split('-') - ARTIFACTS_DATA[key].url = `${baseUrl}/suites/${suiteId}/artifacts/${artifact.id}` - ARTIFACTS_DATA[key].size = formatBytes(artifact.size_in_bytes) - }) + const [, key] = artifact.name.split('-'); + ARTIFACTS_DATA[key].url = `${baseUrl}/suites/${suiteId}/artifacts/${artifact.id}`; + ARTIFACTS_DATA[key].size = formatBytes(artifact.size_in_bytes); + }); Object.keys(ARTIFACTS_DATA).forEach(k => { - const { name, url, size } = ARTIFACTS_DATA[k] + const { name, url, size } = ARTIFACTS_DATA[k]; if (url === null && size === null) { - const badgeUrl = getBadge('failure', COLORS.red, name) - tableRows.push(`${badgeUrl}N/A`) + const badgeUrl = getBadge('failure', COLORS.red, name); + tableRows.push(`${badgeUrl}N/A`); } else { - const badgeUrl = getBadge('success', COLORS.green, `${name} (${size})`) + const badgeUrl = getBadge('success', COLORS.green, `${name} (${size})`); tableRows.push( `${badgeUrl}Download`, - ) + ); } - }) + }); - const tableBody = tableRows.join('') + const tableBody = tableRows.join(''); const commentBody = template .replace(TEMPLATE_VARS.conslusion, conclusion) .replace(TEMPLATE_VARS.sha, sha) .replace(TEMPLATE_VARS.jobLogs, `Run #${runId}`) - .replace(TEMPLATE_VARS.tableBody, tableBody) + .replace(TEMPLATE_VARS.tableBody, tableBody); - core.setOutput('comment_body', commentBody) - core.setOutput('pr_number', prNumber) -} + core.setOutput('comment_body', commentBody); + core.setOutput('pr_number', prNumber); +}; diff --git a/.prettierignore b/.prettierignore index 26f5c409..3d96fd5e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,6 +1,8 @@ public generated dist +temp +dev pnpm-lock.yaml *.svg .gitignore diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..ad2fae3b --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,13 @@ +/** @typedef {import("prettier").Config} PrettierConfig */ + +/** @type { PrettierConfig } */ +module.exports = { + singleQuote: true, + printWidth: 100, + trailingComma: 'all', + quoteProps: 'as-needed', + bracketSpacing: true, + arrowParens: 'avoid', + bracketSameLine: false, + semi: true, +}; diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index e5e9ede8..00000000 --- a/.prettierrc.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "singleQuote": true, - "printWidth": 100, - "trailingComma": "all", - "quoteProps": "as-needed", - "bracketSpacing": true, - "arrowParens": "avoid", - "bracketSameLine": true, - "semi": false -} diff --git a/README.md b/README.md index 2d9c2ff3..ac5cd605 100755 --- a/README.md +++ b/README.md @@ -3,9 +3,7 @@ ![Github Actions CI](https://github.com/interledger/web-monetization-extension/actions/workflows/sanity.yml/badge.svg?branch=main) [![Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://prettier.io/) -Web Monetization is a browser extension that detects Web Monetization on websites using a browser API that allows the -creation of a payment stream from the user agent to the website. This extension is built with React, TypeScript, and -Vite. +Web Monetization is a browser extension that detects Web Monetization on websites using a browser API that allows the creation of a payment stream from the user agent to the website. ### Contributing @@ -19,26 +17,35 @@ Please read the [contribution guidelines](.github/CONTRIBUTING.md) before submit ### Development -To run the extension in development mode with hot reload, use the following command: +To run the extension and the Web Monetization server in development mode with hot reload, use the following command: -`pnpm dev` +```sh +pnpm dev # default Chrome +pnpm dev firefox # For Firefox +pnpm dev opera # For Opera +pnpm dev edge # For Edge +``` -This command builds the extension using Vite's hot reload feature, allowing you to see immediate changes in the browser -as you modify the code. +### Building the extension -### Building the Extension +To build the extension for production (all browsers), use the following command: -To build the extension for production, use the following command: +```sh +pnpm extension build +``` -`pnpm build` +### Building the extension for a specific browser -### Building the Extension for Firefox +To build the extension for a specific browser, use one of the following commands: -To build the extension for Firefox, use the following command: +```sh +pnpm extension build chrome +pnpm extension build firefox +pnpm extension build opera +pnpm extension build edge +``` -`pnpm build firefox` - -This command transpiles the TypeScript code and generates a production-ready build of the extension in the dist +The `build` command transpiles the TypeScript code and generates a production-ready build of the extension in the `packages/extension/dist` directory. ### Installing the Extension in Chrome @@ -77,7 +84,7 @@ To install the extension in Chrome, follow these steps: 4. Select the Extension File:
Navigate to the folder where you extracted the extension files and select the manifest.json file or the main folder of the extension. -### Testing the Extension +### Testing To run the tests, use the following command: @@ -85,11 +92,9 @@ To run the tests, use the following command: This command runs the tests using Jest and generates a coverage report in the coverage directory. -### Linting and Pre-Commit Hooks +### Linting -The extension is set up with ESLint and Prettier for code linting and formatting. Husky and lint-staged are configured -to enforce linting and formatting rules before each commit. When you commit changes, Husky will run the linting and -formatting tasks to ensure code quality. +The extension is set up with ESLint and Prettier for code linting and formatting. ## License diff --git a/jest.config.ts b/jest.config.ts index 924de69a..fc9ff9c2 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -22,4 +22,4 @@ export default { '^.+\\.(ts|tsx)?$': 'ts-jest', '\\.(css|less|scss|sass|svg)$': 'jest-transform-stub', }, -} +}; diff --git a/package.json b/package.json index a0da47b4..4ab8cdd4 100644 --- a/package.json +++ b/package.json @@ -9,13 +9,16 @@ "license": "Apache-2.0", "author": "Interledger Tech Team ", "scripts": { - "extension": "pnpm --filter @interledger/wm-extension --", - "lint": "concurrently \"lint:*\"", - "lint:fix": "eslint --ext js,jsx,ts,tsx, src --fix", - "lint:eslint": "eslint . --ext .js,.ts,.tsx --max-warnings 0 --ignore-path .gitignore", - "lint:prettier": "prettier \"**/*.(md|json|yml)\" --ignore-path .gitignore --check", - "lint:type": "tsc --noEmit", - "wm-server": "pnpm --filter @interledger/wm-server --" + "build": "pnpm -r build", + "dev": "concurrently -P -n SERVER,EXTESNION -c \"red,blue\" \"pnpm wm-server dev\" \"pnpm extension dev {1}\" --", + "format": "prettier --check .", + "format:fix": "prettier --write .", + "lint": "pnpm -r lint", + "lint:fix": "pnpm -r lint:fix eslint --ext js,jsx,ts,tsx, src --fix && prettier --write .", + "typecheck": "pnpm -r typecheck", + "test": "pnpm -r test", + "extension": "pnpm --filter @interledger/wm-extension", + "wm-server": "pnpm --filter @interledger/wm-server" }, "devDependencies": { "@testing-library/jest-dom": "^6.1.3", @@ -26,15 +29,11 @@ "concurrently": "^8.2.2", "eslint": "^8.48.0", "eslint-config-airbnb": "^19.0.4", - "eslint-config-prettier": "^9.0.0", "eslint-plugin-babel": "^5.3.1", - "eslint-plugin-cypress": "^2.12.1", "eslint-plugin-html": "^7.1.0", "eslint-plugin-import": "^2.28.0", - "eslint-plugin-jest": "^26.1.5", "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-simple-import-sort": "^7.0.0", diff --git a/packages/extension/.eslintrc.js b/packages/extension/.eslintrc.js new file mode 100644 index 00000000..1c0b00a3 --- /dev/null +++ b/packages/extension/.eslintrc.js @@ -0,0 +1,33 @@ +module.exports = { + env: { + es2020: true, + browser: true, + node: true, + }, + globals: { + chrome: true, + browser: true, + }, + extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'], + plugins: ['react', 'react-hooks'], + settings: { + react: { + version: 'detect', + }, + }, + rules: { + 'react/self-closing-comp': [ + 'error', + { + component: true, + html: true, + }, + ], + 'react/prop-types': 'off', + 'react/jsx-props-no-spreading': 'off', + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'error', + 'react/react-in-jsx-scope': 'off', + 'react/jsx-uses-react': 'off', + }, +}; diff --git a/packages/extension/jest.config.ts b/packages/extension/jest.config.ts index 3df4697a..088c80f9 100644 --- a/packages/extension/jest.config.ts +++ b/packages/extension/jest.config.ts @@ -1,8 +1,8 @@ -import config from '../../jest.config' +import config from '../../jest.config'; export default { ...config, displayName: '[WM] Extension', setupFilesAfterEnv: ['./jest.setup.ts'], testEnvironment: 'jsdom', -} +}; diff --git a/packages/extension/jest.setup.ts b/packages/extension/jest.setup.ts index 60d87370..e524c769 100644 --- a/packages/extension/jest.setup.ts +++ b/packages/extension/jest.setup.ts @@ -1,5 +1,5 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom'; -import { chrome } from 'jest-chrome' +import { chrome } from 'jest-chrome'; -Object.assign(global, { chrome: chrome, browser: chrome }) +Object.assign(global, { chrome: chrome, browser: chrome }); diff --git a/packages/extension/package.json b/packages/extension/package.json index 243f2d5d..e60601a5 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -15,12 +15,10 @@ "analyze": "bash ./scripts/analyze.sh", "build": "bash ./scripts/build.sh", "dev": "bash ./scripts/dev.sh", - "lint": "concurrently \"lint:*\"", - "lint:fix": "eslint --ext js,jsx,ts,tsx, src --fix", - "lint:eslint": "eslint . --ext .js,.ts,.tsx --max-warnings 0 --ignore-path .gitignore", - "lint:prettier": "prettier \"**/*.(md|json|yml)\" --ignore-path .gitignore --check", - "lint:type": "tsc --noEmit", - "local-signatures": "pnpm tsx --watch ./local-signatures/index.ts", + "format": "prettier --write .", + "lint": "eslint . --ext ts,tsx --cache --cache-location 'node_modules/.cache/.eslintcache' --max-warnings 0", + "lint:fix": "eslint --ext ts,tsx --cache --cache-location 'node_modules/.cache/.eslintcache' --fix", + "typecheck": "tsc --noEmit", "test": "jest --maxWorkers=2 --passWithNoTests", "test:ci": "pnpm test -- --reporters=default --reporters=github-actions" }, diff --git a/packages/extension/scripts/dev.sh b/packages/extension/scripts/dev.sh index 220fa448..9c6c6632 100755 --- a/packages/extension/scripts/dev.sh +++ b/packages/extension/scripts/dev.sh @@ -6,4 +6,4 @@ TARGET=${1:-chrome} NODE_ENV=development echo Running ${NODE_ENV} build for ${TARGET}... -pnpm concurrently -n SIGNATURES,EXTENSION -c green.bold,blue.bold "pnpm local-signatures" "NODE_ENV=${NODE_ENV} TARGET=${TARGET} webpack" +NODE_ENV=${NODE_ENV} TARGET=${TARGET} pnpm webpack diff --git a/packages/extension/src/_locales/en/messages.json b/packages/extension/src/_locales/en/messages.json index b22d4478..e3a1b4f3 100755 --- a/packages/extension/src/_locales/en/messages.json +++ b/packages/extension/src/_locales/en/messages.json @@ -1,14 +1,14 @@ { - "appName": { - "message": "Web Monetization", - "description": "Web Monetization is a browser API that allows the creation of a payment stream from the user agent to the website." - }, - "appDescription": { - "message": "Web Monetization Extension", - "description": "Web Monetization is a browser API that allows the creation of a payment stream from the user agent to the website." - }, - "btnTooltip": { - "message": "Web Monetization", - "description": "..." - } + "appName": { + "message": "Web Monetization", + "description": "Web Monetization is a browser API that allows the creation of a payment stream from the user agent to the website." + }, + "appDescription": { + "message": "Web Monetization Extension", + "description": "Web Monetization is a browser API that allows the creation of a payment stream from the user agent to the website." + }, + "btnTooltip": { + "message": "Web Monetization", + "description": "..." + } } diff --git a/packages/extension/src/background/config.ts b/packages/extension/src/background/config.ts index 2dbd68af..5198fb72 100644 --- a/packages/extension/src/background/config.ts +++ b/packages/extension/src/background/config.ts @@ -1,5 +1,5 @@ -declare const CONFIG_SIGNATURES_URL: string -declare const CONFIG_WM_WALLET_ADDRESS: string +declare const CONFIG_SIGNATURES_URL: string; +declare const CONFIG_WM_WALLET_ADDRESS: string; -export const SIGNATURES_URL = CONFIG_SIGNATURES_URL -export const WM_WALLET_ADDRESS = CONFIG_WM_WALLET_ADDRESS +export const SIGNATURES_URL = CONFIG_SIGNATURES_URL; +export const WM_WALLET_ADDRESS = CONFIG_WM_WALLET_ADDRESS; diff --git a/packages/extension/src/background/grant/confirmPayment.ts b/packages/extension/src/background/grant/confirmPayment.ts index b7374727..5d538082 100644 --- a/packages/extension/src/background/grant/confirmPayment.ts +++ b/packages/extension/src/background/grant/confirmPayment.ts @@ -1,12 +1,12 @@ -import { tabs } from 'webextension-polyfill' +import { tabs } from 'webextension-polyfill'; const getCurrentActiveTabId = async () => { - const activeTabs = await tabs.query({ active: true, currentWindow: true }) - return activeTabs[0].id -} + const activeTabs = await tabs.query({ active: true, currentWindow: true }); + return activeTabs[0].id; +}; export const confirmPayment = async (url: string) => { - const currentTabId = await getCurrentActiveTabId() + const currentTabId = await getCurrentActiveTabId(); return await new Promise(resolve => { if (url) { @@ -14,20 +14,20 @@ export const confirmPayment = async (url: string) => { if (tab.id) { tabs.onUpdated.addListener((tabId, changeInfo) => { try { - const tabUrl = new URL(changeInfo.url || '') - const interactRef = tabUrl.searchParams.get('interact_ref') + const tabUrl = new URL(changeInfo.url || ''); + const interactRef = tabUrl.searchParams.get('interact_ref'); if (tabId === tab.id && interactRef) { - tabs.update(currentTabId, { active: true }) - tabs.remove(tab.id) - resolve(interactRef) + tabs.update(currentTabId, { active: true }); + tabs.remove(tab.id); + resolve(interactRef); } } catch (e) { - throw new Error('Invalid interact ref url.') + throw new Error('Invalid interact ref url.'); } - }) + }); } - }) + }); } - }) -} + }); +}; diff --git a/packages/extension/src/background/grant/createQuote.ts b/packages/extension/src/background/grant/createQuote.ts index 5262bdd4..731bd46a 100644 --- a/packages/extension/src/background/grant/createQuote.ts +++ b/packages/extension/src/background/grant/createQuote.ts @@ -1,15 +1,15 @@ -import { AxiosInstance } from 'axios' +import { AxiosInstance } from 'axios'; -import { getHeaders } from './getHeaders' +import { getHeaders } from './getHeaders'; type TCreateQuote = (_params: { - receiver: string - walletAddress: any - sendingUrl: string - token: string - amount: string - instance: AxiosInstance -}) => Promise + receiver: string; + walletAddress: any; + sendingUrl: string; + token: string; + amount: string; + instance: AxiosInstance; +}) => Promise; export const createQuote: TCreateQuote = async ({ receiver, @@ -28,17 +28,17 @@ export const createQuote: TCreateQuote = async ({ assetCode: walletAddress.assetCode, // 'USD' assetScale: walletAddress.assetScale, // 9 }, - } + }; const quote = await instance.post( new URL(sendingUrl).origin + '/quotes', payload, getHeaders(token), - ) + ); if (!quote.data.id) { - throw new Error('No quote url id') + throw new Error('No quote url id'); } - return quote.data.id -} + return quote.data.id; +}; diff --git a/packages/extension/src/background/grant/getContinuationRequest.ts b/packages/extension/src/background/grant/getContinuationRequest.ts index 6947f267..f3c23cdd 100644 --- a/packages/extension/src/background/grant/getContinuationRequest.ts +++ b/packages/extension/src/background/grant/getContinuationRequest.ts @@ -1,13 +1,13 @@ -import { AxiosInstance } from 'axios' +import { AxiosInstance } from 'axios'; -import { getHeaders } from './getHeaders' +import { getHeaders } from './getHeaders'; type TGetContinuationRequest = (_params: { - url: string - interactRef: any - token: string - instance: AxiosInstance -}) => Promise + url: string; + interactRef: any; + token: string; + instance: AxiosInstance; +}) => Promise; export const getContinuationRequest: TGetContinuationRequest = async ({ url, @@ -21,14 +21,14 @@ export const getContinuationRequest: TGetContinuationRequest = async ({ interact_ref: interactRef, }, getHeaders(token), - ) + ); if (!continuationRequest.data.access_token.value) { - throw new Error('No continuation request') + throw new Error('No continuation request'); } return { manageUrl: continuationRequest.data.access_token.manage, continuationRequestToken: continuationRequest.data.access_token.value, - } -} + }; +}; diff --git a/packages/extension/src/background/grant/getHeaders.ts b/packages/extension/src/background/grant/getHeaders.ts index 803f7b03..0b71ec99 100644 --- a/packages/extension/src/background/grant/getHeaders.ts +++ b/packages/extension/src/background/grant/getHeaders.ts @@ -2,4 +2,4 @@ export const getHeaders = (gnapToken: string) => ({ headers: { Authorization: `GNAP ${gnapToken}`, }, -}) +}); diff --git a/packages/extension/src/background/grant/getIcomingPaymentGrant.ts b/packages/extension/src/background/grant/getIcomingPaymentGrant.ts index df0e2f09..2dd22e73 100644 --- a/packages/extension/src/background/grant/getIcomingPaymentGrant.ts +++ b/packages/extension/src/background/grant/getIcomingPaymentGrant.ts @@ -1,11 +1,11 @@ -import { AxiosInstance } from 'axios' +import { AxiosInstance } from 'axios'; type TGetIncomingPaymentGrant = (_params: { - client: string - identifier: string - wallet: Record - instance: AxiosInstance -}) => Promise + client: string; + identifier: string; + wallet: Record; + instance: AxiosInstance; +}) => Promise; export const getIncomingPaymentGrant: TGetIncomingPaymentGrant = async ({ client, @@ -24,13 +24,13 @@ export const getIncomingPaymentGrant: TGetIncomingPaymentGrant = async ({ ], }, client, // WM_PAYMENT_POINTER_URL - } + }; - const response = await instance.post(wallet.authServer + '/', payload) + const response = await instance.post(wallet.authServer + '/', payload); if (!response.data.access_token.value) { - throw new Error('No client auth') + throw new Error('No client auth'); } - return response.data.access_token.value -} + return response.data.access_token.value; +}; diff --git a/packages/extension/src/background/grant/getIncomingPaymentUrlId.ts b/packages/extension/src/background/grant/getIncomingPaymentUrlId.ts index 18fbbe9c..a78627db 100644 --- a/packages/extension/src/background/grant/getIncomingPaymentUrlId.ts +++ b/packages/extension/src/background/grant/getIncomingPaymentUrlId.ts @@ -1,12 +1,12 @@ -import { AxiosInstance } from 'axios' +import { AxiosInstance } from 'axios'; -import { getHeaders } from './getHeaders' +import { getHeaders } from './getHeaders'; type TGetIncomingPaymentUrlId = (_params: { - walletAddress: string - token: string - instance: AxiosInstance -}) => Promise + walletAddress: string; + token: string; + instance: AxiosInstance; +}) => Promise; export const getIncomingPaymentUrlId: TGetIncomingPaymentUrlId = async ({ walletAddress, @@ -20,11 +20,11 @@ export const getIncomingPaymentUrlId: TGetIncomingPaymentUrlId = async ({ expiresAt: new Date(Date.now() + 6000 * 60 * 10).toISOString(), }, getHeaders(token), - ) + ); if (!incomingPayment?.data?.id) { - throw new Error('No incoming payment id') + throw new Error('No incoming payment id'); } - return incomingPayment.data.id -} + return incomingPayment.data.id; +}; diff --git a/packages/extension/src/background/grant/getOutgoingPaymentGrant.ts b/packages/extension/src/background/grant/getOutgoingPaymentGrant.ts index a9b258c2..7e68f137 100644 --- a/packages/extension/src/background/grant/getOutgoingPaymentGrant.ts +++ b/packages/extension/src/background/grant/getOutgoingPaymentGrant.ts @@ -1,12 +1,12 @@ -import { AxiosInstance } from 'axios' +import { AxiosInstance } from 'axios'; type TGetOutgoingPaymentGrant = (_params: { - client: string - identifier: string - wallet: Record - amount: string | number - instance: AxiosInstance -}) => Promise + client: string; + identifier: string; + wallet: Record; + amount: string | number; + instance: AxiosInstance; +}) => Promise; export const getOutgoingPaymentGrant: TGetOutgoingPaymentGrant = async ({ client, @@ -44,16 +44,16 @@ export const getOutgoingPaymentGrant: TGetOutgoingPaymentGrant = async ({ nonce: new Date().getTime().toString(), }, }, - } + }; - const outgoingPaymentGrant = await instance.post(wallet.authServer + '/', payload) + const outgoingPaymentGrant = await instance.post(wallet.authServer + '/', payload); if (!outgoingPaymentGrant.data.interact.redirect) { - throw new Error('No redirect') + throw new Error('No redirect'); } return { outgoingPaymentGrantToken: outgoingPaymentGrant.data.continue.access_token.value, outgoingPaymentGrantData: outgoingPaymentGrant.data, - } -} + }; +}; diff --git a/packages/extension/src/background/grant/getQuoteGrant.ts b/packages/extension/src/background/grant/getQuoteGrant.ts index 1c449e35..aa62b7f0 100644 --- a/packages/extension/src/background/grant/getQuoteGrant.ts +++ b/packages/extension/src/background/grant/getQuoteGrant.ts @@ -1,11 +1,11 @@ -import { AxiosInstance } from 'axios' +import { AxiosInstance } from 'axios'; type TGetQuoteGrant = (_params: { - client: string - identifier: string - wallet: Record - instance: AxiosInstance -}) => Promise + client: string; + identifier: string; + wallet: Record; + instance: AxiosInstance; +}) => Promise; export const getQuoteGrant: TGetQuoteGrant = async ({ client, identifier, wallet, instance }) => { const quotePayload = { @@ -19,12 +19,12 @@ export const getQuoteGrant: TGetQuoteGrant = async ({ client, identifier, wallet ], }, client, // WM_PAYMENT_POINTER_URL - } - const quoteGrant = await instance.post(wallet.authServer + '/', quotePayload) + }; + const quoteGrant = await instance.post(wallet.authServer + '/', quotePayload); if (!quoteGrant.data?.access_token?.value) { - throw new Error('No quote grant') + throw new Error('No quote grant'); } - return quoteGrant.data.access_token.value -} + return quoteGrant.data.access_token.value; +}; diff --git a/packages/extension/src/background/grant/index.ts b/packages/extension/src/background/grant/index.ts index 7364d9b5..0947b7a5 100644 --- a/packages/extension/src/background/grant/index.ts +++ b/packages/extension/src/background/grant/index.ts @@ -1,12 +1,12 @@ -import { confirmPayment } from './confirmPayment' -import { createQuote } from './createQuote' -import { getContinuationRequest } from './getContinuationRequest' -import { getHeaders } from './getHeaders' -import { getIncomingPaymentGrant } from './getIcomingPaymentGrant' -import { getIncomingPaymentUrlId } from './getIncomingPaymentUrlId' -import { getOutgoingPaymentGrant } from './getOutgoingPaymentGrant' -import { getQuoteGrant } from './getQuoteGrant' -import { rotateToken } from './rotateToken' +import { confirmPayment } from './confirmPayment'; +import { createQuote } from './createQuote'; +import { getContinuationRequest } from './getContinuationRequest'; +import { getHeaders } from './getHeaders'; +import { getIncomingPaymentGrant } from './getIcomingPaymentGrant'; +import { getIncomingPaymentUrlId } from './getIncomingPaymentUrlId'; +import { getOutgoingPaymentGrant } from './getOutgoingPaymentGrant'; +import { getQuoteGrant } from './getQuoteGrant'; +import { rotateToken } from './rotateToken'; export { confirmPayment, @@ -18,4 +18,4 @@ export { getOutgoingPaymentGrant, getQuoteGrant, rotateToken, -} +}; diff --git a/packages/extension/src/background/grant/rotateToken.ts b/packages/extension/src/background/grant/rotateToken.ts index b4d8087f..77927501 100644 --- a/packages/extension/src/background/grant/rotateToken.ts +++ b/packages/extension/src/background/grant/rotateToken.ts @@ -1,26 +1,26 @@ -import { AxiosInstance } from 'axios' +import { AxiosInstance } from 'axios'; -import { getHeaders } from '@/background/grant/getHeaders' +import { getHeaders } from '@/background/grant/getHeaders'; type TRotateToken = (_params: { - url: string - token: string - instance: AxiosInstance -}) => Promise + url: string; + token: string; + instance: AxiosInstance; +}) => Promise; export const rotateToken: TRotateToken = async ({ url, token, instance }) => { const response = await instance.post( url, // this.manageUrl undefined, getHeaders(token), // this.continuationRequestToken - ) + ); if (!response.data.access_token.value) { - throw new Error('No continuation request') + throw new Error('No continuation request'); } return { manageUrl: response.data.access_token.manage, continuationRequestToken: response.data.access_token.value, - } -} + }; +}; diff --git a/packages/extension/src/background/grantFlow.ts b/packages/extension/src/background/grantFlow.ts index 18fac5fb..0ad90f39 100644 --- a/packages/extension/src/background/grantFlow.ts +++ b/packages/extension/src/background/grantFlow.ts @@ -1,6 +1,6 @@ -import { tabs } from 'webextension-polyfill' +import { tabs } from 'webextension-polyfill'; -import { WM_WALLET_ADDRESS } from '@/background/config' +import { WM_WALLET_ADDRESS } from '@/background/config'; import { createQuote, getHeaders, @@ -8,67 +8,67 @@ import { getIncomingPaymentUrlId, getOutgoingPaymentGrant, getQuoteGrant, -} from '@/background/grant' -import { confirmPayment } from '@/background/grant/confirmPayment' -import { getContinuationRequest } from '@/background/grant/getContinuationRequest' -import { getAxiosInstance } from '@/background/requestConfig' +} from '@/background/grant'; +import { confirmPayment } from '@/background/grant/confirmPayment'; +import { getContinuationRequest } from '@/background/grant/getContinuationRequest'; +import { getAxiosInstance } from '@/background/requestConfig'; export class PaymentFlowService { - axiosInstance = getAxiosInstance() + axiosInstance = getAxiosInstance(); - sendingPaymentPointerUrl: string - receivingPaymentPointerUrl: string + sendingPaymentPointerUrl: string; + receivingPaymentPointerUrl: string; - incomingPaymentUrlId: string - quoteUrlId: string - outgoingPaymentGrantData: any + incomingPaymentUrlId: string; + quoteUrlId: string; + outgoingPaymentGrantData: any; - clientAuthToken: string - quoteGrantToken: string - outgoingPaymentGrantToken: string - continuationRequestToken: string - interactRef: string + clientAuthToken: string; + quoteGrantToken: string; + outgoingPaymentGrantToken: string; + continuationRequestToken: string; + interactRef: string; - manageUrl: string + manageUrl: string; - amount: string | number + amount: string | number; - sendingWalletAddress: any - receivingWalletAddress: any + sendingWalletAddress: any; + receivingWalletAddress: any; constructor( sendingPaymentPointerUrl: string, receivingPaymentPointerUrl: string, amount: string, ) { - this.sendingPaymentPointerUrl = sendingPaymentPointerUrl - this.receivingPaymentPointerUrl = receivingPaymentPointerUrl - this.amount = amount + this.sendingPaymentPointerUrl = sendingPaymentPointerUrl; + this.receivingPaymentPointerUrl = receivingPaymentPointerUrl; + this.amount = amount; } async initPaymentFlow() { - this.sendingWalletAddress = await this.getWalletAddress(this.sendingPaymentPointerUrl) - this.receivingWalletAddress = await this.getWalletAddress(this.receivingPaymentPointerUrl) + this.sendingWalletAddress = await this.getWalletAddress(this.sendingPaymentPointerUrl); + this.receivingWalletAddress = await this.getWalletAddress(this.receivingPaymentPointerUrl); this.clientAuthToken = await getIncomingPaymentGrant({ client: WM_WALLET_ADDRESS, identifier: this.receivingPaymentPointerUrl, wallet: this.receivingWalletAddress, instance: this.axiosInstance, - }) + }); this.incomingPaymentUrlId = await getIncomingPaymentUrlId({ walletAddress: this.receivingPaymentPointerUrl, token: this.clientAuthToken, instance: this.axiosInstance, - }) + }); this.quoteGrantToken = await getQuoteGrant({ client: WM_WALLET_ADDRESS, identifier: this.sendingPaymentPointerUrl, wallet: this.sendingWalletAddress, instance: this.axiosInstance, - }) + }); const outgoingData = await getOutgoingPaymentGrant({ client: WM_WALLET_ADDRESS, @@ -76,25 +76,25 @@ export class PaymentFlowService { wallet: this.sendingWalletAddress, amount: this.amount, instance: this.axiosInstance, - }) + }); - this.outgoingPaymentGrantToken = outgoingData.outgoingPaymentGrantToken - this.outgoingPaymentGrantData = outgoingData.outgoingPaymentGrantData + this.outgoingPaymentGrantToken = outgoingData.outgoingPaymentGrantToken; + this.outgoingPaymentGrantData = outgoingData.outgoingPaymentGrantData; - this.interactRef = await confirmPayment(this.outgoingPaymentGrantData.interact.redirect) + this.interactRef = await confirmPayment(this.outgoingPaymentGrantData.interact.redirect); const continuationRequest = await getContinuationRequest({ url: this.outgoingPaymentGrantData.continue.uri, interactRef: this.interactRef, token: this.outgoingPaymentGrantToken, instance: this.axiosInstance, - }) + }); - this.manageUrl = continuationRequest.manageUrl - this.continuationRequestToken = continuationRequest.continuationRequestToken + this.manageUrl = continuationRequest.manageUrl; + this.continuationRequestToken = continuationRequest.continuationRequestToken; - const currentTabId = await this.getCurrentActiveTabId() - await tabs.sendMessage(currentTabId ?? 0, { type: 'START_PAYMENTS' }) + const currentTabId = await this.getCurrentActiveTabId(); + await tabs.sendMessage(currentTabId ?? 0, { type: 'START_PAYMENTS' }); } async getWalletAddress(paymentPointerUrl: string) { @@ -102,37 +102,37 @@ export class PaymentFlowService { headers: { Accept: 'application/json', }, - }) + }); if (!response?.data?.id) { - throw new Error('No client auth') + throw new Error('No client auth'); } - return response.data + return response.data; } async runPayment() { const payload = { walletAddress: this.sendingPaymentPointerUrl, quoteId: this.quoteUrlId, - } + }; const response = await this.axiosInstance.post( new URL(this.sendingPaymentPointerUrl).origin + '/outgoing-payments', payload, getHeaders(this.continuationRequestToken), - ) + ); const { receiveAmount, receiver: incomingPayment, walletAddress: paymentPointer, - } = response.data - const currentTabId = await this.getCurrentActiveTabId() + } = response.data; + const currentTabId = await this.getCurrentActiveTabId(); await tabs.sendMessage(currentTabId ?? 0, { type: 'PAYMENT_SUCCESS', data: { receiveAmount, incomingPayment, paymentPointer }, - }) + }); // console.log('outgoingPayment', outgoingPayment) } @@ -144,13 +144,13 @@ export class PaymentFlowService { token: this.quoteGrantToken, amount: '1000000', instance: this.axiosInstance, - }) + }); - await this.runPayment() + await this.runPayment(); } async getCurrentActiveTabId() { - const activeTabs = await tabs.query({ active: true, currentWindow: true }) - return activeTabs[0].id + const activeTabs = await tabs.query({ active: true, currentWindow: true }); + return activeTabs[0].id; } } diff --git a/packages/extension/src/background/index.ts b/packages/extension/src/background/index.ts index 7c65b53a..ebf9eac1 100755 --- a/packages/extension/src/background/index.ts +++ b/packages/extension/src/background/index.ts @@ -1,11 +1,11 @@ -import { action, Runtime, runtime, Tabs, tabs } from 'webextension-polyfill' +import { action, Runtime, runtime, Tabs, tabs } from 'webextension-polyfill'; -import { PaymentFlowService } from '@/background/grantFlow' +import { PaymentFlowService } from '@/background/grantFlow'; -const iconActive34 = runtime.getURL('assets/icons/icon-active-34.png') -const iconActive128 = runtime.getURL('assets/icons/icon-active-128.png') -const iconInactive34 = runtime.getURL('assets/icons/icon-inactive-34.png') -const iconInactive128 = runtime.getURL('assets/icons/icon-inactive-128.png') +const iconActive34 = runtime.getURL('assets/icons/icon-active-34.png'); +const iconActive128 = runtime.getURL('assets/icons/icon-active-128.png'); +const iconInactive34 = runtime.getURL('assets/icons/icon-inactive-34.png'); +const iconInactive128 = runtime.getURL('assets/icons/icon-inactive-128.png'); // const SENDING_PAYMENT_POINTER_URL = 'https://ilp.rafiki.money/wmuser' // cel din extensie al userului // const RECEIVING_PAYMENT_POINTER_URL = 'https://ilp.rafiki.money/web-page' // cel din dom @@ -15,13 +15,13 @@ const iconInactive128 = runtime.getURL('assets/icons/icon-inactive-128.png') * @type {class} */ class Background { - _port: number - grantFlow: PaymentFlowService | null = null - spentAmount: number = 0 - paymentStarted = false + _port: number; + grantFlow: PaymentFlowService | null = null; + spentAmount: number = 0; + paymentStarted = false; constructor() { - this.init() + this.init(); } /** @@ -30,23 +30,23 @@ class Background { * @returns {void} */ init = async () => { - console.log('[===== Loaded Background Scripts =====]') + console.log('[===== Loaded Background Scripts =====]'); //When extension installed - runtime.onInstalled.addListener(this.onInstalled) + runtime.onInstalled.addListener(this.onInstalled); //Add message listener in Browser. - runtime.onMessage.addListener(this.onMessage) + runtime.onMessage.addListener(this.onMessage); //Add Update listener for tab - tabs.onUpdated.addListener(this.onUpdatedTab) + tabs.onUpdated.addListener(this.onUpdatedTab); //Add New tab create listener - tabs.onCreated.addListener(this.onCreatedTab) + tabs.onCreated.addListener(this.onCreatedTab); //Add tab change listener - tabs.onActivated.addListener(this.handleTabChange) - } + tabs.onActivated.addListener(this.handleTabChange); + }; //TODO: Listeners @@ -54,8 +54,8 @@ class Background { * Extension Installed */ onInstalled = () => { - console.log('[===== Installed Extension!] =====') - } + console.log('[===== Installed Extension!] ====='); + }; /** * Message Handler Function @@ -66,13 +66,13 @@ class Background { */ onMessage = async (message: EXTMessage, sender: Runtime.MessageSender) => { try { - console.log('[===== Received message =====]', message, sender) + console.log('[===== Received message =====]', message, sender); switch (message.type) { case 'IS_MONETIZATION_READY': { if (message?.data) { - this.updateIcon(message.data.monetization) + this.updateIcon(message.data.monetization); } - break + break; } case 'SET_INCOMING_POINTER': { @@ -80,66 +80,66 @@ class Background { incomingPayment: receivingPaymentPointerUrl, paymentPointer: sendingPaymentPointerUrl, amount, - } = message.data + } = message.data; if (this.grantFlow?.sendingPaymentPointerUrl === sendingPaymentPointerUrl) { if (!this.paymentStarted) { - this.paymentStarted = true - const currentTabId = await this.grantFlow?.getCurrentActiveTabId() - await tabs.sendMessage(currentTabId ?? 0, { type: 'START_PAYMENTS' }) + this.paymentStarted = true; + const currentTabId = await this.grantFlow?.getCurrentActiveTabId(); + await tabs.sendMessage(currentTabId ?? 0, { type: 'START_PAYMENTS' }); } } else { this.grantFlow = new PaymentFlowService( sendingPaymentPointerUrl, receivingPaymentPointerUrl, amount, - ) + ); - this.grantFlow.initPaymentFlow() + this.grantFlow.initPaymentFlow(); } - break + break; } case 'GET_SENDING_PAYMENT_POINTER': { if (this.grantFlow) { - const { sendingPaymentPointerUrl, amount } = this.grantFlow + const { sendingPaymentPointerUrl, amount } = this.grantFlow; return { type: 'SUCCESS', data: { sendingPaymentPointerUrl, amount, started: this.paymentStarted }, - } + }; } return { type: 'ERROR', data: { sendingPaymentPointerUrl: '' }, - } + }; } case 'RUN_PAYMENT': { if (this.grantFlow) { - this.grantFlow.sendPayment() + this.grantFlow.sendPayment(); this.spentAmount = Number( parseFloat(String(this.spentAmount + 1000000 / 10 ** 9)).toFixed(3), - ) - this.sendSpendAmount() - this.paymentStarted = true + ); + this.sendSpendAmount(); + this.paymentStarted = true; } - break + break; } case 'PAUSE_PAYMENTS': { - this.paymentStarted = false - break + this.paymentStarted = false; + break; } } - return true // result to reply + return true; // result to reply } catch (error) { - console.log('[===== Error in MessageListener =====]', error) - return error + console.log('[===== Error in MessageListener =====]', error); + return error; } - } + }; /** * Message from Long Live Connection @@ -147,22 +147,22 @@ class Background { * @param msg */ onMessageFromExtension = (msg: EXTMessage) => { - console.log('[===== Message from Long Live Connection =====]', msg) - } + console.log('[===== Message from Long Live Connection =====]', msg); + }; /** * * @param tab */ onCreatedTab = (tab: Tabs.Tab) => { - console.log('[===== New Tab Created =====]', tab) - } + console.log('[===== New Tab Created =====]', tab); + }; sendSpendAmount() { runtime.sendMessage({ type: 'SPENT_AMOUNT', data: { spentAmount: this.spentAmount }, - }) + }); } /** @@ -174,12 +174,12 @@ class Background { */ onUpdatedTab = async (tabId: number, changeInfo: Tabs.OnUpdatedChangeInfoType, tab: Tabs.Tab) => { if (tab.status === 'complete' && tab.url?.match(/^http/)) { - const response = await this.sendMessage(tab, { type: 'IS_MONETIZATION_READY' }) + const response = await this.sendMessage(tab, { type: 'IS_MONETIZATION_READY' }); if (response.data) { - await this.updateIcon(response.data.monetization) + await this.updateIcon(response.data.monetization); } } - } + }; /** * Get url from tabId @@ -187,13 +187,13 @@ class Background { */ getURLFromTab = async (tabId: number) => { try { - const tab = await tabs.get(tabId) - return tab.url || '' + const tab = await tabs.get(tabId); + return tab.url || ''; } catch (error) { - console.log(`[===== Could not get Tab Info$(tabId) in getURLFromTab =====]`, error) - throw '' + console.log(`[===== Could not get Tab Info$(tabId) in getURLFromTab =====]`, error); + throw ''; } - } + }; /** * Open new tab by url @@ -201,13 +201,13 @@ class Background { */ openNewTab = async (url: string) => { try { - const tab = await tabs.create({ url }) - return tab + const tab = await tabs.create({ url }); + return tab; } catch (error) { - console.log(`[===== Error in openNewTab =====]`, error) - return null + console.log(`[===== Error in openNewTab =====]`, error); + return null; } - } + }; /** * Close specific tab @@ -216,49 +216,49 @@ class Background { */ closeTab = async (tab: Tabs.Tab) => { try { - await tabs.remove(tab.id ?? 0) + await tabs.remove(tab.id ?? 0); } catch (error) { - console.log(`[===== Error in closeTab =====]`, error) + console.log(`[===== Error in closeTab =====]`, error); } - } + }; /** * send message */ sendMessage = async (tab: Tabs.Tab, msg: EXTMessage) => { try { - const res = await tabs.sendMessage(tab.id ?? 0, msg) - return res + const res = await tabs.sendMessage(tab.id ?? 0, msg); + return res; } catch (error) { - console.log(`[===== Error in sendMessage =====]`, error) - return null + console.log(`[===== Error in sendMessage =====]`, error); + return null; } - } + }; updateIcon = async (active: boolean) => { const iconData = { '34': active ? iconActive34 : iconInactive34, '128': active ? iconActive128 : iconInactive128, - } + }; if (action) { - await action.setIcon({ path: iconData }) + await action.setIcon({ path: iconData }); } else if (chrome.browserAction) { - chrome.browserAction.setIcon({ path: iconData }) + chrome.browserAction.setIcon({ path: iconData }); } - } + }; handleTabChange = async (activeInfo: chrome.tabs.TabActiveInfo) => { - const tabId = activeInfo.tabId + const tabId = activeInfo.tabId; - const tab = await tabs.get(tabId) + const tab = await tabs.get(tabId); if (tab && tab.url?.includes('https') && tab.status === 'complete') { - const response = await this.sendMessage(tab, { type: 'IS_MONETIZATION_READY' }) + const response = await this.sendMessage(tab, { type: 'IS_MONETIZATION_READY' }); if (response?.data) { - this.updateIcon(response.data.monetization) + this.updateIcon(response.data.monetization); } } - } + }; } -export const background = new Background() +export const background = new Background(); diff --git a/packages/extension/src/background/requestConfig.ts b/packages/extension/src/background/requestConfig.ts index 44953061..3dd95a13 100644 --- a/packages/extension/src/background/requestConfig.ts +++ b/packages/extension/src/background/requestConfig.ts @@ -1,6 +1,6 @@ -import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios' +import axios, { AxiosInstance, InternalAxiosRequestConfig } from 'axios'; -import { SIGNATURES_URL } from '@/background/config' +import { SIGNATURES_URL } from '@/background/config'; export const getAxiosInstance = (timeout = 10000): AxiosInstance => { const axiosInstance = axios.create({ @@ -11,12 +11,12 @@ export const getAxiosInstance = (timeout = 10000): AxiosInstance => { }, }, timeout, - }) + }); axiosInstance.interceptors.request.use( async (config: InternalAxiosRequestConfig) => { if (!config.method || !config.url) { - throw new Error('Cannot intercept request: url or method missing') + throw new Error('Cannot intercept request: url or method missing'); } const payload = { @@ -27,17 +27,17 @@ export const getAxiosInstance = (timeout = 10000): AxiosInstance => { method: config.method.toUpperCase(), url: config.url, body: JSON.stringify(config.data), - } + }; const contentAndSigHeaders = await axios.post(SIGNATURES_URL, payload, { headers: { 'Content-Type': 'application/json' }, - }) + }); - config.headers['Signature'] = contentAndSigHeaders.data['Signature'] - config.headers['Signature-Input'] = contentAndSigHeaders.data['Signature-Input'] - config.headers['Content-Digest'] = contentAndSigHeaders.data['Content-Digest'] + config.headers['Signature'] = contentAndSigHeaders.data['Signature']; + config.headers['Signature-Input'] = contentAndSigHeaders.data['Signature-Input']; + config.headers['Content-Digest'] = contentAndSigHeaders.data['Content-Digest']; - return config + return config; }, undefined, { @@ -45,7 +45,7 @@ export const getAxiosInstance = (timeout = 10000): AxiosInstance => { config.method?.toLowerCase() === 'post' || !!(config.headers && config.headers['Authorization']), }, - ) + ); - return axiosInstance -} + return axiosInstance; +}; diff --git a/packages/extension/src/components/Popup/PopupFooter/PopupFooter.tsx b/packages/extension/src/components/Popup/PopupFooter/PopupFooter.tsx index da5e2620..c33db202 100644 --- a/packages/extension/src/components/Popup/PopupFooter/PopupFooter.tsx +++ b/packages/extension/src/components/Popup/PopupFooter/PopupFooter.tsx @@ -1,9 +1,9 @@ -import './PopupFooter.scss' +import './PopupFooter.scss'; -import React from 'react' +import React from 'react'; interface IProps { - isMonetizationReady: boolean + isMonetizationReady: boolean; } const PopupFooter: React.FC = ({ isMonetizationReady }) => ( @@ -14,6 +14,6 @@ const PopupFooter: React.FC = ({ isMonetizationReady }) => ( This site isn't Web Monetization ready )} -) +); -export default PopupFooter +export default PopupFooter; diff --git a/packages/extension/src/components/Popup/PopupFooter/index.ts b/packages/extension/src/components/Popup/PopupFooter/index.ts index 90aeac0c..3f22404f 100644 --- a/packages/extension/src/components/Popup/PopupFooter/index.ts +++ b/packages/extension/src/components/Popup/PopupFooter/index.ts @@ -1 +1 @@ -export { default } from './PopupFooter' +export { default } from './PopupFooter'; diff --git a/packages/extension/src/components/Popup/PopupHeader/PopupHeader.tsx b/packages/extension/src/components/Popup/PopupHeader/PopupHeader.tsx index 52b3ac45..85781bd5 100644 --- a/packages/extension/src/components/Popup/PopupHeader/PopupHeader.tsx +++ b/packages/extension/src/components/Popup/PopupHeader/PopupHeader.tsx @@ -1,9 +1,9 @@ -import React from 'react' -import { runtime } from 'webextension-polyfill' +import React from 'react'; +import { runtime } from 'webextension-polyfill'; -const Logo = runtime.getURL('assets/images/logo.svg') -const Close = runtime.getURL('assets/images/close.svg') -import './PopupHeader.scss' +const Logo = runtime.getURL('assets/images/logo.svg'); +const Close = runtime.getURL('assets/images/close.svg'); +import './PopupHeader.scss'; const PopupHeader: React.FC = () => { return ( @@ -14,7 +14,7 @@ const PopupHeader: React.FC = () => { Close - ) -} + ); +}; -export default PopupHeader +export default PopupHeader; diff --git a/packages/extension/src/components/Popup/PopupHeader/index.ts b/packages/extension/src/components/Popup/PopupHeader/index.ts index 9a403d0e..e2e9051f 100644 --- a/packages/extension/src/components/Popup/PopupHeader/index.ts +++ b/packages/extension/src/components/Popup/PopupHeader/index.ts @@ -1 +1 @@ -export { default } from './PopupHeader' +export { default } from './PopupHeader'; diff --git a/packages/extension/src/components/__tests__/button.test.tsx b/packages/extension/src/components/__tests__/button.test.tsx index a9a3b286..a1809236 100644 --- a/packages/extension/src/components/__tests__/button.test.tsx +++ b/packages/extension/src/components/__tests__/button.test.tsx @@ -1,60 +1,60 @@ -import { render } from '@testing-library/react' -import React from 'react' +import { render } from '@testing-library/react'; +import React from 'react'; -import { Button } from '@/components/button' +import { Button } from '@/components/button'; describe('Button', () => { it('should render a button with the `aria-label` attribute', () => { - const { queryByRole } = render() + const { queryByRole } = render(); - expect(queryByRole('button')).toBeInTheDocument() - expect(queryByRole('button')).toHaveAttribute('aria-label', 'test button') - }) + expect(queryByRole('button')).toBeInTheDocument(); + expect(queryByRole('button')).toHaveAttribute('aria-label', 'test button'); + }); it('should default to `type="button"`', () => { - const { queryByRole } = render() + const { queryByRole } = render(); - expect(queryByRole('button')).toBeInTheDocument() - expect(queryByRole('button')).toHaveAttribute('type', 'button') - }) + expect(queryByRole('button')).toBeInTheDocument(); + expect(queryByRole('button')).toHaveAttribute('type', 'button'); + }); it('should not have the `disabled` attribute and `aria-disabled="false"` if `loading` is false', () => { - const { queryByRole } = render() + const { queryByRole } = render(); - expect(queryByRole('button')).toBeInTheDocument() - expect(queryByRole('button')).not.toHaveAttribute('disabled') - expect(queryByRole('button')).toHaveAttribute('aria-disabled', 'false') - expect(queryByRole('button')).not.toBeDisabled() - }) + expect(queryByRole('button')).toBeInTheDocument(); + expect(queryByRole('button')).not.toHaveAttribute('disabled'); + expect(queryByRole('button')).toHaveAttribute('aria-disabled', 'false'); + expect(queryByRole('button')).not.toBeDisabled(); + }); it('should have the `disabled` and `aria-disabled="true"` attributes if `loading` is true', () => { const { queryByRole } = render( , - ) + ); - expect(queryByRole('button')).toBeInTheDocument() - expect(queryByRole('button')).toHaveAttribute('disabled') - expect(queryByRole('button')).toHaveAttribute('aria-disabled', 'true') - expect(queryByRole('button')).toBeDisabled() - }) + expect(queryByRole('button')).toBeInTheDocument(); + expect(queryByRole('button')).toHaveAttribute('disabled'); + expect(queryByRole('button')).toHaveAttribute('aria-disabled', 'true'); + expect(queryByRole('button')).toBeDisabled(); + }); it('should have the `bg-button-base` class by default', () => { - const { queryByRole } = render() + const { queryByRole } = render(); - expect(queryByRole('button')).toBeInTheDocument() - expect(queryByRole('button')).toHaveClass('bg-button-base') - }) + expect(queryByRole('button')).toBeInTheDocument(); + expect(queryByRole('button')).toHaveClass('bg-button-base'); + }); it('should have the `bg-error` class when the `destructive` variant is passed', () => { const { queryByRole } = render( , - ) + ); - expect(queryByRole('button')).toBeInTheDocument() - expect(queryByRole('button')).toHaveClass('bg-error') - }) -}) + expect(queryByRole('button')).toBeInTheDocument(); + expect(queryByRole('button')).toHaveClass('bg-error'); + }); +}); diff --git a/packages/extension/src/components/__tests__/input.test.tsx b/packages/extension/src/components/__tests__/input.test.tsx index 6f66e7a4..7541daef 100644 --- a/packages/extension/src/components/__tests__/input.test.tsx +++ b/packages/extension/src/components/__tests__/input.test.tsx @@ -1,55 +1,55 @@ -import { render } from '@testing-library/react' -import React from 'react' +import { render } from '@testing-library/react'; +import React from 'react'; -import { Input } from '@/components/input' +import { Input } from '@/components/input'; describe('Input', () => { it('should default to `type="text"`', () => { - const { queryByLabelText } = render() + const { queryByLabelText } = render(); - expect(queryByLabelText('test input')).toBeInTheDocument() - expect(queryByLabelText('test input')).toHaveAttribute('type', 'text') - }) + expect(queryByLabelText('test input')).toBeInTheDocument(); + expect(queryByLabelText('test input')).toHaveAttribute('type', 'text'); + }); it('should not have the `disabled` attribute and `aria-disabled="false"` if `loading` is false', () => { - const { queryByLabelText } = render() + const { queryByLabelText } = render(); - expect(queryByLabelText('test input')).toBeInTheDocument() - expect(queryByLabelText('test input')).not.toHaveAttribute('disabled') - expect(queryByLabelText('test input')).toHaveAttribute('aria-disabled', 'false') - expect(queryByLabelText('test input')).not.toBeDisabled() - }) + expect(queryByLabelText('test input')).toBeInTheDocument(); + expect(queryByLabelText('test input')).not.toHaveAttribute('disabled'); + expect(queryByLabelText('test input')).toHaveAttribute('aria-disabled', 'false'); + expect(queryByLabelText('test input')).not.toBeDisabled(); + }); it('should have the `border-base` class by default', () => { - const { queryByLabelText } = render() + const { queryByLabelText } = render(); - expect(queryByLabelText('test input')).toBeInTheDocument() - expect(queryByLabelText('test input')).toHaveClass('border-base') - }) + expect(queryByLabelText('test input')).toBeInTheDocument(); + expect(queryByLabelText('test input')).toHaveClass('border-base'); + }); it('should have the `pl-12` class when the `icon` variant is passed', () => { - const { queryByLabelText } = render(} />) + const { queryByLabelText } = render(} />); - expect(queryByLabelText('test input')).toBeInTheDocument() - expect(queryByLabelText('test input')).toHaveClass('pl-12') - }) + expect(queryByLabelText('test input')).toBeInTheDocument(); + expect(queryByLabelText('test input')).toHaveClass('pl-12'); + }); it('should have the `bg-disabled` and `border-transparent` classes when the `disabled` variant is passed', () => { - const { queryByLabelText } = render() + const { queryByLabelText } = render(); - expect(queryByLabelText('test input')).toBeInTheDocument() - expect(queryByLabelText('test input')).toHaveClass('bg-disabled') - expect(queryByLabelText('test input')).toHaveClass('border-transparent') - }) + expect(queryByLabelText('test input')).toBeInTheDocument(); + expect(queryByLabelText('test input')).toHaveClass('bg-disabled'); + expect(queryByLabelText('test input')).toHaveClass('border-transparent'); + }); it('should have the `aria-invalid` and `aria-describedby` attributes if errorMessage is present', () => { const { queryByLabelText, queryByText } = render( , - ) - - expect(queryByLabelText('test input')).toBeInTheDocument() - expect(queryByLabelText('test input')).toHaveAttribute('aria-invalid') - expect(queryByLabelText('test input')).toHaveAttribute('aria-describedby') - expect(queryByText('some error')).toBeInTheDocument() - }) -}) + ); + + expect(queryByLabelText('test input')).toBeInTheDocument(); + expect(queryByLabelText('test input')).toHaveAttribute('aria-invalid'); + expect(queryByLabelText('test input')).toHaveAttribute('aria-describedby'); + expect(queryByText('some error')).toBeInTheDocument(); + }); +}); diff --git a/packages/extension/src/components/__tests__/switch.test.tsx b/packages/extension/src/components/__tests__/switch.test.tsx index 7c509b11..259a0d72 100644 --- a/packages/extension/src/components/__tests__/switch.test.tsx +++ b/packages/extension/src/components/__tests__/switch.test.tsx @@ -1,69 +1,69 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom'; -import { fireEvent, render, screen } from '@testing-library/react' -import React from 'react' +import { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; -import { Switch } from '@/components/switch' +import { Switch } from '@/components/switch'; describe('Switch', () => { it('renders without crashing', () => { - render() - expect(screen.getByRole('switch')).toBeInTheDocument() - }) + render(); + expect(screen.getByRole('switch')).toBeInTheDocument(); + }); it('applies default classes', () => { - render() - const switchElement = screen.getByRole('switch').nextSibling - expect(switchElement).toHaveClass('w-[42px] h-[26px] before:h-5 before:w-5') - }) + render(); + const switchElement = screen.getByRole('switch').nextSibling; + expect(switchElement).toHaveClass('w-[42px] h-[26px] before:h-5 before:w-5'); + }); it('applies small size classes when size prop is small', () => { - render() - const switchElement = screen.getByRole('switch').nextSibling - expect(switchElement).toHaveClass('w-9 h-[22px] before:h-4 before:w-4 before:left-[3px]') - }) + render(); + const switchElement = screen.getByRole('switch').nextSibling; + expect(switchElement).toHaveClass('w-9 h-[22px] before:h-4 before:w-4 before:left-[3px]'); + }); it('forwards ref to input element', () => { - const ref = React.createRef() - render() - expect(ref.current).toBeInstanceOf(HTMLInputElement) - }) + const ref = React.createRef(); + render(); + expect(ref.current).toBeInstanceOf(HTMLInputElement); + }); it('forwards checked prop to input element', () => { - render() - const inputElement = screen.getByRole('switch') - expect(inputElement).toBeChecked() - }) + render(); + const inputElement = screen.getByRole('switch'); + expect(inputElement).toBeChecked(); + }); it('handles additional props', () => { - render() - const inputElement = screen.getByRole('switch') - expect(inputElement).toHaveAttribute('aria-label', 'Custom Switch') - }) + render(); + const inputElement = screen.getByRole('switch'); + expect(inputElement).toHaveAttribute('aria-label', 'Custom Switch'); + }); it('applies custom class names', () => { - const customClass = 'custom-class' - render() - const switchElement = screen.getByRole('switch').nextSibling - expect(switchElement).toHaveClass(customClass) - }) + const customClass = 'custom-class'; + render(); + const switchElement = screen.getByRole('switch').nextSibling; + expect(switchElement).toHaveClass(customClass); + }); it('toggles switch state when clicked', () => { - render() - const inputElement = screen.getByRole('switch') - expect(inputElement).not.toBeChecked() + render(); + const inputElement = screen.getByRole('switch'); + expect(inputElement).not.toBeChecked(); - fireEvent.click(inputElement) - expect(inputElement).toBeChecked() + fireEvent.click(inputElement); + expect(inputElement).toBeChecked(); - fireEvent.click(inputElement) - expect(inputElement).not.toBeChecked() - }) + fireEvent.click(inputElement); + expect(inputElement).not.toBeChecked(); + }); it('handles additional HTML attributes', () => { - const testId = 'switch-test' - render() - const switchElement = screen.getByTestId(testId) - expect(switchElement).toBeInTheDocument() - }) -}) + const testId = 'switch-test'; + render(); + const switchElement = screen.getByTestId(testId); + expect(switchElement).toBeInTheDocument(); + }); +}); diff --git a/packages/extension/src/components/button.tsx b/packages/extension/src/components/button.tsx index 4566fc04..6167d342 100644 --- a/packages/extension/src/components/button.tsx +++ b/packages/extension/src/components/button.tsx @@ -1,8 +1,8 @@ -import { type VariantProps, cva } from 'class-variance-authority' -import React, { forwardRef } from 'react' +import { type VariantProps, cva } from 'class-variance-authority'; +import React, { forwardRef } from 'react'; -import { LoadingSpinner } from '@/components/loading-spinner' -import { cn } from '@/utils/cn' +import { LoadingSpinner } from '@/components/loading-spinner'; +import { cn } from '@/utils/cn'; const buttonVariants = cva( [ @@ -32,13 +32,13 @@ const buttonVariants = cva( size: 'default', }, }, -) +); export interface ButtonProps extends VariantProps, React.ButtonHTMLAttributes { - loading?: boolean - ['aria-label']: string + loading?: boolean; + ['aria-label']: string; } export const Button = forwardRef(function Button( @@ -52,8 +52,9 @@ export const Button = forwardRef(function Button className={cn(buttonVariants({ variant, size, fullWidth, loading }), className)} disabled={props.disabled ?? loading ?? false} aria-disabled={props.disabled ?? loading ?? false} - {...props}> + {...props} + > {loading ? : children} - ) -}) + ); +}); diff --git a/packages/extension/src/components/icons.tsx b/packages/extension/src/components/icons.tsx index ee34cb21..9da0a83a 100644 --- a/packages/extension/src/components/icons.tsx +++ b/packages/extension/src/components/icons.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React from 'react'; export const Spinner = (props: React.SVGProps) => { return ( @@ -7,7 +7,8 @@ export const Spinner = (props: React.SVGProps) => { xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16" - {...props}> + {...props} + > ) => { d="M2.204 6.447A6 6 0 108 2" /> - ) -} + ); +}; export const DollarSign = (props: React.SVGProps) => { return ( @@ -26,7 +27,8 @@ export const DollarSign = (props: React.SVGProps) => { viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" - {...props}> + {...props} + > ) => { x="0" y="0" width="24" - height="24"> + height="24" + > @@ -47,5 +50,5 @@ export const DollarSign = (props: React.SVGProps) => { - ) -} + ); +}; diff --git a/packages/extension/src/components/input.tsx b/packages/extension/src/components/input.tsx index c98ec04e..b25789d0 100644 --- a/packages/extension/src/components/input.tsx +++ b/packages/extension/src/components/input.tsx @@ -1,7 +1,7 @@ -import { type VariantProps, cva } from 'class-variance-authority' -import React, { forwardRef } from 'react' +import { type VariantProps, cva } from 'class-variance-authority'; +import React, { forwardRef } from 'react'; -import { cn } from '@/utils/cn' +import { cn } from '@/utils/cn'; const inputVariants = cva( [ @@ -23,14 +23,14 @@ const inputVariants = cva( variant: 'default', }, }, -) +); export interface InputProps extends VariantProps, React.InputHTMLAttributes { - errorMessage?: string - disabled?: boolean - icon?: React.ReactNode + errorMessage?: string; + disabled?: boolean; + icon?: React.ReactNode; } export const Input = forwardRef(function Input( @@ -52,5 +52,5 @@ export const Input = forwardRef(function Input( /> {errorMessage &&

{errorMessage}

} - ) -}) + ); +}); diff --git a/packages/extension/src/components/label.tsx b/packages/extension/src/components/label.tsx index 94f6063f..b3621174 100644 --- a/packages/extension/src/components/label.tsx +++ b/packages/extension/src/components/label.tsx @@ -1,14 +1,14 @@ -import { type VariantProps, cva } from 'class-variance-authority' -import React, { forwardRef } from 'react' +import { type VariantProps, cva } from 'class-variance-authority'; +import React, { forwardRef } from 'react'; -import { cn } from '@/utils/cn' +import { cn } from '@/utils/cn'; -const labelVariants = cva('text-medium font-medium leading-6 px-2 flex items-center gap-2') +const labelVariants = cva('text-medium font-medium leading-6 px-2 flex items-center gap-2'); export interface LabelProps extends VariantProps, React.LabelHTMLAttributes { - children: React.ReactNode + children: React.ReactNode; } export const Label = forwardRef(function Label( @@ -19,5 +19,5 @@ export const Label = forwardRef(function Label( - ) -}) + ); +}); diff --git a/packages/extension/src/components/loading-spinner.tsx b/packages/extension/src/components/loading-spinner.tsx index c42a723c..d0d6f4b9 100644 --- a/packages/extension/src/components/loading-spinner.tsx +++ b/packages/extension/src/components/loading-spinner.tsx @@ -1,7 +1,7 @@ -import { type VariantProps, cva } from 'class-variance-authority' -import React from 'react' +import { type VariantProps, cva } from 'class-variance-authority'; +import React from 'react'; -import { Spinner } from '@/components/icons' +import { Spinner } from '@/components/icons'; const loadingSpinnerStyles = cva('animate-spin text-white', { variants: { @@ -13,10 +13,10 @@ const loadingSpinnerStyles = cva('animate-spin text-white', { defaultVariants: { variant: 'lg', }, -}) +}); -export type LoadingIndicatorProps = VariantProps +export type LoadingIndicatorProps = VariantProps; export const LoadingSpinner = ({ variant }: LoadingIndicatorProps) => { - return -} + return ; +}; diff --git a/packages/extension/src/components/switch.tsx b/packages/extension/src/components/switch.tsx index 5771072c..65a52dbf 100644 --- a/packages/extension/src/components/switch.tsx +++ b/packages/extension/src/components/switch.tsx @@ -1,7 +1,7 @@ -import { type VariantProps, cva } from 'class-variance-authority' -import React, { forwardRef } from 'react' +import { type VariantProps, cva } from 'class-variance-authority'; +import React, { forwardRef } from 'react'; -import { cn } from '@/utils/cn' +import { cn } from '@/utils/cn'; const switchVariants = cva( [ @@ -27,12 +27,12 @@ const switchVariants = cva( size: 'default', }, }, -) +); export interface SwitchProps extends VariantProps, React.HTMLAttributes { - checked?: boolean + checked?: boolean; } export const Switch = forwardRef(function Switch( @@ -50,5 +50,5 @@ export const Switch = forwardRef(function Switch( />
- ) -}) + ); +}); diff --git a/packages/extension/src/content/index.tsx b/packages/extension/src/content/index.tsx index 56d02f73..fe96294f 100755 --- a/packages/extension/src/content/index.tsx +++ b/packages/extension/src/content/index.tsx @@ -1,26 +1,26 @@ -import { runtime } from 'webextension-polyfill' +import { runtime } from 'webextension-polyfill'; -import { initMonetizationTagManager } from '@/utils/monetizationTagManager' -import { wm2Polyfill } from '@/utils/polyfill' +import { initMonetizationTagManager } from '@/utils/monetizationTagManager'; +import { wm2Polyfill } from '@/utils/polyfill'; -import { loadObserver } from './linksObserver' -import MessageListener from './messageListener' +import { loadObserver } from './linksObserver'; +import MessageListener from './messageListener'; // import "./content.css"; -runtime.onMessage.addListener(MessageListener) +runtime.onMessage.addListener(MessageListener); function inject(configure: (_script: HTMLScriptElement) => void) { - const script = document.createElement('script') - configure(script) - document.documentElement.appendChild(script) + const script = document.createElement('script'); + configure(script); + document.documentElement.appendChild(script); // document.documentElement.removeChild(script) } // eslint-disable-next-line @typescript-eslint/no-extra-semi -;(function injectCode(code: string) { - inject(script => (script.innerHTML = code)) -})(wm2Polyfill) +(function injectCode(code: string) { + inject(script => (script.innerHTML = code)); +})(wm2Polyfill); -loadObserver() -initMonetizationTagManager() +loadObserver(); +initMonetizationTagManager(); diff --git a/packages/extension/src/content/linksObserver.ts b/packages/extension/src/content/linksObserver.ts index 727f871c..fadf6f2b 100644 --- a/packages/extension/src/content/linksObserver.ts +++ b/packages/extension/src/content/linksObserver.ts @@ -7,38 +7,38 @@ const listenForLinkChange = (mutationsList: MutationRecord[]) => { link.getAttribute('href')?.match(/^http/) && link.getAttribute('rel')?.match(/monetization/) ) { - acc.push(link) + acc.push(link); } - return acc + return acc; }, [], - ) + ); if (monetizationLinks.length) { - console.log(monetizationLinks) + console.log(monetizationLinks); } } if (mutationsList[0].type === 'attributes') { - const target = mutationsList[0].target as HTMLElement + const target = mutationsList[0].target as HTMLElement; if ( target.tagName?.toLowerCase() === 'link' && target.getAttribute('href')?.match(/^http/) && target.getAttribute('rel')?.match(/monetization/) ) { - console.log('LINK ATTR CHANGED', target) + console.log('LINK ATTR CHANGED', target); } } -} +}; export const loadObserver = () => { - const observer = new MutationObserver(listenForLinkChange) + const observer = new MutationObserver(listenForLinkChange); const observeOptions = { attributes: true, childList: true, subtree: true, - } + }; - observer.observe(document, observeOptions) -} + observer.observe(document, observeOptions); +}; diff --git a/packages/extension/src/content/messageListener.ts b/packages/extension/src/content/messageListener.ts index e61fed35..1142ea89 100644 --- a/packages/extension/src/content/messageListener.ts +++ b/packages/extension/src/content/messageListener.ts @@ -1,8 +1,8 @@ // import { Runtime } from 'webextension-polyfill' -import { PaymentSender } from '@/content/monetization' +import { PaymentSender } from '@/content/monetization'; -const paymentSender = new PaymentSender() +const paymentSender = new PaymentSender(); export const onRequest = async ( msg: EXTMessage, @@ -12,7 +12,7 @@ export const onRequest = async ( switch (msg.type) { case 'IS_MONETIZATION_READY': { - const monetizationTag = document.querySelector('link[rel="monetization"]') + const monetizationTag = document.querySelector('link[rel="monetization"]'); return { type: 'SUCCESS', @@ -20,21 +20,21 @@ export const onRequest = async ( monetization: !!monetizationTag, paymentPointer: monetizationTag?.getAttribute('href'), }, - } + }; } case 'START_PAYMENTS': { - paymentSender.start() - break + paymentSender.start(); + break; } case 'STOP_PAYMENTS': { - paymentSender.stop() - break + paymentSender.stop(); + break; } case 'PAYMENT_SUCCESS': { - const { receiveAmount, incomingPayment, paymentPointer } = msg.data + const { receiveAmount, incomingPayment, paymentPointer } = msg.data; window.dispatchEvent( new CustomEvent('monetization-v2', { @@ -51,14 +51,14 @@ export const onRequest = async ( receipt: null, }, }), - ) + ); - break + break; } default: - return { type: 'SUCCESS' } + return { type: 'SUCCESS' }; } -} +}; -export default onRequest +export default onRequest; diff --git a/packages/extension/src/content/monetization.tsx b/packages/extension/src/content/monetization.tsx index c7043939..fb256556 100644 --- a/packages/extension/src/content/monetization.tsx +++ b/packages/extension/src/content/monetization.tsx @@ -1,12 +1,12 @@ -import { sendMessage } from '@/utils/sendMessages' +import { sendMessage } from '@/utils/sendMessages'; export class PaymentSender { - sender: any + sender: any; start() { this.sender = setInterval(() => { - this.send() - }, 1000) + this.send(); + }, 1000); // stop payments manually after 3 seconds // setTimeout(() => { @@ -15,11 +15,11 @@ export class PaymentSender { } stop() { - sendMessage({ type: 'PAUSE_PAYMENTS' }) - clearInterval(this.sender) + sendMessage({ type: 'PAUSE_PAYMENTS' }); + clearInterval(this.sender); } send() { - sendMessage({ type: 'RUN_PAYMENT' }) + sendMessage({ type: 'RUN_PAYMENT' }); } } diff --git a/packages/extension/src/manifest/chrome-v3.json b/packages/extension/src/manifest/chrome-v3.json index 622b6a88..60aa11ea 100644 --- a/packages/extension/src/manifest/chrome-v3.json +++ b/packages/extension/src/manifest/chrome-v3.json @@ -1,39 +1,39 @@ { - "name": "__MSG_appName__", - "version": "1.0.1", - "manifest_version": 3, - "description": "__MSG_appDescription__", - "icons": { - "34": "assets/icons/icon-34.png", - "128": "assets/icons/icon-128.png" + "name": "__MSG_appName__", + "version": "1.0.1", + "manifest_version": 3, + "description": "__MSG_appDescription__", + "icons": { + "34": "assets/icons/icon-34.png", + "128": "assets/icons/icon-128.png" + }, + "default_locale": "en", + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*"], + "js": ["content/content.js"] + } + ], + "background": { + "service_worker": "background/background.js" + }, + "permissions": ["tabs", "storage"], + "host_permissions": ["http://*/*", "https://*/*"], + "options_ui": { + "page": "options/index.html" + }, + "action": { + "default_icon": { + "16": "assets/icons/icon-16.png", + "48": "assets/icons/icon-48.png" }, - "default_locale": "en", - "content_scripts": [ - { - "matches": ["http://*/*", "https://*/*"], - "js": ["content/content.js"] - } - ], - "background": { - "service_worker": "background/background.js" - }, - "permissions": ["tabs", "storage"], - "host_permissions": ["http://*/*", "https://*/*"], - "options_ui": { - "page": "options/index.html" - }, - "action": { - "default_icon": { - "16": "assets/icons/icon-16.png", - "48": "assets/icons/icon-48.png" - }, - "default_title": "Web Monetization", - "default_popup": "popup/index.html" - }, - "web_accessible_resources": [ - { - "resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], - "matches": [""] - } - ] + "default_title": "Web Monetization", + "default_popup": "popup/index.html" + }, + "web_accessible_resources": [ + { + "resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], + "matches": [""] + } + ] } diff --git a/packages/extension/src/manifest/chrome.json b/packages/extension/src/manifest/chrome.json index 68de6a36..8805a11e 100644 --- a/packages/extension/src/manifest/chrome.json +++ b/packages/extension/src/manifest/chrome.json @@ -1,33 +1,27 @@ { - "name": "__MSG_appName__", - "version": "1.0.1", - "manifest_version": 2, - "description": "__MSG_appDescription__", - "icons": { - "34": "assets/icons/icon-34.png", - "128": "assets/icons/icon-128.png" - }, - "default_locale": "en", - "content_scripts": [ - { - "matches": ["http://*/*", "https://*/*", ""], - "js": ["content/content.js"] - } - ], - "background": { - "scripts": ["background/background.js"] - }, - "permissions": ["tabs", "storage"], - "browser_action": { - "default_icon": "assets/icons/icon-34.png", - "default_title": "Web Monetization", - "default_popup": "popup/index.html" - }, - "web_accessible_resources": [ - "assets/*", - "content/*", - "options/*", - "popup/*", - "background/*" - ] + "name": "__MSG_appName__", + "version": "1.0.1", + "manifest_version": 2, + "description": "__MSG_appDescription__", + "icons": { + "34": "assets/icons/icon-34.png", + "128": "assets/icons/icon-128.png" + }, + "default_locale": "en", + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*", ""], + "js": ["content/content.js"] + } + ], + "background": { + "scripts": ["background/background.js"] + }, + "permissions": ["tabs", "storage"], + "browser_action": { + "default_icon": "assets/icons/icon-34.png", + "default_title": "Web Monetization", + "default_popup": "popup/index.html" + }, + "web_accessible_resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"] } diff --git a/packages/extension/src/manifest/edge.json b/packages/extension/src/manifest/edge.json index dfa03fcb..631cd6eb 100644 --- a/packages/extension/src/manifest/edge.json +++ b/packages/extension/src/manifest/edge.json @@ -1,27 +1,27 @@ { - "name": "__MSG_appName__", - "version": "1.0.1", - "manifest_version": 3, - "description": "__MSG_appDescription__", - "icons": { - "34": "assets/icons/icon-34.png", - "128": "assets/icons/icon-128.png" - }, - "default_locale": "en", - "content_scripts": [ - { - "matches": ["http://*/*", "https://*/*"], - "js": ["content/content.js"] - } - ], - "background": { - "service_worker": "background/background.js" - }, - "host_permissions": ["http://*/*", "https://*/*"], - "web_accessible_resources": [ - { - "resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], - "matches": [""] - } - ] + "name": "__MSG_appName__", + "version": "1.0.1", + "manifest_version": 3, + "description": "__MSG_appDescription__", + "icons": { + "34": "assets/icons/icon-34.png", + "128": "assets/icons/icon-128.png" + }, + "default_locale": "en", + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*"], + "js": ["content/content.js"] + } + ], + "background": { + "service_worker": "background/background.js" + }, + "host_permissions": ["http://*/*", "https://*/*"], + "web_accessible_resources": [ + { + "resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], + "matches": [""] + } + ] } diff --git a/packages/extension/src/manifest/firefox-v3.json b/packages/extension/src/manifest/firefox-v3.json index ee9ae7e4..a7b770aa 100644 --- a/packages/extension/src/manifest/firefox-v3.json +++ b/packages/extension/src/manifest/firefox-v3.json @@ -1,47 +1,47 @@ { - "name": "__MSG_appName__", - "version": "1.0.1", - "manifest_version": 3, - "description": "__MSG_appDescription__", - "icons": { - "34": "assets/icons/icon-34.png", - "128": "assets/icons/icon-128.png" - }, - "default_locale": "en", - "content_scripts": [ - { - "matches": ["http://*/*", "https://*/*"], - "js": ["content/content.js"] - } - ], - "background": { - "scripts": ["background/background.js"], - "type": "module" - }, - "permissions": ["tabs", "storage"], - "host_permissions": ["http://*/*", "https://*/*"], - "options_ui": { - "page": "options/index.html", - "browser_style": false - }, - "action": { - "default_icon": { - "16": "assets/icons/icon-16.png", - "48": "assets/icons/icon-48.png" - }, - "default_title": "Web Monetization", - "default_popup": "popup/index.html", - "browser_style": false + "name": "__MSG_appName__", + "version": "1.0.1", + "manifest_version": 3, + "description": "__MSG_appDescription__", + "icons": { + "34": "assets/icons/icon-34.png", + "128": "assets/icons/icon-128.png" + }, + "default_locale": "en", + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*"], + "js": ["content/content.js"] + } + ], + "background": { + "scripts": ["background/background.js"], + "type": "module" + }, + "permissions": ["tabs", "storage"], + "host_permissions": ["http://*/*", "https://*/*"], + "options_ui": { + "page": "options/index.html", + "browser_style": false + }, + "action": { + "default_icon": { + "16": "assets/icons/icon-16.png", + "48": "assets/icons/icon-48.png" }, - "web_accessible_resources": [ - { - "resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], - "matches": [""] - } - ], - "browser_specific_settings": { - "gecko": { - "id": "web-extension@interledger.com" - } + "default_title": "Web Monetization", + "default_popup": "popup/index.html", + "browser_style": false + }, + "web_accessible_resources": [ + { + "resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], + "matches": [""] + } + ], + "browser_specific_settings": { + "gecko": { + "id": "web-extension@interledger.com" } + } } diff --git a/packages/extension/src/manifest/firefox.json b/packages/extension/src/manifest/firefox.json index 14232657..275b1555 100644 --- a/packages/extension/src/manifest/firefox.json +++ b/packages/extension/src/manifest/firefox.json @@ -1,40 +1,34 @@ { - "name": "__MSG_appName__", - "version": "1.0.1", - "manifest_version": 2, - "description": "__MSG_appDescription__", - "icons": { - "34": "assets/icons/icon-34.png", - "128": "assets/icons/icon-128.png" - }, - "default_locale": "en", - "content_scripts": [ - { - "matches": ["http://*/*", "https://*/*", ""], - "js": ["content/content.js"] - } - ], - "background": { - "scripts": ["background/background.js"], - "type": "module" - }, - "permissions": ["tabs", "storage"], - "browser_action": { - "default_icon": "assets/icons/icon-34.png", - "default_title": "Web Monetization", - "default_popup": "popup/index.html", - "browser_style": false - }, - "web_accessible_resources": [ - "assets/*", - "content/*", - "options/*", - "popup/*", - "background/*" - ], - "browser_specific_settings": { - "gecko": { - "id": "web-extension@interledger.com" - } + "name": "__MSG_appName__", + "version": "1.0.1", + "manifest_version": 2, + "description": "__MSG_appDescription__", + "icons": { + "34": "assets/icons/icon-34.png", + "128": "assets/icons/icon-128.png" + }, + "default_locale": "en", + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*", ""], + "js": ["content/content.js"] } + ], + "background": { + "scripts": ["background/background.js"], + "type": "module" + }, + "permissions": ["tabs", "storage"], + "browser_action": { + "default_icon": "assets/icons/icon-34.png", + "default_title": "Web Monetization", + "default_popup": "popup/index.html", + "browser_style": false + }, + "web_accessible_resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], + "browser_specific_settings": { + "gecko": { + "id": "web-extension@interledger.com" + } + } } diff --git a/packages/extension/src/manifest/opera.json b/packages/extension/src/manifest/opera.json index dfa03fcb..631cd6eb 100644 --- a/packages/extension/src/manifest/opera.json +++ b/packages/extension/src/manifest/opera.json @@ -1,27 +1,27 @@ { - "name": "__MSG_appName__", - "version": "1.0.1", - "manifest_version": 3, - "description": "__MSG_appDescription__", - "icons": { - "34": "assets/icons/icon-34.png", - "128": "assets/icons/icon-128.png" - }, - "default_locale": "en", - "content_scripts": [ - { - "matches": ["http://*/*", "https://*/*"], - "js": ["content/content.js"] - } - ], - "background": { - "service_worker": "background/background.js" - }, - "host_permissions": ["http://*/*", "https://*/*"], - "web_accessible_resources": [ - { - "resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], - "matches": [""] - } - ] + "name": "__MSG_appName__", + "version": "1.0.1", + "manifest_version": 3, + "description": "__MSG_appDescription__", + "icons": { + "34": "assets/icons/icon-34.png", + "128": "assets/icons/icon-128.png" + }, + "default_locale": "en", + "content_scripts": [ + { + "matches": ["http://*/*", "https://*/*"], + "js": ["content/content.js"] + } + ], + "background": { + "service_worker": "background/background.js" + }, + "host_permissions": ["http://*/*", "https://*/*"], + "web_accessible_resources": [ + { + "resources": ["assets/*", "content/*", "options/*", "popup/*", "background/*"], + "matches": [""] + } + ] } diff --git a/packages/extension/src/popup/Popup.scss b/packages/extension/src/popup/Popup.scss index 5dcf9432..0f183007 100644 --- a/packages/extension/src/popup/Popup.scss +++ b/packages/extension/src/popup/Popup.scss @@ -3,7 +3,7 @@ body { height: fit-content; margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', - 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; + 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; diff --git a/packages/extension/src/popup/Popup.tsx b/packages/extension/src/popup/Popup.tsx index f8b8d062..a47775e3 100644 --- a/packages/extension/src/popup/Popup.tsx +++ b/packages/extension/src/popup/Popup.tsx @@ -1,102 +1,101 @@ -import './Popup.scss' +import './Popup.scss'; -import React, { useEffect, useState } from 'react' -import { runtime } from 'webextension-polyfill' +import React, { useEffect, useState } from 'react'; +import { runtime } from 'webextension-polyfill'; -import PopupFooter from '@/components/Popup/PopupFooter' -import PopupHeader from '@/components/Popup/PopupHeader' -import { Switch } from '@/components/switch' -import { sendMessage, sendMessageToActiveTab } from '@/utils/sendMessages' +import PopupFooter from '@/components/Popup/PopupFooter'; +import PopupHeader from '@/components/Popup/PopupHeader'; +import { sendMessage, sendMessageToActiveTab } from '@/utils/sendMessages'; -const Success = runtime.getURL('assets/images/web-monetization-success.svg') -const Fail = runtime.getURL('assets/images/web-monetization-fail.svg') -const CheckIcon = runtime.getURL('assets/images/check.svg') -const DollarIcon = runtime.getURL('assets/images/dollar.svg') -const CloseIcon = runtime.getURL('assets/images/close.svg') +const Success = runtime.getURL('assets/images/web-monetization-success.svg'); +const Fail = runtime.getURL('assets/images/web-monetization-fail.svg'); +const CheckIcon = runtime.getURL('assets/images/check.svg'); +const DollarIcon = runtime.getURL('assets/images/dollar.svg'); +const CloseIcon = runtime.getURL('assets/images/close.svg'); const Popup = () => { - const [loading, setLoading] = useState(false) - const [paymentStarted, setPaymentStarted] = useState(false) - const [spent, setSpent] = useState(0) - const [sendingPaymentPointer, setSendingPaymentPointer] = useState('') - const [isMonetizationReady, setIsMonetizationReady] = useState(false) - const [receivingPaymentPointer, setReceivingPaymentPointer] = useState('') + const [loading, setLoading] = useState(false); + const [paymentStarted, setPaymentStarted] = useState(false); + const [spent, setSpent] = useState(0); + const [sendingPaymentPointer, setSendingPaymentPointer] = useState(''); + const [isMonetizationReady, setIsMonetizationReady] = useState(false); + const [receivingPaymentPointer, setReceivingPaymentPointer] = useState(''); const [formData, setFormData] = useState({ paymentPointer: sendingPaymentPointer || '', amount: 20, - }) + }); useEffect(() => { - checkMonetizationReady() - getSendingPaymentPointer() - listenForIncomingPayment() + checkMonetizationReady(); + getSendingPaymentPointer(); + listenForIncomingPayment(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, []); const checkMonetizationReady = async () => { - const response = await sendMessageToActiveTab({ type: 'IS_MONETIZATION_READY' }) - setIsMonetizationReady(response.data.monetization) - setReceivingPaymentPointer(response.data.paymentPointer) - } + const response = await sendMessageToActiveTab({ type: 'IS_MONETIZATION_READY' }); + setIsMonetizationReady(response.data.monetization); + setReceivingPaymentPointer(response.data.paymentPointer); + }; const handleChange = (event: React.ChangeEvent) => { - setFormData(prevState => ({ ...prevState, [event.target.name]: event.target.value })) - } + setFormData(prevState => ({ ...prevState, [event.target.name]: event.target.value })); + }; const handleSubmit = async (event: React.FormEvent) => { - event.preventDefault() + event.preventDefault(); - setLoading(true) + setLoading(true); const data = { amount: formData.amount, paymentPointer: formData.paymentPointer, incomingPayment: receivingPaymentPointer, - } + }; - await sendMessage({ type: 'SET_INCOMING_POINTER', data }) - } + await sendMessage({ type: 'SET_INCOMING_POINTER', data }); + }; const getSendingPaymentPointer = async () => { - const response = await sendMessage({ type: 'GET_SENDING_PAYMENT_POINTER' }) - setSendingPaymentPointer(response.data.sendingPaymentPointerUrl) + const response = await sendMessage({ type: 'GET_SENDING_PAYMENT_POINTER' }); + setSendingPaymentPointer(response.data.sendingPaymentPointerUrl); - const { sendingPaymentPointerUrl: paymentPointer, amount } = response.data + const { sendingPaymentPointerUrl: paymentPointer, amount } = response.data; if (paymentPointer && amount) { setFormData({ paymentPointer: response.data.sendingPaymentPointerUrl, amount: response.data.amount, - }) + }); } - } + }; const listenForIncomingPayment = async () => { const listener = (message: any) => { if (message.type === 'SPENT_AMOUNT') { - setSpent(message.data.spentAmount) - setPaymentStarted(true) + setSpent(message.data.spentAmount); + setPaymentStarted(true); } if (loading) { - setLoading(false) + setLoading(false); } - } + }; - runtime.onMessage.addListener(listener) + runtime.onMessage.addListener(listener); return () => { - runtime.onMessage.removeListener(listener) - } - } + runtime.onMessage.removeListener(listener); + }; + }; const stopPayments = async (e: React.MouseEvent) => { - e.preventDefault() - setPaymentStarted(false) + e.preventDefault(); + setPaymentStarted(false); setTimeout(() => { if (loading) { - setLoading(false) + setLoading(false); } - }, 1000) - await sendMessageToActiveTab({ type: 'STOP_PAYMENTS' }) - } + }, 1000); + await sendMessageToActiveTab({ type: 'STOP_PAYMENTS' }); + }; return (
@@ -113,7 +112,8 @@ const Popup = () => {
+ className={`pointerForm ${paymentStarted ? 'active' : ''}`} + >
@@ -162,7 +162,7 @@ const Popup = () => {
- ) -} + ); +}; -export default Popup +export default Popup; diff --git a/packages/extension/src/popup/index.html b/packages/extension/src/popup/index.html index 5f106fb3..42644b2c 100755 --- a/packages/extension/src/popup/index.html +++ b/packages/extension/src/popup/index.html @@ -1,14 +1,10 @@ - + + + <%= htmlWebpackPlugin.options.title %> + - - - <%= htmlWebpackPlugin.options.title %> - - - - + - - + diff --git a/packages/extension/src/popup/index.tsx b/packages/extension/src/popup/index.tsx index e45924bd..26d956bc 100755 --- a/packages/extension/src/popup/index.tsx +++ b/packages/extension/src/popup/index.tsx @@ -1,9 +1,9 @@ -import './index.css' +import './index.css'; -import React from 'react' -import ReactDOM from 'react-dom/client' +import React from 'react'; +import ReactDOM from 'react-dom/client'; -import Popup from './Popup' +import Popup from './Popup'; -const root = ReactDOM.createRoot(document.getElementById('popup-container')!) -root.render() +const root = ReactDOM.createRoot(document.getElementById('popup-container')!); +root.render(); diff --git a/packages/extension/src/types/message.d.ts b/packages/extension/src/types/message.d.ts index 8dc5b546..021df720 100644 --- a/packages/extension/src/types/message.d.ts +++ b/packages/extension/src/types/message.d.ts @@ -9,9 +9,9 @@ declare type EXTMessageType = | 'START_PAYMENTS' | 'STOP_PAYMENTS' | 'PAYMENT_SUCCESS' - | 'PAUSE_PAYMENTS' + | 'PAUSE_PAYMENTS'; declare type EXTMessage = { - type: EXTMessageType - data?: T -} + type: EXTMessageType; + data?: T; +}; diff --git a/packages/extension/src/types/openControl.d.ts b/packages/extension/src/types/openControl.d.ts index 1c20b8ce..3a1bfab1 100644 --- a/packages/extension/src/types/openControl.d.ts +++ b/packages/extension/src/types/openControl.d.ts @@ -1,7 +1,7 @@ declare type OpenControls = { - isVisible: boolean - handleClose: () => void - handleOpen: () => void - handleToggle: () => void - isOpen: boolean -} + isVisible: boolean; + handleClose: () => void; + handleOpen: () => void; + handleToggle: () => void; + isOpen: boolean; +}; diff --git a/packages/extension/src/types/response.d.ts b/packages/extension/src/types/response.d.ts index 6cf03154..40c356fc 100644 --- a/packages/extension/src/types/response.d.ts +++ b/packages/extension/src/types/response.d.ts @@ -1,6 +1,6 @@ -declare type EXTResponseType = 'SUCCESS' | 'FAILED' | 'PENDING' | 'UNAUTHORIZED' | 'AUTHENTICATED' +declare type EXTResponseType = 'SUCCESS' | 'FAILED' | 'PENDING' | 'UNAUTHORIZED' | 'AUTHENTICATED'; declare type EXTResponse = { - type: EXTResponseType - data?: T -} + type: EXTResponseType; + data?: T; +}; diff --git a/packages/extension/src/utils/cn.ts b/packages/extension/src/utils/cn.ts index ef859784..fbb7fea2 100644 --- a/packages/extension/src/utils/cn.ts +++ b/packages/extension/src/utils/cn.ts @@ -1,6 +1,6 @@ -import { cx, CxOptions } from 'class-variance-authority' -import { twMerge } from 'tailwind-merge' +import { cx, CxOptions } from 'class-variance-authority'; +import { twMerge } from 'tailwind-merge'; export function cn(...inputs: CxOptions) { - return twMerge(cx(inputs)) + return twMerge(cx(inputs)); } diff --git a/packages/extension/src/utils/monetizationTagManager/CustomError.ts b/packages/extension/src/utils/monetizationTagManager/CustomError.ts index b259ec2a..8702500f 100644 --- a/packages/extension/src/utils/monetizationTagManager/CustomError.ts +++ b/packages/extension/src/utils/monetizationTagManager/CustomError.ts @@ -1,16 +1,16 @@ export class CustomError extends Error { constructor(message?: string) { // 'Error' breaks prototype chain here - super(message) + super(message); // restore prototype chain - const actualProto = new.target.prototype + const actualProto = new.target.prototype; if (Object.setPrototypeOf) { - Object.setPrototypeOf(this, actualProto) + Object.setPrototypeOf(this, actualProto); } else { // eslint-disable-next-line @typescript-eslint/no-explicit-any - ;(this as any).__proto__ = actualProto + (this as any).__proto__ = actualProto; } } } diff --git a/packages/extension/src/utils/monetizationTagManager/MonetizationTagManager.ts b/packages/extension/src/utils/monetizationTagManager/MonetizationTagManager.ts index bf616c64..0f84bcb0 100644 --- a/packages/extension/src/utils/monetizationTagManager/MonetizationTagManager.ts +++ b/packages/extension/src/utils/monetizationTagManager/MonetizationTagManager.ts @@ -1,15 +1,15 @@ /* eslint-disable */ -import { EventEmitter } from 'events' -import { v4 as uuidV4 } from 'uuid' +import { EventEmitter } from 'events'; +import { v4 as uuidV4 } from 'uuid'; -import { CustomError } from './CustomError' -import { mozClone } from './mozClone' -import { resolvePaymentEndpoint } from './resolvePaymentEndpoint' -import { whenDocumentReady } from './whenDocumentReady' +import { CustomError } from './CustomError'; +import { mozClone } from './mozClone'; +import { resolvePaymentEndpoint } from './resolvePaymentEndpoint'; +import { whenDocumentReady } from './whenDocumentReady'; const debug = // console.log.bind(console, 'MonetizationTagManager') - (..._: unknown[]) => {} + (..._: unknown[]) => {}; export interface PaymentDetails { /** @@ -17,12 +17,12 @@ export interface PaymentDetails { * configuration of a tag. e.g. a new href on a link will mean a new * requestId */ - requestId: string - paymentPointer: string - initiatingUrl: string - fromBody: boolean - tagType: TagType - attrs: Record + requestId: string; + paymentPointer: string; + initiatingUrl: string; + fromBody: boolean; + tagType: TagType; + attrs: Record; } /** @@ -31,95 +31,95 @@ export interface PaymentDetails { * On a tag[content|href] changed, both will be set */ export interface PaymentDetailsChangeArguments { - started: PaymentDetails | null - stopped: PaymentDetails | null + started: PaymentDetails | null; + stopped: PaymentDetails | null; } -export type PaymentDetailsChangeCallback = (_args: PaymentDetailsChangeArguments) => void +export type PaymentDetailsChangeCallback = (_args: PaymentDetailsChangeArguments) => void; -export type MonetizationTag = HTMLMetaElement | HTMLLinkElement -export type MonetizationTagList = NodeListOf +export type MonetizationTag = HTMLMetaElement | HTMLLinkElement; +export type MonetizationTagList = NodeListOf; -export type TagType = 'meta' | 'link' +export type TagType = 'meta' | 'link'; export function getTagType(tag: MonetizationTag): TagType { - return tag instanceof HTMLMetaElement ? 'meta' : 'link' + return tag instanceof HTMLMetaElement ? 'meta' : 'link'; } export class DeprecatedMetaTagIgnoredError extends CustomError {} interface FireOnMonetizationChangeIfHaveAttributeParams { - node: HTMLElement - changeDetected?: boolean + node: HTMLElement; + changeDetected?: boolean; } export const metaDeprecatedMessage = 'Web-Monetization Error: ' + 'A `` tag has been seen, so ' + 'ignoring deprecated `` tag and ' + - 'using only `` tags consistently' + 'using only `` tags consistently'; export const MonetizationTagAttrs = { meta: ['content', 'name'], link: ['href', 'disabled', 'rel', 'crossorigin', 'type'], -} +}; -const MAX_NUMBER_META_TAGS = 1 +const MAX_NUMBER_META_TAGS = 1; function monetizationTagTypeSpecified(tag: Node, ambiguous = false): tag is MonetizationTag { if (tag instanceof HTMLLinkElement) { - return tag.rel === 'monetization' || (ambiguous && !tag.rel) + return tag.rel === 'monetization' || (ambiguous && !tag.rel); } else if (tag instanceof HTMLMetaElement) { - return tag.name === 'monetization' || (ambiguous && !tag.name) + return tag.name === 'monetization' || (ambiguous && !tag.name); } else { - return false + return false; } } function nodeIsPotentiallyMonetizationTag(node: Node): node is MonetizationTag { - return node instanceof HTMLLinkElement || node instanceof HTMLMetaElement + return node instanceof HTMLLinkElement || node instanceof HTMLMetaElement; } function getTagAttrs(tag: MonetizationTag, tagType: TagType) { return Object.fromEntries( MonetizationTagAttrs[tagType].map(attr => { - return [attr, tag.getAttribute(attr)] + return [attr, tag.getAttribute(attr)]; }), - ) + ); } export class MonetizationTagManager extends EventEmitter { - private affinity: TagType = 'meta' - private documentObserver: MutationObserver - private monetizationTagAttrObserver: MutationObserver + private affinity: TagType = 'meta'; + private documentObserver: MutationObserver; + private monetizationTagAttrObserver: MutationObserver; private monetizationTags = new Map< MonetizationTag, { - details: PaymentDetails + details: PaymentDetails; } - >() + >(); - private linkTagsById = new Map() + private linkTagsById = new Map(); dispatchEventByLinkId(id: string, event: Event) { - const link = this.linkTagsById.get(id) + const link = this.linkTagsById.get(id); if (link) { - debug('dispatchLinkEventByLinkId', id, event) - link.dispatchEvent(event) + debug('dispatchLinkEventByLinkId', id, event); + link.dispatchEvent(event); } } requestIds(): string[] { - return Array.from(this.monetizationTags.values()).map(e => e.details.requestId) + return Array.from(this.monetizationTags.values()).map(e => e.details.requestId); } linkRequests(): PaymentDetails[] { - return this.requests().filter(d => d.tagType === 'link') + return this.requests().filter(d => d.tagType === 'link'); } requests(): PaymentDetails[] { - return Array.from(this.monetizationTags.values()).map(e => e.details) + return Array.from(this.monetizationTags.values()).map(e => e.details); } constructor( @@ -128,81 +128,81 @@ export class MonetizationTagManager extends EventEmitter { private callback: PaymentDetailsChangeCallback, private throwOnIllegalState = true, ) { - super() - this.documentObserver = new MutationObserver(records => this._onWholeDocumentObserved(records)) + super(); + this.documentObserver = new MutationObserver(records => this._onWholeDocumentObserved(records)); this.monetizationTagAttrObserver = new MutationObserver(records => this._onMonetizationTagAttrsChange(records), - ) + ); } /** * Wait until the document is ready and formed */ startWhenDocumentReady(): void { - whenDocumentReady(this.document, this._start.bind(this)) + whenDocumentReady(this.document, this._start.bind(this)); } // Though this is `public`, it's not part of the public interface, so we // prefix this method with `_` with no `private` modifier, in order to // jest.spyOn it. _start() { - const monetizationTags: MonetizationTagList = this.document.querySelectorAll('meta,link') + const monetizationTags: MonetizationTagList = this.document.querySelectorAll('meta,link'); monetizationTags.forEach(tag => { try { - this._observeMonetizationTagAttrs(tag) - this.onAddedTag(tag) + this._observeMonetizationTagAttrs(tag); + this.onAddedTag(tag); } catch (e) { // eslint-disable-next-line no-console - console.error(e) + console.error(e); } - }) - const onMonetizations = this.document.querySelectorAll('[onmonetization]') + }); + const onMonetizations = this.document.querySelectorAll('[onmonetization]'); onMonetizations.forEach(om => { - this.checkMonetizationAttr(om) - }) + this.checkMonetizationAttr(om); + }); this.documentObserver.observe(this.document, { subtree: true, childList: true, attributeFilter: ['onmonetization'], - }) + }); } _check(op: string, node: Node) { - debug('head node', op, node) + debug('head node', op, node); if (nodeIsPotentiallyMonetizationTag(node)) { if (op === 'added') { - this._observeMonetizationTagAttrs(node) - this.onAddedTag(node) + this._observeMonetizationTagAttrs(node); + this.onAddedTag(node); } else if (op === 'removed' && this.monetizationTags.has(node)) { - this._onRemovedTag(node) + this._onRemovedTag(node); } } if (op === 'added' && node instanceof HTMLElement) { - this.checkMonetizationAttr(node) + this.checkMonetizationAttr(node); } } - _checkRemoved = this._check.bind(this, 'removed') - _checkAdded = this._check.bind(this, 'added') + _checkRemoved = this._check.bind(this, 'removed'); + _checkAdded = this._check.bind(this, 'added'); _onWholeDocumentObserved(records: MutationRecord[]) { - debug('document mutation records.length=', records.length) + debug('document mutation records.length=', records.length); // Explicitly remove these first for (const record of records) { - debug('Record', record.type, record.target) + debug('Record', record.type, record.target); if (record.type === 'childList') { - record.removedNodes.forEach(this._checkRemoved) + record.removedNodes.forEach(this._checkRemoved); } } for (const record of records) { - debug('Record', record.type, record.target) + debug('Record', record.type, record.target); if (record.type === 'childList') { - record.addedNodes.forEach(this._checkAdded) + record.addedNodes.forEach(this._checkAdded); } } - this.onOnMonetizationChangeObserved(records) + this.onOnMonetizationChangeObserved(records); } /** @@ -211,27 +211,27 @@ export class MonetizationTagManager extends EventEmitter { * @param records */ _onMonetizationTagAttrsChange(records: MutationRecord[]) { - const handledTags = new Set() + const handledTags = new Set(); // Check for a non specified link or meta with the type now specified and // just treat it as a newly seen, monetization tag for (const record of records) { - const target = record.target as MonetizationTag + const target = record.target as MonetizationTag; if (handledTags.has(target)) { - continue + continue; } - const hasTarget = this.monetizationTags.has(target) - const typeSpecified = monetizationTagTypeSpecified(target) + const hasTarget = this.monetizationTags.has(target); + const typeSpecified = monetizationTagTypeSpecified(target); // this will also handle the case of a @disabled tag that // is not tracked, becoming enabled if (!hasTarget && typeSpecified) { - this.onAddedTag(target) - handledTags.add(target) + this.onAddedTag(target); + handledTags.add(target); } else if (hasTarget && !typeSpecified) { - this._onRemovedTag(target) - handledTags.add(target) + this._onRemovedTag(target); + handledTags.add(target); } else if (!hasTarget && !typeSpecified) { // ignore these changes - handledTags.add(target) + handledTags.add(target); } else if (hasTarget && typeSpecified) { if ( record.type === 'attributes' && @@ -240,11 +240,11 @@ export class MonetizationTagManager extends EventEmitter { // can't use record.target[disabled] as it's a Boolean not string target.getAttribute('disabled') !== record.oldValue ) { - const wasDisabled = record.oldValue !== null - const isDisabled = target.hasAttribute('disabled') + const wasDisabled = record.oldValue !== null; + const isDisabled = target.hasAttribute('disabled'); if (wasDisabled != isDisabled) { - this._onChangedPaymentEndpoint(target, isDisabled, wasDisabled) - handledTags.add(target) + this._onChangedPaymentEndpoint(target, isDisabled, wasDisabled); + handledTags.add(target); } } else if ( record.type === 'attributes' && @@ -252,16 +252,16 @@ export class MonetizationTagManager extends EventEmitter { target instanceof HTMLMetaElement && target.content !== record.oldValue ) { - this._onChangedPaymentEndpoint(target) - handledTags.add(target) + this._onChangedPaymentEndpoint(target); + handledTags.add(target); } else if ( record.type === 'attributes' && record.attributeName === 'href' && target instanceof HTMLLinkElement && target.href !== record.oldValue ) { - this._onChangedPaymentEndpoint(target) - handledTags.add(target) + this._onChangedPaymentEndpoint(target); + handledTags.add(target); } } } @@ -280,36 +280,36 @@ export class MonetizationTagManager extends EventEmitter { */ private onAddedTag(tag: MonetizationTag) { if (!monetizationTagTypeSpecified(tag)) { - return + return; } - const type = getTagType(tag) + const type = getTagType(tag); // TODO:WM2 any other cases? if (type === 'link' && tag.hasAttribute('disabled')) { - return + return; } if (type != this.affinity) { if (type === 'link') { - this.affinity = 'link' + this.affinity = 'link'; // @ts-ignore for (const tag of this.monetizationTags.keys()) { - this._onRemovedTag(tag) + this._onRemovedTag(tag); } } } - let started: PaymentDetails | null = this.getPaymentDetails(tag) + let started: PaymentDetails | null = this.getPaymentDetails(tag); if (started.fromBody && started.tagType === 'meta') { const error = new Error( 'Web-Monetization Error: ' + 'must be in the document head', - ) - this.emit('illegal-state-error', error) + ); + this.emit('illegal-state-error', error); if (this.throwOnIllegalState) { - throw error + throw error; } else { - return + return; } } if ( @@ -330,92 +330,92 @@ export class MonetizationTagManager extends EventEmitter { // TODO:WM2, but this DOES work? // this won't work, may need to halt completely all the way up // the stack - return + return; } } if (started.tagType === 'link') { - started = this.checkStartedLinkForWellFormedness(started, tag) + started = this.checkStartedLinkForWellFormedness(started, tag); } if (started) { - this.monetizationTags.set(tag, { details: started }) - this.callback({ stopped: null, started: started }) + this.monetizationTags.set(tag, { details: started }); + this.callback({ stopped: null, started: started }); } } _observeMonetizationTagAttrs(tag: MonetizationTag) { - const attributeFilter = MonetizationTagAttrs[getTagType(tag)] + const attributeFilter = MonetizationTagAttrs[getTagType(tag)]; this.monetizationTagAttrObserver.observe(tag, { childList: false, attributeOldValue: true, attributeFilter, - }) + }); } _onRemovedTag(tag: MonetizationTag) { - const entry = this.getEntry(tag, '_onRemovedTag') - this.monetizationTags.delete(tag) - this.clearLinkById(entry.details) - this.callback({ started: null, stopped: entry.details }) + const entry = this.getEntry(tag, '_onRemovedTag'); + this.monetizationTags.delete(tag); + this.clearLinkById(entry.details); + this.callback({ started: null, stopped: entry.details }); } private getEntry(meta: MonetizationTag, caller = '') { - const entry = this.monetizationTags.get(meta) + const entry = this.monetizationTags.get(meta); if (!entry) { - throw new Error(`${caller}: tag not tracked: ${meta.outerHTML.slice(0, 200)}`) + throw new Error(`${caller}: tag not tracked: ${meta.outerHTML.slice(0, 200)}`); } - return entry + return entry; } _onChangedPaymentEndpoint(tag: MonetizationTag, disabled = false, wasDisabled = false) { - const entry = this.getEntry(tag, '_onChangedPaymentEndpoint') - const stopped = wasDisabled ? null : entry.details - this.clearLinkById(entry.details) - let started: PaymentDetails | null = null + const entry = this.getEntry(tag, '_onChangedPaymentEndpoint'); + const stopped = wasDisabled ? null : entry.details; + this.clearLinkById(entry.details); + let started: PaymentDetails | null = null; if (!disabled) { - started = this.getPaymentDetails(tag) - started = this.checkStartedLinkForWellFormedness(started, tag) + started = this.getPaymentDetails(tag); + started = this.checkStartedLinkForWellFormedness(started, tag); if (started) { - entry.details = started + entry.details = started; } } if (started || stopped) { - this.callback({ started, stopped }) + this.callback({ started, stopped }); } } private checkStartedLinkForWellFormedness(started: PaymentDetails, tag: MonetizationTag) { - let returnValue: PaymentDetails | null = started + let returnValue: PaymentDetails | null = started; if (started.tagType === 'link') { - let error: Error | null = null + let error: Error | null = null; try { - resolvePaymentEndpoint(started.paymentPointer, true) + resolvePaymentEndpoint(started.paymentPointer, true); } catch (e) { - error = e - returnValue = null + error = e; + returnValue = null; } if (!error && returnValue) { - this.linkTagsById.set(started.requestId, tag as HTMLLinkElement) + this.linkTagsById.set(started.requestId, tag as HTMLLinkElement); } else { - this.emit('link-resolve-payment-endpoint-error', tag, error) + this.emit('link-resolve-payment-endpoint-error', tag, error); // const event = new ErrorEvent('error', { error }) - const event = new Event('error') - tag.dispatchEvent(event) + const event = new Event('error'); + tag.dispatchEvent(event); } } - return returnValue + return returnValue; } private clearLinkById(stopped: PaymentDetails) { if (stopped.tagType === 'link') { - this.linkTagsById.delete(stopped.requestId) + this.linkTagsById.delete(stopped.requestId); } } private getPaymentDetails(tag: MonetizationTag): PaymentDetails { - const tagType = getTagType(tag) - const paymentPointer = tag instanceof HTMLMetaElement ? tag.content : tag.href + const tagType = getTagType(tag); + const paymentPointer = tag instanceof HTMLMetaElement ? tag.content : tag.href; return { attrs: getTagAttrs(tag, tagType), requestId: uuidV4(), @@ -425,12 +425,12 @@ export class MonetizationTagManager extends EventEmitter { initiatingUrl: this.window.location.href, tagType: getTagType(tag), fromBody: tag.parentElement != this.document.head, - } + }; } private checkMonetizationAttr(node: HTMLElement) { - debug('checkMonetizationAttr', node) - this.fireOnMonetizationAttrChangedEvent({ node }) + debug('checkMonetizationAttr', node); + this.fireOnMonetizationAttrChangedEvent({ node }); } private onOnMonetizationChangeObserved(records: MutationRecord[]) { @@ -443,7 +443,7 @@ export class MonetizationTagManager extends EventEmitter { this.fireOnMonetizationAttrChangedEvent({ node: record.target, changeDetected: true, - }) + }); } } } @@ -452,34 +452,34 @@ export class MonetizationTagManager extends EventEmitter { node, changeDetected = false, }: FireOnMonetizationChangeIfHaveAttributeParams) { - const attribute = node.getAttribute('onmonetization') + const attribute = node.getAttribute('onmonetization'); if (attribute || changeDetected) { const attributeDetail = { attribute, - } + }; const customEvent = new CustomEvent('onmonetization-attr-changed', { bubbles: true, detail: mozClone(attributeDetail, this.document), - }) - const result = node.dispatchEvent(customEvent) - debug('dispatched onmonetization-attr-changed ev', result) + }); + const result = node.dispatchEvent(customEvent); + debug('dispatched onmonetization-attr-changed ev', result); } } stop() { - this.documentObserver.disconnect() - this.monetizationTagAttrObserver.disconnect() - this.monetizationTags.clear() + this.documentObserver.disconnect(); + this.monetizationTagAttrObserver.disconnect(); + this.monetizationTags.clear(); } atMostOneTagAndNoneInBody() { - let fromBody = false + let fromBody = false; // @ts-ignore for (const value of this.monetizationTags.values()) { if (value.details.fromBody) { - fromBody = true + fromBody = true; } } - return this.monetizationTags.size <= 1 && !fromBody + return this.monetizationTags.size <= 1 && !fromBody; } } diff --git a/packages/extension/src/utils/monetizationTagManager/index.ts b/packages/extension/src/utils/monetizationTagManager/index.ts index 26b661ba..4581db36 100644 --- a/packages/extension/src/utils/monetizationTagManager/index.ts +++ b/packages/extension/src/utils/monetizationTagManager/index.ts @@ -1,39 +1,39 @@ -import { MonetizationTagManager } from '@/utils/monetizationTagManager/MonetizationTagManager' +import { MonetizationTagManager } from '@/utils/monetizationTagManager/MonetizationTagManager'; interface PaymentDetailsChangeArguments { - started: PaymentDetails | null - stopped: PaymentDetails | null + started: PaymentDetails | null; + stopped: PaymentDetails | null; } interface PaymentDetails { - requestId: string - paymentPointer: string - initiatingUrl: string - fromBody: boolean - tagType: 'link' - attrs: Record + requestId: string; + paymentPointer: string; + initiatingUrl: string; + fromBody: boolean; + tagType: 'link'; + attrs: Record; } export const initMonetizationTagManager = () => { const onPaymentDetailsChange = (details: PaymentDetailsChangeArguments) => { - const { started, stopped } = details + const { started, stopped } = details; if (stopped) { // debug('sending stopped request', JSON.stringify(stopped, null, 2)) // this.stopMonetization(stopped) - console.log('stop monetization') + console.log('stop monetization'); } if (started) { // debug('sending start request', JSON.stringify(started, null, 2)) // void this.startMonetization(started) // console.log('start monetization') } - } + }; const monetizationTagManager = new MonetizationTagManager( window, document, onPaymentDetailsChange, - ) + ); - monetizationTagManager.startWhenDocumentReady() -} + monetizationTagManager.startWhenDocumentReady(); +}; diff --git a/packages/extension/src/utils/monetizationTagManager/mozClone.ts b/packages/extension/src/utils/monetizationTagManager/mozClone.ts index dc4f8fe3..4909c5d7 100644 --- a/packages/extension/src/utils/monetizationTagManager/mozClone.ts +++ b/packages/extension/src/utils/monetizationTagManager/mozClone.ts @@ -1,14 +1,14 @@ -type DefaultView = WindowProxy & typeof globalThis -type CloneInto = (obj: unknown, _window: DefaultView | null) => typeof obj -declare const cloneInto: CloneInto | undefined +type DefaultView = WindowProxy & typeof globalThis; +type CloneInto = (obj: unknown, _window: DefaultView | null) => typeof obj; +declare const cloneInto: CloneInto | undefined; -let cloneIntoRef: CloneInto | undefined +let cloneIntoRef: CloneInto | undefined; try { - cloneIntoRef = cloneInto + cloneIntoRef = cloneInto; } catch (e) { - cloneIntoRef = undefined + cloneIntoRef = undefined; } export function mozClone(obj: unknown, document: Document) { - return cloneIntoRef ? cloneIntoRef(obj, document.defaultView) : obj + return cloneIntoRef ? cloneIntoRef(obj, document.defaultView) : obj; } diff --git a/packages/extension/src/utils/monetizationTagManager/resolvePaymentEndpoint.ts b/packages/extension/src/utils/monetizationTagManager/resolvePaymentEndpoint.ts index a76af1d0..bf0c046f 100644 --- a/packages/extension/src/utils/monetizationTagManager/resolvePaymentEndpoint.ts +++ b/packages/extension/src/utils/monetizationTagManager/resolvePaymentEndpoint.ts @@ -1,28 +1,30 @@ export class PaymentEndpointError extends Error {} export function resolvePaymentEndpoint(pointerOrUrl: string, urlOnly = false) { - const httpUrl = urlOnly ? pointerOrUrl : pointerOrUrl.replace(/^\$/, 'https://') + const httpUrl = urlOnly ? pointerOrUrl : pointerOrUrl.replace(/^\$/, 'https://'); - let url: URL + let url: URL; try { - url = new URL(httpUrl) + url = new URL(httpUrl); if (!url.protocol.match(/https?:/)) { - const spec = urlOnly ? '' : 'either a payment pointer or ' + const spec = urlOnly ? '' : 'either a payment pointer or '; // noinspection ExceptionCaughtLocallyJS throw new PaymentEndpointError( `SPSP endpoint must be specified as ${spec}fully resolved https:// url, ` + `got ${JSON.stringify(pointerOrUrl)} `, - ) + ); } } catch (e) { if (e instanceof PaymentEndpointError) { - throw e + throw e; } else { - throw new PaymentEndpointError(`Invalid payment pointer/url: ${JSON.stringify(pointerOrUrl)}`) + throw new PaymentEndpointError( + `Invalid payment pointer/url: ${JSON.stringify(pointerOrUrl)}`, + ); } } - const isPaymentPointer = pointerOrUrl.startsWith('$') + const isPaymentPointer = pointerOrUrl.startsWith('$'); if (isPaymentPointer && (url.hash || url.search || url.port || url.username || url.password)) { throw new PaymentEndpointError( @@ -35,7 +37,7 @@ export function resolvePaymentEndpoint(pointerOrUrl: string, urlOnly = false) { username: url.username, password: url.password, }), - ) + ); } - return isPaymentPointer && url.pathname === '/' ? url.href + '.well-known/pay' : url.href + return isPaymentPointer && url.pathname === '/' ? url.href + '.well-known/pay' : url.href; } diff --git a/packages/extension/src/utils/monetizationTagManager/whenDocumentReady.ts b/packages/extension/src/utils/monetizationTagManager/whenDocumentReady.ts index 3a845893..573e2ec9 100644 --- a/packages/extension/src/utils/monetizationTagManager/whenDocumentReady.ts +++ b/packages/extension/src/utils/monetizationTagManager/whenDocumentReady.ts @@ -1,15 +1,15 @@ export function whenDocumentReady(document: Document, start: () => void) { if (document.readyState === 'interactive' || document.readyState === 'complete') { - start() + start(); } else { document.addEventListener( 'readystatechange', () => { if (document.readyState === 'interactive') { - start() + start(); } }, { once: true }, - ) + ); } } diff --git a/packages/extension/src/utils/polyfill.ts b/packages/extension/src/utils/polyfill.ts index 6acf624e..ef5fd5eb 100644 --- a/packages/extension/src/utils/polyfill.ts +++ b/packages/extension/src/utils/polyfill.ts @@ -99,4 +99,4 @@ export const wm2Polyfill = ` } }, { capture: true }) dbg('add coil-onmonetization-v2-attr-changed handler end') -` +`; diff --git a/packages/extension/src/utils/sendMessages.ts b/packages/extension/src/utils/sendMessages.ts index 9e4c6dc5..a6f767c1 100644 --- a/packages/extension/src/utils/sendMessages.ts +++ b/packages/extension/src/utils/sendMessages.ts @@ -1,4 +1,4 @@ -import { Runtime, runtime, Tabs, tabs } from 'webextension-polyfill' +import { Runtime, runtime, Tabs, tabs } from 'webextension-polyfill'; /** * Send Message to Background Script @@ -10,8 +10,8 @@ export const sendMessage = ( msg: EXTMessage, options?: Runtime.SendMessageOptionsType, ): Promise => { - return runtime.sendMessage(msg, options) -} + return runtime.sendMessage(msg, options); +}; /** * Send Message to Content Script @@ -21,8 +21,8 @@ export const sendMessageToTab = ( msg: EXTMessage, options?: Tabs.SendMessageOptionsType, ): Promise => { - return tabs.sendMessage(tab.id as number, msg, options) -} + return tabs.sendMessage(tab.id as number, msg, options); +}; /** * Send Message to Content Script @@ -31,13 +31,13 @@ export const sendMessageToActiveTab = async ( msg: EXTMessage, options?: Tabs.SendMessageOptionsType, ): Promise => { - let activeTab: Tabs.Tab + let activeTab: Tabs.Tab; try { - const activeTabs = await tabs.query({ active: true, currentWindow: true }) - activeTab = activeTabs[0] + const activeTabs = await tabs.query({ active: true, currentWindow: true }); + activeTab = activeTabs[0]; } catch (error) { - console.log('[===== Error in sendMessageToActiveTab =====]', error) - throw `Error in sendMessageToActiveTab` + console.log('[===== Error in sendMessageToActiveTab =====]', error); + throw `Error in sendMessageToActiveTab`; } - return sendMessageToTab(activeTab, msg, options) -} + return sendMessageToTab(activeTab, msg, options); +}; diff --git a/packages/extension/src/utils/storage.ts b/packages/extension/src/utils/storage.ts index 24995aeb..7d08ce70 100755 --- a/packages/extension/src/utils/storage.ts +++ b/packages/extension/src/utils/storage.ts @@ -1,3 +1,3 @@ -import { storage } from 'webextension-polyfill' +import { storage } from 'webextension-polyfill'; -export default storage.sync ? storage.sync : storage.local +export default storage.sync ? storage.sync : storage.local; diff --git a/packages/extension/tailwind.config.ts b/packages/extension/tailwind.config.ts index 6c7d30e1..976f6dd9 100644 --- a/packages/extension/tailwind.config.ts +++ b/packages/extension/tailwind.config.ts @@ -1,4 +1,4 @@ -import { Config } from 'tailwindcss' +import { Config } from 'tailwindcss'; module.exports = { content: ['./src/**/*.{html,js,jsx,ts,tsx}', './src/components/**/*.{js,jsx,ts,tsx}'], @@ -38,4 +38,4 @@ module.exports = { }, }, plugins: [], -} satisfies Config +} satisfies Config; diff --git a/packages/extension/webpack.config.ts b/packages/extension/webpack.config.ts index 2222ff5f..efa7b11a 100644 --- a/packages/extension/webpack.config.ts +++ b/packages/extension/webpack.config.ts @@ -1,5 +1,5 @@ -import path from 'path' -import TerserPlugin from 'terser-webpack-plugin' +import path from 'path'; +import TerserPlugin from 'terser-webpack-plugin'; import { config, @@ -17,7 +17,7 @@ import { getProgressPlugins, getResolves, getZipPlugins, -} from './webpack.config.utils' +} from './webpack.config.utils'; let generalConfig: any = { mode: @@ -74,7 +74,7 @@ let generalConfig: any = { resolve: getResolves(), entry: getEntry(Directories.SRC_DIR), output: getOutput(config.TARGET, config.OUTPUT_DIR), -} +}; let plugins: any[] = [ ...getCleanWebpackPlugins( @@ -86,7 +86,7 @@ let plugins: any[] = [ ...getExtensionManifestPlugins(), ...getHTMLPlugins(config.TARGET, config.OUTPUT_DIR, Directories.SRC_DIR), ...getCopyPlugins(config.TARGET, config.OUTPUT_DIR, Directories.SRC_DIR), -] +]; if (config.NODE_ENV === 'development') { generalConfig = { @@ -103,7 +103,7 @@ if (config.NODE_ENV === 'development') { aggregateTimeout: 200, poll: 1000, }, - } + }; plugins = [ ...plugins, @@ -112,7 +112,7 @@ if (config.NODE_ENV === 'development') { WM_WALLET_ADDRESS: 'https://ilp.rafiki.money/wm-dev', }), ...getExtensionReloaderPlugins(), - ] + ]; } if (config.NODE_ENV === 'profile') { @@ -125,7 +125,7 @@ if (config.NODE_ENV === 'profile') { errors: true, hash: true, }, - } + }; plugins = [ ...plugins, @@ -134,7 +134,7 @@ if (config.NODE_ENV === 'profile') { WM_WALLET_ADDRESS: 'https://ilp.rafiki.money/wm-dev', }), ...getAnalyzerPlugins(), - ] + ]; } if (config.NODE_ENV === 'production') { @@ -154,7 +154,7 @@ if (config.NODE_ENV === 'production') { }), ], }, - } + }; plugins = [ ...plugins, @@ -164,7 +164,7 @@ if (config.NODE_ENV === 'production') { }), ...getZipPlugins(config.TARGET, Directories.DIST_DIR), - ] + ]; } export default [ @@ -172,4 +172,4 @@ export default [ ...generalConfig, plugins, }, -] +]; diff --git a/packages/extension/webpack.config.utils.ts b/packages/extension/webpack.config.utils.ts index a69e181c..0acc146c 100644 --- a/packages/extension/webpack.config.utils.ts +++ b/packages/extension/webpack.config.utils.ts @@ -1,31 +1,32 @@ -import { CleanWebpackPlugin } from 'clean-webpack-plugin' -import CopyWebpackPlugin from 'copy-webpack-plugin' -import ESLintPlugin from 'eslint-webpack-plugin' -import HtmlWebpackPlugin from 'html-webpack-plugin' -import path from 'path' -import { DefinePlugin, ProgressPlugin } from 'webpack' -import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer' -import WebpackExtensionManifestPlugin from 'webpack-extension-manifest-plugin' -import ZipPlugin from 'zip-webpack-plugin' +import { CleanWebpackPlugin } from 'clean-webpack-plugin'; +import CopyWebpackPlugin from 'copy-webpack-plugin'; +import ESLintPlugin from 'eslint-webpack-plugin'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import path from 'path'; +import { DefinePlugin, ProgressPlugin } from 'webpack'; +import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; +import WebpackExtensionManifestPlugin from 'webpack-extension-manifest-plugin'; +import ZipPlugin from 'zip-webpack-plugin'; -const ExtReloader = require('webpack-ext-reloader-mv3') +import manifestChrome from './src/manifest/chrome.json'; +import manifestEdge from './src/manifest/edge.json'; +import manifestFirefox from './src/manifest/firefox.json'; +import manifestOpera from './src/manifest/opera.json'; -const manifestChrome = require('./src/manifest/chrome.json') -const manifestFirefox = require('./src/manifest/firefox.json') -const manifestOpera = require('./src/manifest/opera.json') -const manifestEdge = require('./src/manifest/edge.json') +// eslint-disable-next-line @typescript-eslint/no-var-requires +const ExtReloader = require('webpack-ext-reloader-mv3'); const manifest = { chrome: manifestChrome, firefox: manifestFirefox, opera: manifestOpera, edge: manifestEdge, -} +}; interface EnvironmentConfig { - NODE_ENV: string - OUTPUT_DIR: string - TARGET: string + NODE_ENV: string; + OUTPUT_DIR: string; + TARGET: string; } export const Directories = { @@ -33,7 +34,7 @@ export const Directories = { DIST_DIR: 'dist', TEMP_DIR: 'temp', SRC_DIR: 'src', -} +}; /** * Environment Config @@ -48,7 +49,7 @@ const EnvConfig: EnvironmentConfig = { : Directories.DEV_DIR, ...(process.env.NODE_ENV ? { NODE_ENV: process.env.NODE_ENV } : { NODE_ENV: 'development' }), ...(process.env.TARGET ? { TARGET: process.env.TARGET } : { TARGET: 'chrome' }), -} +}; /** * Get HTML Plugins @@ -69,7 +70,7 @@ export const getHTMLPlugins = ( template: path.resolve(__dirname, `${sourceDir}/popup/index.html`), chunks: ['popup'], }), -] +]; /** * Get DefinePlugins @@ -82,7 +83,7 @@ export const getDefinePlugins = (config: { SIGNATURES_URL: string; WM_WALLET_ADD CONFIG_SIGNATURES_URL: JSON.stringify(config.SIGNATURES_URL), CONFIG_WM_WALLET_ADDRESS: JSON.stringify(config.WM_WALLET_ADDRESS), }), -] +]; /** * Get Output Configurations @@ -95,8 +96,8 @@ export const getOutput = (browserDir: string, outputDir = Directories.DEV_DIR) = return { path: path.resolve(process.cwd(), `${outputDir}/${browserDir}`), filename: '[name]/[name].js', - } -} + }; +}; /** * Get Entry Points @@ -109,8 +110,8 @@ export const getEntry = (sourceDir = Directories.SRC_DIR) => { popup: [path.resolve(__dirname, `${sourceDir}/popup/index.tsx`)], content: [path.resolve(__dirname, `${sourceDir}/content/index.tsx`)], background: [path.resolve(__dirname, `${sourceDir}/background/index.ts`)], - } -} + }; +}; /** * Get CopyPlugins @@ -138,8 +139,8 @@ export const getCopyPlugins = ( }, ], }), - ] -} + ]; +}; /** * Get ZipPlugins @@ -164,8 +165,8 @@ export const getZipPlugins = (browserDir: string, outputDir = Directories.DIST_D forceZip64Format: false, }, }), - ] -} + ]; +}; /** * Get Analyzer Plugins @@ -177,8 +178,8 @@ export const getAnalyzerPlugins = () => { new BundleAnalyzerPlugin({ analyzerMode: 'server', }), - ] -} + ]; +}; /** * Get CleanWebpackPlugins @@ -195,8 +196,8 @@ export const getCleanWebpackPlugins = (...dirs: string[]) => { cleanStaleWebpackAssets: false, verbose: true, }), - ] -} + ]; +}; /** * Get Resolves @@ -219,8 +220,8 @@ export const getResolves = () => { '@/hooks': path.resolve(__dirname, './src/hooks/'), }, extensions: ['.js', '.jsx', '.ts', '.tsx'], - } -} + }; +}; /** * Get Extension Manifest Plugins @@ -232,12 +233,12 @@ export const getExtensionManifestPlugins = () => { new WebpackExtensionManifestPlugin({ config: { base: (manifest as any)[EnvConfig.TARGET] }, }), - ] -} + ]; +}; export const eslintOptions = { fix: true, -} +}; /** * Get Eslint Plugins @@ -245,8 +246,8 @@ export const eslintOptions = { * @returns */ export const getEslintPlugins = (options = eslintOptions) => { - return [new ESLintPlugin(options)] -} + return [new ESLintPlugin(options)]; +}; /** * Get Progress Plugins @@ -254,14 +255,14 @@ export const getEslintPlugins = (options = eslintOptions) => { * @returns */ export const getProgressPlugins = () => { - return [new ProgressPlugin()] -} + return [new ProgressPlugin()]; +}; /** * Environment Configuration Variables * */ -export const config = EnvConfig +export const config = EnvConfig; /** * Get Extension Reloader Plugin @@ -279,5 +280,5 @@ export const getExtensionReloaderPlugins = () => { extensionPage: ['popup', 'options'], }, }), - ] -} + ]; +}; diff --git a/packages/server/.eslintrc.js b/packages/server/.eslintrc.js new file mode 100644 index 00000000..99979c28 --- /dev/null +++ b/packages/server/.eslintrc.js @@ -0,0 +1,5 @@ +module.exports = { + env: { + node: true, + }, +} diff --git a/packages/server/package.json b/packages/server/package.json index 8b67f0a8..72b5b719 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -7,16 +7,13 @@ "url": "git@github.com:interledeger/web-monetization-extension.git", "directory": "packages/server" }, - "keywords": [ - "ilp", - "open payments", - "interledger", - "web monetization" - ], "license": "Apache-2.0", "author": "Interledger Tech Team ", "scripts": { - "build": "tsc" + "build": "tsc", + "dev": "tsx --watch ./src/index.ts", + "lint": "eslint . --ext js,ts --max-warnings 0", + "lint:fix": "eslint . --ext ts --fix" }, "dependencies": { "@interledger/http-signature-utils": "^2.0.0", @@ -26,6 +23,7 @@ "devDependencies": { "@types/koa": "^2.14.0", "@types/koa-bodyparser": "^4.3.12", + "tsx": "^4.7.0", "typescript": "^5.2.2" } } diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index f382a684..41d984b7 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -3,9 +3,9 @@ import { Headers, loadBase64Key, RequestLike, -} from '@interledger/http-signature-utils' -import Koa from 'koa' -import bodyParser from 'koa-bodyparser' +} from '@interledger/http-signature-utils'; +import Koa from 'koa'; +import bodyParser from 'koa-bodyparser'; interface Context extends Koa.ParameterizedContext {} @@ -13,69 +13,69 @@ interface Context interface GenerateSignatureRequestBody extends RequestLike {} function validateBody(body: any): body is GenerateSignatureRequestBody { - return !!body.headers && !!body.method && !!body.url + return !!body.headers && !!body.method && !!body.url; } async function validatePath(ctx: Context, next: Koa.Next): Promise { if (ctx.path !== '/') { - ctx.status = 404 + ctx.status = 404; } else { - await next() + await next(); } } async function validateMethod(ctx: Context, next: Koa.Next): Promise { if (ctx.method !== 'POST') { - ctx.status = 405 + ctx.status = 405; } else { - await next() + await next(); } } async function createHeadersHandler(ctx: Context): Promise { - const { body } = ctx.request + const { body } = ctx.request; if (!validateBody(body)) { - ctx.throw('Invalid request body', 400) + ctx.throw('Invalid request body', 400); } - let privateKey: ReturnType + let privateKey: ReturnType; try { - privateKey = loadBase64Key(BASE64_PRIVATE_KEY) + privateKey = loadBase64Key(BASE64_PRIVATE_KEY); } catch { - ctx.throw('Not a valid private key', 400) + ctx.throw('Not a valid private key', 400); } if (privateKey === undefined) { - ctx.throw('Not an Ed25519 private key', 400) + ctx.throw('Not an Ed25519 private key', 400); } const headers = await createHeaders({ request: body, privateKey, keyId: KEY_ID, - }) + }); - delete headers['Content-Length'] - delete headers['Content-Type'] + delete headers['Content-Length']; + delete headers['Content-Type']; - ctx.body = headers + ctx.body = headers; } -const PORT = 3000 +const PORT = 3000; const BASE64_PRIVATE_KEY = - 'LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1DNENBUUF3QlFZREsyVndCQ0lFSUUvVlJTRVUzYS9CTUE2cmhUQnZmKzcxMG10YWlmbkF6SzFsWGpDK0QrSTkKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQ==' -const KEY_ID = 'f0ac2190-54d5-47c8-b061-221e7068d823' + 'LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1DNENBUUF3QlFZREsyVndCQ0lFSUUvVlJTRVUzYS9CTUE2cmhUQnZmKzcxMG10YWlmbkF6SzFsWGpDK0QrSTkKLS0tLS1FTkQgUFJJVkFURSBLRVktLS0tLQ=='; +const KEY_ID = 'f0ac2190-54d5-47c8-b061-221e7068d823'; -const app = new Koa() +const app = new Koa(); -app.use(bodyParser()) -app.use(validatePath) -app.use(validateMethod) -app.use(createHeadersHandler) +app.use(bodyParser()); +app.use(validatePath); +app.use(validateMethod); +app.use(createHeadersHandler); app.listen(3000, () => { // eslint-disable-next-line no-console - console.log(`Local signatures server started on port ${PORT}`) -}) + console.log(`Local signatures server started on port ${PORT}`); +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3fe501fb..e8526c93 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,33 +32,21 @@ importers: eslint-config-airbnb: specifier: ^19.0.4 version: 19.0.4(eslint-plugin-import@2.29.0)(eslint-plugin-jsx-a11y@6.8.0)(eslint-plugin-react-hooks@4.6.0)(eslint-plugin-react@7.33.2)(eslint@8.55.0) - eslint-config-prettier: - specifier: ^9.0.0 - version: 9.1.0(eslint@8.55.0) eslint-plugin-babel: specifier: ^5.3.1 version: 5.3.1(eslint@8.55.0) - eslint-plugin-cypress: - specifier: ^2.12.1 - version: 2.15.1(eslint@8.55.0) eslint-plugin-html: specifier: ^7.1.0 version: 7.1.0 eslint-plugin-import: specifier: ^2.28.0 version: 2.29.0(@typescript-eslint/parser@6.13.2)(eslint@8.55.0) - eslint-plugin-jest: - specifier: ^26.1.5 - version: 26.9.0(@typescript-eslint/eslint-plugin@6.13.2)(eslint@8.55.0)(jest@29.7.0)(typescript@5.3.3) eslint-plugin-jsx-a11y: specifier: ^6.7.1 version: 6.8.0(eslint@8.55.0) eslint-plugin-node: specifier: ^11.1.0 version: 11.1.0(eslint@8.55.0) - eslint-plugin-prettier: - specifier: ^5.0.0 - version: 5.0.1(eslint-config-prettier@9.1.0)(eslint@8.55.0)(prettier@3.1.0) eslint-plugin-react: specifier: ^7.33.2 version: 7.33.2(eslint@8.55.0) @@ -238,6 +226,9 @@ importers: '@types/koa-bodyparser': specifier: ^4.3.12 version: 4.3.12 + tsx: + specifier: ^4.7.0 + version: 4.7.0 typescript: specifier: ^5.2.2 version: 5.3.3 @@ -612,6 +603,213 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} + /@esbuild/aix-ppc64@0.19.11: + resolution: {integrity: sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.19.11: + resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.19.11: + resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.19.11: + resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.19.11: + resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.19.11: + resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.19.11: + resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.19.11: + resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.19.11: + resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.19.11: + resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.19.11: + resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.19.11: + resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.19.11: + resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.19.11: + resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.19.11: + resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.19.11: + resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.19.11: + resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.19.11: + resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.19.11: + resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.19.11: + resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.19.11: + resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.19.11: + resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.19.11: + resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.55.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -964,18 +1162,6 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - /@pkgr/utils@2.4.2: - resolution: {integrity: sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dependencies: - cross-spawn: 7.0.3 - fast-glob: 3.3.2 - is-glob: 4.0.3 - open: 9.1.0 - picocolors: 1.0.0 - tslib: 2.6.2 - dev: true - /@polka/url@1.0.0-next.24: resolution: {integrity: sha512-2LuNTFBIO0m7kKIQvvPHN6UE63VjpmL9rnEEaOOaiSPbZK+zUOYIzBAWcED+3XYzhYsd/0mD57VdxAEqqV52CQ==} @@ -1524,14 +1710,6 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@5.62.0: - resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - dev: true - /@typescript-eslint/scope-manager@6.13.2: resolution: {integrity: sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1560,37 +1738,11 @@ packages: - supports-color dev: true - /@typescript-eslint/types@5.62.0: - resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - /@typescript-eslint/types@6.13.2: resolution: {integrity: sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==} engines: {node: ^16.0.0 || >=18.0.0} dev: true - /@typescript-eslint/typescript-estree@5.62.0(typescript@5.3.3): - resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.5.4 - tsutils: 3.21.0(typescript@5.3.3) - typescript: 5.3.3 - transitivePeerDependencies: - - supports-color - dev: true - /@typescript-eslint/typescript-estree@6.13.2(typescript@5.3.3): resolution: {integrity: sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1612,26 +1764,6 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@5.62.0(eslint@8.55.0)(typescript@5.3.3): - resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.55.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.6 - '@typescript-eslint/scope-manager': 5.62.0 - '@typescript-eslint/types': 5.62.0 - '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.3.3) - eslint: 8.55.0 - eslint-scope: 5.1.1 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - /@typescript-eslint/utils@6.13.2(eslint@8.55.0)(typescript@5.3.3): resolution: {integrity: sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==} engines: {node: ^16.0.0 || >=18.0.0} @@ -1651,14 +1783,6 @@ packages: - typescript dev: true - /@typescript-eslint/visitor-keys@5.62.0: - resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.62.0 - eslint-visitor-keys: 3.4.3 - dev: true - /@typescript-eslint/visitor-keys@6.13.2: resolution: {integrity: sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==} engines: {node: ^16.0.0 || >=18.0.0} @@ -2211,11 +2335,6 @@ packages: tweetnacl: 0.14.5 dev: false - /big-integer@1.6.52: - resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} - engines: {node: '>=0.6'} - dev: true - /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} @@ -2224,13 +2343,6 @@ packages: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: false - /bplist-parser@0.2.0: - resolution: {integrity: sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==} - engines: {node: '>= 5.10.0'} - dependencies: - big-integer: 1.6.52 - dev: true - /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -2273,13 +2385,6 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - /bundle-name@3.0.0: - resolution: {integrity: sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==} - engines: {node: '>=12'} - dependencies: - run-applescript: 5.0.0 - dev: true - /bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -2801,24 +2906,6 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - /default-browser-id@3.0.0: - resolution: {integrity: sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==} - engines: {node: '>=12'} - dependencies: - bplist-parser: 0.2.0 - untildify: 4.0.0 - dev: true - - /default-browser@4.0.0: - resolution: {integrity: sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==} - engines: {node: '>=14.16'} - dependencies: - bundle-name: 3.0.0 - default-browser-id: 3.0.0 - execa: 7.2.0 - titleize: 3.0.0 - dev: true - /define-data-property@1.1.1: resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} engines: {node: '>= 0.4'} @@ -2828,11 +2915,6 @@ packages: has-property-descriptors: 1.0.1 dev: true - /define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - dev: true - /define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -3167,6 +3249,37 @@ packages: is-symbol: 1.0.4 dev: true + /esbuild@0.19.11: + resolution: {integrity: sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.11 + '@esbuild/android-arm': 0.19.11 + '@esbuild/android-arm64': 0.19.11 + '@esbuild/android-x64': 0.19.11 + '@esbuild/darwin-arm64': 0.19.11 + '@esbuild/darwin-x64': 0.19.11 + '@esbuild/freebsd-arm64': 0.19.11 + '@esbuild/freebsd-x64': 0.19.11 + '@esbuild/linux-arm': 0.19.11 + '@esbuild/linux-arm64': 0.19.11 + '@esbuild/linux-ia32': 0.19.11 + '@esbuild/linux-loong64': 0.19.11 + '@esbuild/linux-mips64el': 0.19.11 + '@esbuild/linux-ppc64': 0.19.11 + '@esbuild/linux-riscv64': 0.19.11 + '@esbuild/linux-s390x': 0.19.11 + '@esbuild/linux-x64': 0.19.11 + '@esbuild/netbsd-x64': 0.19.11 + '@esbuild/openbsd-x64': 0.19.11 + '@esbuild/sunos-x64': 0.19.11 + '@esbuild/win32-arm64': 0.19.11 + '@esbuild/win32-ia32': 0.19.11 + '@esbuild/win32-x64': 0.19.11 + dev: true + /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -3236,15 +3349,6 @@ packages: object.entries: 1.1.7 dev: true - /eslint-config-prettier@9.1.0(eslint@8.55.0): - resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 8.55.0 - dev: true - /eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} dependencies: @@ -3294,15 +3398,6 @@ packages: eslint-rule-composer: 0.3.0 dev: true - /eslint-plugin-cypress@2.15.1(eslint@8.55.0): - resolution: {integrity: sha512-eLHLWP5Q+I4j2AWepYq0PgFEei9/s5LvjuSqWrxurkg1YZ8ltxdvMNmdSf0drnsNo57CTgYY/NIHHLRSWejR7w==} - peerDependencies: - eslint: '>= 3.2.1' - dependencies: - eslint: 8.55.0 - globals: 13.23.0 - dev: true - /eslint-plugin-es@3.0.1(eslint@8.55.0): resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} engines: {node: '>=8.10.0'} @@ -3355,28 +3450,6 @@ packages: - supports-color dev: true - /eslint-plugin-jest@26.9.0(@typescript-eslint/eslint-plugin@6.13.2)(eslint@8.55.0)(jest@29.7.0)(typescript@5.3.3): - resolution: {integrity: sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 6.13.2(@typescript-eslint/parser@6.13.2)(eslint@8.55.0)(typescript@5.3.3) - '@typescript-eslint/utils': 5.62.0(eslint@8.55.0)(typescript@5.3.3) - eslint: 8.55.0 - jest: 29.7.0(@types/node@20.10.4)(ts-node@10.9.2) - transitivePeerDependencies: - - supports-color - - typescript - dev: true - /eslint-plugin-jsx-a11y@6.8.0(eslint@8.55.0): resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} engines: {node: '>=4.0'} @@ -3417,27 +3490,6 @@ packages: semver: 6.3.1 dev: true - /eslint-plugin-prettier@5.0.1(eslint-config-prettier@9.1.0)(eslint@8.55.0)(prettier@3.1.0): - resolution: {integrity: sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - '@types/eslint': '>=8.0.0' - eslint: '>=8.0.0' - eslint-config-prettier: '*' - prettier: '>=3.0.0' - peerDependenciesMeta: - '@types/eslint': - optional: true - eslint-config-prettier: - optional: true - dependencies: - eslint: 8.55.0 - eslint-config-prettier: 9.1.0(eslint@8.55.0) - prettier: 3.1.0 - prettier-linter-helpers: 1.0.0 - synckit: 0.8.6 - dev: true - /eslint-plugin-react-hooks@4.6.0(eslint@8.55.0): resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} engines: {node: '>=10'} @@ -3640,21 +3692,6 @@ packages: strip-final-newline: 2.0.0 dev: true - /execa@7.2.0: - resolution: {integrity: sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==} - engines: {node: ^14.18.0 || ^16.14.0 || >=18.0.0} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 4.3.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 - dev: true - /exit@0.1.2: resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} engines: {node: '>= 0.8.0'} @@ -3683,10 +3720,6 @@ packages: /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - /fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - dev: true - /fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -3874,6 +3907,12 @@ packages: get-intrinsic: 1.2.2 dev: true + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + /getpass@0.1.7: resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} dependencies: @@ -4178,11 +4217,6 @@ packages: engines: {node: '>=10.17.0'} dev: true - /human-signals@4.3.1: - resolution: {integrity: sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==} - engines: {node: '>=14.18.0'} - dev: true - /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -4331,18 +4365,6 @@ packages: has-tostringtag: 1.0.0 dev: true - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: true - - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dev: true - /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -4375,14 +4397,6 @@ packages: dependencies: is-extglob: 2.1.1 - /is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - dependencies: - is-docker: 3.0.0 - dev: true - /is-map@2.0.2: resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} dev: true @@ -4464,11 +4478,6 @@ packages: engines: {node: '>=8'} dev: true - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -4511,13 +4520,6 @@ packages: get-intrinsic: 1.2.2 dev: true - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: true - /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} dev: true @@ -5420,11 +5422,6 @@ packages: engines: {node: '>=6'} dev: true - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: true - /min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -5504,13 +5501,6 @@ packages: path-key: 3.1.1 dev: true - /npm-run-path@5.1.0: - resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: true - /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: @@ -5623,27 +5613,10 @@ packages: mimic-fn: 2.1.0 dev: true - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: true - /only@0.0.2: resolution: {integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==} dev: false - /open@9.1.0: - resolution: {integrity: sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==} - engines: {node: '>=14.16'} - dependencies: - default-browser: 4.0.0 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 2.2.0 - dev: true - /opener@1.5.2: resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} hasBin: true @@ -5758,11 +5731,6 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: true - /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -5943,13 +5911,6 @@ packages: engines: {node: '>= 0.8.0'} dev: true - /prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - dependencies: - fast-diff: 1.3.0 - dev: true - /prettier@3.1.0: resolution: {integrity: sha512-TQLvXjq5IAibjh8EpBIkNKxO749UEWABoiIZehEPiY4GNpVdhaFKqSTu+QrlU6D2dPAfubRmtJTi4K4YkQ5eXw==} engines: {node: '>=14'} @@ -6195,6 +6156,10 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + /resolve.exports@2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} @@ -6235,13 +6200,6 @@ packages: glob: 7.2.3 dev: true - /run-applescript@5.0.0: - resolution: {integrity: sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==} - engines: {node: '>=12'} - dependencies: - execa: 5.1.1 - dev: true - /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -6589,11 +6547,6 @@ packages: engines: {node: '>=6'} dev: true - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: true - /strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -6661,14 +6614,6 @@ packages: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true - /synckit@0.8.6: - resolution: {integrity: sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA==} - engines: {node: ^14.18.0 || >=16.0.0} - dependencies: - '@pkgr/utils': 2.4.2 - tslib: 2.6.2 - dev: true - /tailwind-merge@2.1.0: resolution: {integrity: sha512-l11VvI4nSwW7MtLSLYT4ldidDEUwQAMWuSHk7l4zcXZDgnCRa0V3OdCwFfM7DCzakVXMNRwAeje9maFFXT71dQ==} dependencies: @@ -6769,11 +6714,6 @@ packages: any-promise: 1.3.0 dev: true - /titleize@3.0.0: - resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} - engines: {node: '>=12'} - dev: true - /tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -6938,10 +6878,6 @@ packages: strip-bom: 3.0.0 dev: true - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -6950,14 +6886,15 @@ packages: engines: {node: '>=0.6.x'} dev: false - /tsutils@3.21.0(typescript@5.3.3): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + /tsx@4.7.0: + resolution: {integrity: sha512-I+t79RYPlEYlHn9a+KzwrvEwhJg35h/1zHsLC2JXvhC2mdynMv6Zxzvhv5EMV6VF5qJlLlkSnMVvdZV3PSIGcg==} + engines: {node: '>=18.0.0'} + hasBin: true dependencies: - tslib: 1.14.1 - typescript: 5.3.3 + esbuild: 0.19.11 + get-tsconfig: 4.7.2 + optionalDependencies: + fsevents: 2.3.3 dev: true /tunnel-agent@0.6.0: @@ -7066,11 +7003,6 @@ packages: engines: {node: '>= 0.8'} dev: false - /untildify@4.0.0: - resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} - engines: {node: '>=8'} - dev: true - /update-browserslist-db@1.0.13(browserslist@4.22.2): resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} hasBin: true diff --git a/tsconfig.json b/tsconfig.json index b0edc2b6..c3ffe94d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -26,6 +26,6 @@ "@/hooks/*": ["./hooks/*"] } }, - "include": ["./src/**/*", "local-signature/**/*", "./jest.config.ts", "./jest.setup.ts"], + "include": ["./src/**/*", "./jest.config.ts", "./jest.setup.ts"], "exclude": ["dist", "dev", "temp"] }