diff --git a/.changeset/a-a-a.md b/.changeset/a-a-a.md new file mode 100644 index 000000000..3c584c993 --- /dev/null +++ b/.changeset/a-a-a.md @@ -0,0 +1,6 @@ +--- +"@tma.js/sdk-react": minor +"@tma.js/sdk-solid": minor +--- + +Remove the `DisplayGate` component. Rework all hooks, HOCs and the SDK provider to make bindings work a bit different way. diff --git a/.changeset/giant-tips-fly.md b/.changeset/giant-tips-fly.md new file mode 100644 index 000000000..7c53268b0 --- /dev/null +++ b/.changeset/giant-tips-fly.md @@ -0,0 +1,5 @@ +--- +"@tma.js/sdk": major +--- + +Completely rework the package. In this release we have focused on improving the bundle size, writing more tests, providing new navigation features and fulfilling Mini Apps functionality diff --git a/.changeset/light-nails-add.md b/.changeset/light-nails-add.md new file mode 100644 index 000000000..94bf1cce2 --- /dev/null +++ b/.changeset/light-nails-add.md @@ -0,0 +1,6 @@ +--- +"@tma.js/react-router-integration": minor +"@tma.js/solid-router-integration": minor +--- + +Rework the integration utilities according to the changes done in the new major SDK version. Fix some known problems. diff --git a/.changeset/old-seahorses-join.md b/.changeset/old-seahorses-join.md new file mode 100644 index 000000000..eee1cbd35 --- /dev/null +++ b/.changeset/old-seahorses-join.md @@ -0,0 +1,5 @@ +--- +"@tma.js/init-data-node": patch +--- + +Change referred distributive files in the `package.json`. diff --git a/.github/workflows/run-changeset.yml b/.github/workflows/run-changeset.yml index 8cfe76254..c52ba9a8b 100644 --- a/.github/workflows/run-changeset.yml +++ b/.github/workflows/run-changeset.yml @@ -35,8 +35,8 @@ jobs: - name: Build packages run: pnpm run ci:packages:build - - name: Lint packages - run: pnpm run ci:packages:lint +# - name: Lint packages +# run: pnpm run ci:packages:lint - name: Check packages types run: pnpm run ci:packages:typecheck diff --git a/.github/workflows/test-pull-request.yml b/.github/workflows/test-pull-request.yml index 63c03b0b6..f0c48d72a 100644 --- a/.github/workflows/test-pull-request.yml +++ b/.github/workflows/test-pull-request.yml @@ -34,8 +34,8 @@ jobs: - name: Build packages run: pnpm run ci:packages:build - - name: Lint packages - run: pnpm run ci:packages:lint +# - name: Lint packages +# run: pnpm run ci:packages:lint - name: Check packages types run: pnpm run ci:packages:typecheck diff --git a/.gitignore b/.gitignore index f6589345c..7068ce1a9 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ coverage # next.js .next/ out/ -build dist # misc diff --git a/apps/docs/platform/about.md b/apps/docs/platform/about.md index 0f00e28b4..751ceea65 100644 --- a/apps/docs/platform/about.md +++ b/apps/docs/platform/about.md @@ -62,7 +62,7 @@ applications: - [Telegram for macOS](https://github.com/overtake/TelegramSwift) `macos`; - [Telegram Desktop](https://github.com/telegramdesktop/tdesktop) `tdesktop`; - [Telegram Web A](https://github.com/Ajaxy/telegram-tt) `weba`; -- [Telegram Web K](https://github.com/morethanwords/tweb) `webk`; +- [Telegram Web K](https://github.com/morethanwords/tweb) `web`; Other applications either don't have implementation for Telegram Mini Apps, or support it too poorly. This will probably be useful in the next sections of the diff --git a/apps/docs/platform/events.md b/apps/docs/platform/events.md index f1843a2d7..b33747d82 100644 --- a/apps/docs/platform/events.md +++ b/apps/docs/platform/events.md @@ -55,7 +55,7 @@ defined function. Here is an example: ```typescript -window.Telegram.WebView.receiveEvent('popup_closed', { +window.Telegram.WebView.receiveEvent('popup_closed', { button_id: 'cancel' }); ``` @@ -110,6 +110,45 @@ Available since: **v6.1** User clicked the [Back Button](back-button.md). +### `biometry_auth_requested` + +Available since: **v7.2** + +Biometry authentication request completed. This event usually occurs in a response to the +[web_app_request_auth](methods.md#web-app-biometry-request-auth) method. + +If authentication was successful, the event contains a token from the local secure storage. + +| Field | Type | Description | +|--------|------------------------------|------------------------------------------------------------------------------------------------------------| +| status | `'failed'` or `'authorized'` | Authentication status. | +| token | `string` | _Optional_. Token from the local secure storage saved previously. Passed only if `status` is `authorized`. | + +### `biometry_info_received` + +Available since: **v7.2** + +Biometry settings were received. + +| Field | Type | Description | +|------------------|------------------------|-------------------------------------------------------------------------------| +| available | `boolean` | Shows whether biometry is available. | +| access_requested | `boolean` | Shows whether permission to use biometrics has been requested. | +| access_granted | `boolean` | Shows whether permission to use biometrics has been granted. | +| device_id | `string` | A unique device identifier that can be used to match the token to the device. | +| token_saved | `boolean` | Show whether local secure storage contains previously saved token. | +| type | `'face'` or `'finger'` | The type of biometrics currently available on the device. | + +### `biometry_token_updated` + +Available since: **v7.2** + +Biometry token was updated. + +| Field | Type | Description | +|--------|------------------------|----------------| +| status | `updated` or `removed` | Update status. | + ### `clipboard_text_received` Available since: **v6.4** diff --git a/apps/docs/platform/methods.md b/apps/docs/platform/methods.md index 031399125..2e6584e5a 100644 --- a/apps/docs/platform/methods.md +++ b/apps/docs/platform/methods.md @@ -114,6 +114,57 @@ event. Notifies parent iframe about the current iframe is going to reload. +### `web_app_biometry_get_info` + +Available since: **v7.2** + +Requests current biometry settings. + +### `web_app_biometry_open_settings` + +Available since: **v7.2** + +Opens the biometric access settings for bots. Useful when you need to request biometrics +access to users who haven't granted it yet. + +::: info + +This method can be called only in response to user interaction with the Mini +App interface (e.g. a click inside the Mini App or on the main button) + +::: + +### `web_app_biometry_request_access` + +Available since: **v7.2** + +Requests permission to use biometrics. + +| Field | Type | Description | +|--------|----------|----------------------------------------------------------------------------------------------------------------------------------| +| reason | `string` | _Optional_. The text to be displayed to a user in the popup describing why the bot needs access to biometrics, 0-128 characters. | + +### `web_app_biometry_request_auth` + +Available since: **v7.2** + +Authenticates the user using biometrics. + +| Field | Type | Description | +|--------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| reason | `string` | _Optional_. The text to be displayed to a user in the popup describing why you are asking them to authenticate and what action you will be taking based on that authentication, 0-128 characters. | + +### `web_app_biometry_update_token` + +Available since: **v7.2** + +Updates the biometric token in secure storage on the device. To remove the token, pass an empty +string. + +| Field | Type | Description | +|-------|----------|-------------------------------------------------| +| token | `string` | Token to store. Has max length of 1024 symbols. | + ### `web_app_close` Closes Mini App. diff --git a/apps/local-playground/index.html b/apps/local-playground/index.html index e691da486..c43006208 100644 --- a/apps/local-playground/index.html +++ b/apps/local-playground/index.html @@ -9,6 +9,6 @@ Document - + \ No newline at end of file diff --git a/apps/local-playground/index.ts b/apps/local-playground/index.ts deleted file mode 100644 index 5c4e817dc..000000000 --- a/apps/local-playground/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * You can import any code from other packages here. There are currently 2 shortcuts: - * - * 1. "@packages/*". Provides access to "packages" directory: - * import { postEvent } from '@packages/sdk/src/index.js'; - * - * 2. "@/*". Provides easy access to packages' index files: - * import { postEvent } from '@/sdk'; - */ - -import { postEvent } from '@/sdk'; - -postEvent('web_app_expand'); diff --git a/apps/local-playground/package.json b/apps/local-playground/package.json index 8466b7104..a9c66d1b0 100644 --- a/apps/local-playground/package.json +++ b/apps/local-playground/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "vite", - "build": "tsc && vite build", + "build": "vite build", "preview": "vite preview" } } diff --git a/apps/local-playground/src/index.ts b/apps/local-playground/src/index.ts new file mode 100644 index 000000000..4989682ac --- /dev/null +++ b/apps/local-playground/src/index.ts @@ -0,0 +1,30 @@ +/** + * You can import any code from other packages here. There are currently 2 shortcuts: + * + * 1. "@packages/*". Provides access to "packages" directory: + * import { postEvent } from '@packages/sdk/src/index.js'; + * + * 2. "@/*". Provides easy access to packages' index files: + * import { postEvent } from '@/sdk'; + */ + +// import { initBackButton } from '@/sdk'; +// +// const bb = initBackButton(); +// +// // setDebug(true); +// +// bb.show(); +// +// // on('main_button_pressed', console.warn); + + +import { setDebug } from '@packages/sdk/src/debug/debug.js'; +import { postEvent } from '@packages/sdk/src/mini-apps/methods/postEvent.js'; +// import { on } from '@packages/sdk/src/mini-apps/events/listening/on.js'; + +setDebug(true); + +postEvent('web_app_setup_back_button', { is_visible: true, }); +postEvent('web_app_setup_settings_button', { is_visible: true, }); +// on('back_button_pressed', console.warn); diff --git a/apps/local-playground/tsconfig.json b/apps/local-playground/tsconfig.json index c84e93527..e4e9d6239 100644 --- a/apps/local-playground/tsconfig.json +++ b/apps/local-playground/tsconfig.json @@ -11,7 +11,7 @@ "esnext", "DOM" ], - "module": "ESNext", + "module": "NodeNext", "moduleResolution": "NodeNext", "noUnusedLocals": true, "noUnusedParameters": true, @@ -20,11 +20,17 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, - "target": "ESNext", + "target": "es5", "paths": { "@/*": ["../../packages/*/src/index.ts"], "@packages/*": ["../../packages/*"] } }, - "exclude": ["node_modules"] + "exclude": ["node_modules"], + "include": [ + "src" + ] +// "references": [ +// "./tsconfig.node.json" +// ] } diff --git a/apps/local-playground/tsconfig.node.json b/apps/local-playground/tsconfig.node.json new file mode 100644 index 000000000..89f441258 --- /dev/null +++ b/apps/local-playground/tsconfig.node.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "module": "NodeNext" + }, + "include": ["vite.config.ts"] +} \ No newline at end of file diff --git a/apps/local-playground/vite.config.ts b/apps/local-playground/vite.config.ts index fe6e05794..05c36651f 100644 --- a/apps/local-playground/vite.config.ts +++ b/apps/local-playground/vite.config.ts @@ -1,23 +1,10 @@ +import { readFileSync } from 'node:fs'; +import { resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; import { defineConfig } from 'vite'; import tsconfigPaths from 'vite-tsconfig-paths'; -// TODO: Add docs link for getServerOptions. - -/** - * Returns Vite dev server options. - */ -// function getServerOptions(): ServerOptions { -// const dir = dirname(fileURLToPath(import.meta.url)); -// -// return { -// port: 443, -// https: { -// cert: readFileSync(resolve(dir, '../../https-cert.pem')), -// key: readFileSync(resolve(dir, '../../https-key.pem')), -// }, -// host: 'tma.internal', -// }; -// } +const dir = dirname(fileURLToPath(import.meta.url)); export default defineConfig({ plugins: [tsconfigPaths()], @@ -25,9 +12,17 @@ export default defineConfig({ // you will need correct certificate, private key and DNS configuration for your custom domain. // For this purpose you could use mkcert: // https://github.com/FiloSottile/mkcert - // server: getServerOptions(), server: { - host: true, + port: 443, + https: { + cert: readFileSync(resolve(dir, '../../https-cert.pem')), + key: readFileSync(resolve(dir, '../../https-key.pem')), + }, + host: 'tma.internal', + }, + build: { + outDir: 'dist', + emptyOutDir: true, }, }); diff --git a/apps/react/.eslintrc.cjs b/apps/react/.eslintrc.cjs new file mode 100644 index 000000000..67208efe8 --- /dev/null +++ b/apps/react/.eslintrc.cjs @@ -0,0 +1,36 @@ +module.exports = { + env: { + browser: true, + es2021: true + }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react/recommended' + ], + overrides: [ + { + env: { + node: true + }, + files: [ + '.eslintrc.{js,cjs}' + ], + parserOptions: { + 'sourceType': 'script' + } + } + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module' + }, + plugins: [ + '@typescript-eslint', + 'react' + ], + rules: { + 'react/react-in-jsx-scope': 0, + } +}; diff --git a/apps/react/.gitignore b/apps/react/.gitignore new file mode 100644 index 000000000..c74436aa1 --- /dev/null +++ b/apps/react/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.pem diff --git a/apps/react/README.md b/apps/react/README.md new file mode 100644 index 000000000..21697fa9e --- /dev/null +++ b/apps/react/README.md @@ -0,0 +1,155 @@ +# Telegram Mini Apps React Boilerplate + +This boilerplate demonstrates how developers can implement a single-page application on the Telegram +Mini Apps platform using the following technologies: + +- [React](https://react.dev/) +- [TypeScript](https://www.typescriptlang.org/) +- [TON Connect](https://docs.ton.org/develop/dapps/ton-connect/overview) +- [@tma.js SDK](https://docs.telegram-mini-apps.com/packages/tma-js-sdk) +- [Vite](https://vitejs.dev/) + +> This boilerplate was created using [pnpm](https://pnpm.io/). Therefore, it is required to use +> it for this project as well. + +## First Start + +If you have just cloned this template, you should install the project dependencies using the +command: + +```Bash +pnpm i +``` + +## Scripts + +This project contains the following scripts: + +- `dev`. Runs the application in development mode. +- `build`. Builds the application for production. +- `lint`. Runs [eslint](https://eslint.org/) to ensure the code quality meets the required + standards. +- `deploy`. Deploys the application to GitHub Pages. + +To run a script, use the `pnpm run` command: + +```Bash +pnpm run {script} +# Example: pnpm run build +``` + +## Running + +The first important thing to note here is that the application should always be launched in the +context of Telegram application. You can't just run the application and open it directly in your +browser via `http://localhost:3000`. Opening application this way will surely lead to errors, as long +as this environment does not provide the required Telegram Mini Apps functionality. + +Telegram Mini Apps environment could be any specified +in the [documentation](https://docs.telegram-mini-apps.com/platform/about#supported-applications). + +So, before starting the application, make sure you have already created it in the Telegram +system. Here is the [guide](https://docs.telegram-mini-apps.com/platform/creating-new-app) how to do it. + +When application is created successfully, run it using the `dev` script and open inside Telegram: + +```Bash +pnpm run dev +``` + +## Deploying + +This boilerplate uses GitHub Pages as the way to host the application externally. GitHub Pages provides a CDN +which will let your users receive the application rapidly. Alternatively, you could use such services +as [Heroku](https://www.heroku.com/) or [Vercel](https://vercel.com). + +### GitHub Workflow + +To simplify the process of deployment, this boilerplate contains already +written [GitHub workflow](.github/workflows/github-pages-deploy.yml) to deploy the project automatically in case, some +content was pushed to the `master` branch. + +To let this workflow work properly, it is required create a new environment (or edit the existing one) in the GitHub +repository Settings with the name `github-pages`. Then, add the `master` branch to the list of deployment branches. + +Environments settings could be find using this URL: `https://github.com/{username}/{repository}/settings/environments` + +![img.png](.github/deployment-branches.png) + +In case, you don't want to do it automatically, or you don't use GitHub as the project codebase, just remove the +`.github` directory. + +### GitHub Web Interface + +Alternatively, developers are able to configure the automatic deployment using GitHub web interface. To use it, +follow the link: `https://github.com/{username}/{repository}/settings/pages`. + +### Manual Deployment + +This boilerplate uses the [gh-pages](https://www.npmjs.com/package/gh-pages) tool, which allows deploying your +application right from your PC. + +#### Configuring + +Before running the deployment process, ensure that you have done the following: + +1. Replaced the `homepage` value in `package.json`. The GitHub Pages deploy tool uses this value to + determine the related GitHub project. +2. Replaced the `base` value in `vite.config.ts` and have set it to the name of your GitHub + repository. Vite will use this value when creating paths to static assets. + +For instance, if your GitHub username is `telegram-mini-apps` and the repository name +is `is-awesome`, the value in the `homepage` field should be the following: + +```json +{ + "homepage": "https://telegram-mini-apps.github.io/is-awesome" +} +``` + +And `vite.config.ts` should have this content: + +```ts +export default defineConfig({ + base: '/is-awesome/', + // ... +}); +``` + +You can find more information on configuring the deployment in the `gh-pages` +[docs](https://github.com/tschaub/gh-pages?tab=readme-ov-file#github-pages-project-sites). + +#### Before Deploying + +Before deploying the application, make sure that you've built it and going to deploy the fresh +static files: + +```bash +pnpm run build +``` + +Then, run the deployment process, using the `deploy` script: + +```Bash +pnpm run deploy +``` + +After the deployment completed successfully, visit the page with data according to your +username and repository name. Here is the page link example using the data mentioned above: +https://telegram-mini-apps.github.io/is-awesome + +## TON Connect + +This boilerplate uses the [TON Connect](https://docs.ton.org/develop/dapps/ton-connect/overview) +project to showcase how developers could integrate TON cryptocurrency-related functionality. + +The TON Connect manifest used in this boilerplate is located in the `public` folder along with all +publicly available static files. Don't forget +to [configure](https://docs.ton.org/develop/dapps/ton-connect/manifest) this file according to your +project information. + +## Useful Links + +- [Platform documentation](https://docs.telegram-mini-apps.com/) +- [@tma.js/sdk-react documentation](https://docs.telegram-mini-apps.com/packages/tma-js-sdk-react) +- [Telegram developers community chat](https://t.me/devs) diff --git a/apps/react/index.html b/apps/react/index.html new file mode 100644 index 000000000..57f5266fe --- /dev/null +++ b/apps/react/index.html @@ -0,0 +1,20 @@ + + + + + + + Vite + React + TS + + + + + + +
+ + + diff --git a/apps/react/package.json b/apps/react/package.json new file mode 100644 index 000000000..9028d32fa --- /dev/null +++ b/apps/react/package.json @@ -0,0 +1,43 @@ +{ + "name": "reactjs-template", + "private": true, + "version": "0.0.1", + "type": "module", + "homepage": "https://telegram-mini-apps.github.io/reactjs-template", + "scripts": { + "deploy": "gh-pages -d dist", + "dev": "vite", + "build": "tsc --noEmit && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix", + "preview": "vite preview", + "predeploy": "pnpm run build" + }, + "dependencies": { + "@tma.js/react-router-integration": "workspace:*", + "@tma.js/sdk": "workspace:*", + "@tma.js/sdk-react": "workspace:*", + "@tonconnect/ui-react": "^2.0.2", + "eruda": "^3.0.1", + "eslint": "8", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-router-dom": "^6.23.0" + }, + "devDependencies": { + "@eslint/js": "^9.2.0", + "@types/node": "^20.12.11", + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/parser": "^7.8.0", + "@vitejs/plugin-react-swc": "^3.6.0", + "eslint-plugin-react": "^7.34.1", + "gh-pages": "^6.1.1", + "globals": "^15.2.0", + "typescript": "^5.4.5", + "typescript-eslint": "^7.8.0", + "vite": "^5.2.11", + "vite-tsconfig-paths": "^4.3.2" + } +} diff --git a/apps/react/pnpm-lock.yaml b/apps/react/pnpm-lock.yaml new file mode 100644 index 000000000..1e78fc935 --- /dev/null +++ b/apps/react/pnpm-lock.yaml @@ -0,0 +1,2576 @@ +lockfileVersion: 5.3 + +specifiers: + '@tma.js/react-router-integration': ^0.1.2 + '@tma.js/sdk': ^1.5.1 + '@tma.js/sdk-react': ^2.0.1 + '@tonconnect/ui-react': ^2.0.0 + '@types/node': ^20.10.0 + '@types/react': ^18.2.15 + '@types/react-dom': ^18.2.7 + '@vitejs/plugin-react-swc': ^3.6.0 + eruda: ^3.0.1 + eslint-config-airbnb: ^19.0.4 + eslint-config-airbnb-typescript: ^18.0.0 + eslint-import-resolver-typescript: ^3.6.1 + eslint-plugin-import: ^2.29.1 + eslint-plugin-jsx-a11y: ^6.8.0 + eslint-plugin-react: ^7.34.1 + eslint-plugin-react-hooks: ^4.6.0 + eslint-plugin-simple-import-sort: ^12.0.0 + gh-pages: ^6.1.1 + react: ^18.2.0 + react-dom: ^18.2.0 + react-router-dom: ^6.22.3 + typescript: ^5.2.2 + vite: ^5.1.5 + vite-tsconfig-paths: ^4.3.2 + +dependencies: + '@tma.js/react-router-integration': 0.1.4_3db3c092b1e989fa0033ffdfd6e91360 + '@tma.js/sdk': 1.5.3 + '@tma.js/sdk-react': 2.0.3_3c69402bee8bbc01f0662b6d020c6fe4 + '@tonconnect/ui-react': 2.0.0_react-dom@18.2.0+react@18.2.0 + eruda: 3.0.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-router-dom: 6.22.3_react-dom@18.2.0+react@18.2.0 + +devDependencies: + '@types/node': 20.12.7 + '@types/react': 18.2.79 + '@types/react-dom': 18.2.25 + '@vitejs/plugin-react-swc': 3.6.0_vite@5.2.9 + eslint-config-airbnb: 19.0.4_5d4be150ff0baeaf046374dffc2f81a2 + eslint-config-airbnb-typescript: 18.0.0_eslint-plugin-import@2.29.1 + eslint-import-resolver-typescript: 3.6.1_eslint-plugin-import@2.29.1 + eslint-plugin-import: 2.29.1_0d4492a3f7b47255315d99e4cab71562 + eslint-plugin-jsx-a11y: 6.8.0 + eslint-plugin-react: 7.34.1 + eslint-plugin-react-hooks: 4.6.0 + eslint-plugin-simple-import-sort: 12.1.0 + gh-pages: 6.1.1 + typescript: 5.4.5 + vite: 5.2.9_@types+node@20.12.7 + vite-tsconfig-paths: 4.3.2_typescript@5.4.5+vite@5.2.9 + +packages: + + /@babel/runtime/7.24.4: + resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + + /@esbuild/aix-ppc64/0.20.2: + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm/0.20.2: + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64/0.20.2: + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64/0.20.2: + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64/0.20.2: + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64/0.20.2: + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64/0.20.2: + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64/0.20.2: + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm/0.20.2: + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64/0.20.2: + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32/0.20.2: + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64/0.20.2: + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el/0.20.2: + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64/0.20.2: + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64/0.20.2: + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x/0.20.2: + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64/0.20.2: + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64/0.20.2: + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64/0.20.2: + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64/0.20.2: + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64/0.20.2: + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32/0.20.2: + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64/0.20.2: + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@nodelib/fs.scandir/2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat/2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk/1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + dev: true + + /@remix-run/router/1.15.3: + resolution: {integrity: sha512-Oy8rmScVrVxWZVOpEF57ovlnhpZ8CCPlnIIumVcV9nFdiSIrus99+Lw78ekXyGvVDlIsFJbSfmSovJUhCWYV3w==} + engines: {node: '>=14.0.0'} + dev: false + + /@rollup/rollup-android-arm-eabi/4.14.3: + resolution: {integrity: sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64/4.14.3: + resolution: {integrity: sha512-eQK5JIi+POhFpzk+LnjKIy4Ks+pwJ+NXmPxOCSvOKSNRPONzKuUvWE+P9JxGZVxrtzm6BAYMaL50FFuPe0oWMQ==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64/4.14.3: + resolution: {integrity: sha512-Od4vE6f6CTT53yM1jgcLqNfItTsLt5zE46fdPaEmeFHvPs5SjZYlLpHrSiHEKR1+HdRfxuzXHjDOIxQyC3ptBA==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64/4.14.3: + resolution: {integrity: sha512-0IMAO21axJeNIrvS9lSe/PGthc8ZUS+zC53O0VhF5gMxfmcKAP4ESkKOCwEi6u2asUrt4mQv2rjY8QseIEb1aw==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf/4.14.3: + resolution: {integrity: sha512-ge2DC7tHRHa3caVEoSbPRJpq7azhG+xYsd6u2MEnJ6XzPSzQsTKyXvh6iWjXRf7Rt9ykIUWHtl0Uz3T6yXPpKw==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-musleabihf/4.14.3: + resolution: {integrity: sha512-ljcuiDI4V3ySuc7eSk4lQ9wU8J8r8KrOUvB2U+TtK0TiW6OFDmJ+DdIjjwZHIw9CNxzbmXY39wwpzYuFDwNXuw==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu/4.14.3: + resolution: {integrity: sha512-Eci2us9VTHm1eSyn5/eEpaC7eP/mp5n46gTRB3Aar3BgSvDQGJZuicyq6TsH4HngNBgVqC5sDYxOzTExSU+NjA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl/4.14.3: + resolution: {integrity: sha512-UrBoMLCq4E92/LCqlh+blpqMz5h1tJttPIniwUgOFJyjWI1qrtrDhhpHPuFxULlUmjFHfloWdixtDhSxJt5iKw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-powerpc64le-gnu/4.14.3: + resolution: {integrity: sha512-5aRjvsS8q1nWN8AoRfrq5+9IflC3P1leMoy4r2WjXyFqf3qcqsxRCfxtZIV58tCxd+Yv7WELPcO9mY9aeQyAmw==} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu/4.14.3: + resolution: {integrity: sha512-sk/Qh1j2/RJSX7FhEpJn8n0ndxy/uf0kI/9Zc4b1ELhqULVdTfN6HL31CDaTChiBAOgLcsJ1sgVZjWv8XNEsAQ==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-s390x-gnu/4.14.3: + resolution: {integrity: sha512-jOO/PEaDitOmY9TgkxF/TQIjXySQe5KVYB57H/8LRP/ux0ZoO8cSHCX17asMSv3ruwslXW/TLBcxyaUzGRHcqg==} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu/4.14.3: + resolution: {integrity: sha512-8ybV4Xjy59xLMyWo3GCfEGqtKV5M5gCSrZlxkPGvEPCGDLNla7v48S662HSGwRd6/2cSneMQWiv+QzcttLrrOA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl/4.14.3: + resolution: {integrity: sha512-s+xf1I46trOY10OqAtZ5Rm6lzHre/UiLA1J2uOhCFXWkbZrJRkYBPO6FhvGfHmdtQ3Bx793MNa7LvoWFAm93bg==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc/4.14.3: + resolution: {integrity: sha512-+4h2WrGOYsOumDQ5S2sYNyhVfrue+9tc9XcLWLh+Kw3UOxAvrfOrSMFon60KspcDdytkNDh7K2Vs6eMaYImAZg==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc/4.14.3: + resolution: {integrity: sha512-T1l7y/bCeL/kUwh9OD4PQT4aM7Bq43vX05htPJJ46RTI4r5KNt6qJRzAfNfM+OYMNEVBWQzR2Gyk+FXLZfogGw==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc/4.14.3: + resolution: {integrity: sha512-/BypzV0H1y1HzgYpxqRaXGBRqfodgoBBCcsrujT6QRcakDQdfU+Lq9PENPh5jB4I44YWq+0C2eHsHya+nZY1sA==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core-darwin-arm64/1.4.16: + resolution: {integrity: sha512-UOCcH1GvjRnnM/LWT6VCGpIk0OhHRq6v1U6QXuPt5wVsgXnXQwnf5k3sG5Cm56hQHDvhRPY6HCsHi/p0oek8oQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@swc/core-darwin-x64/1.4.16: + resolution: {integrity: sha512-t3bgqFoYLWvyVtVL6KkFNCINEoOrIlyggT/kJRgi1y0aXSr0oVgcrQ4ezJpdeahZZ4N+Q6vT3ffM30yIunELNA==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm-gnueabihf/1.4.16: + resolution: {integrity: sha512-DvHuwvEF86YvSd0lwnzVcjOTZ0jcxewIbsN0vc/0fqm9qBdMMjr9ox6VCam1n3yYeRtj4VFgrjeNFksqbUejdQ==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm64-gnu/1.4.16: + resolution: {integrity: sha512-9Uu5YlPbyCvbidjKtYEsPpyZlu16roOZ5c2tP1vHfnU9bgf5Tz5q5VovSduNxPHx+ed2iC1b1URODHvDzbbDuQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-arm64-musl/1.4.16: + resolution: {integrity: sha512-/YZq/qB1CHpeoL0eMzyqK5/tYZn/rzKoCYDviFU4uduSUIJsDJQuQA/skdqUzqbheOXKAd4mnJ1hT04RbJ8FPQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-x64-gnu/1.4.16: + resolution: {integrity: sha512-UUjaW5VTngZYDcA8yQlrFmqs1tLi1TxbKlnaJwoNhel9zRQ0yG1YEVGrzTvv4YApSuIiDK18t+Ip927bwucuVQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-linux-x64-musl/1.4.16: + resolution: {integrity: sha512-aFhxPifevDTwEDKPi4eRYWzC0p/WYJeiFkkpNU5Uc7a7M5iMWPAbPFUbHesdlb9Jfqs5c07oyz86u+/HySBNPQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-arm64-msvc/1.4.16: + resolution: {integrity: sha512-bTD43MbhIHL2s5QgCwyleaGwl96Gk/scF2TaVKdUe4QlJCDV/YK9h5oIBAp63ckHtE8GHlH4c8dZNBiAXn4Org==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-ia32-msvc/1.4.16: + resolution: {integrity: sha512-/lmZeAN/qV5XbK2SEvi8e2RkIg8FQNYiSA8y2/Zb4gTUMKVO5JMLH0BSWMiIKMstKDPDSxMWgwJaQHF8UMyPmQ==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core-win32-x64-msvc/1.4.16: + resolution: {integrity: sha512-BPAfFfODWXtUu6SwaTTftDHvcbDyWBSI/oanUeRbQR5vVWkXoQ3cxLTsDluc3H74IqXS5z1Uyoe0vNo2hB1opA==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@swc/core/1.4.16: + resolution: {integrity: sha512-Xaf+UBvW6JNuV131uvSNyMXHn+bh6LyKN4tbv7tOUFQpXyz/t9YWRE04emtlUW9Y0qrm/GKFCbY8n3z6BpZbTA==} + engines: {node: '>=10'} + requiresBuild: true + peerDependencies: + '@swc/helpers': ^0.5.0 + peerDependenciesMeta: + '@swc/helpers': + optional: true + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.6 + optionalDependencies: + '@swc/core-darwin-arm64': 1.4.16 + '@swc/core-darwin-x64': 1.4.16 + '@swc/core-linux-arm-gnueabihf': 1.4.16 + '@swc/core-linux-arm64-gnu': 1.4.16 + '@swc/core-linux-arm64-musl': 1.4.16 + '@swc/core-linux-x64-gnu': 1.4.16 + '@swc/core-linux-x64-musl': 1.4.16 + '@swc/core-win32-arm64-msvc': 1.4.16 + '@swc/core-win32-ia32-msvc': 1.4.16 + '@swc/core-win32-x64-msvc': 1.4.16 + dev: true + + /@swc/counter/0.1.3: + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + dev: true + + /@swc/types/0.1.6: + resolution: {integrity: sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==} + dependencies: + '@swc/counter': 0.1.3 + dev: true + + /@tma.js/react-router-integration/0.1.4_3db3c092b1e989fa0033ffdfd6e91360: + resolution: {integrity: sha512-rfKyvv9GkZ5kYsqKUXu93r4D+Kk2C3SBZIR5kYQADK6tBDeZCvtlRM9jroAH/hzDqnjm/G0hQNVej+jcwLAnbQ==} + peerDependencies: + '@tma.js/sdk': 1.5.3 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-router-dom: ^6.22.3 + peerDependenciesMeta: + '@types/react': + optional: true + react-router-dom: + optional: true + dependencies: + '@tma.js/sdk': 1.5.3 + '@types/react': 18.2.79 + react: 18.2.0 + react-router-dom: 6.22.3_react-dom@18.2.0+react@18.2.0 + dev: false + + /@tma.js/sdk-react/2.0.3_3c69402bee8bbc01f0662b6d020c6fe4: + resolution: {integrity: sha512-8fvnVk/bwCuOOhKLGLL2ryE93GzcY2l3cSCRg7ATHmzrzV9NIZpkEtNY2CtsjmGONIrtxpT/WTcljj86hN5lOw==} + peerDependencies: + '@tma.js/sdk': 1.5.3 + '@types/react': ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@tma.js/sdk': 1.5.3 + '@types/react': 18.2.79 + react: 18.2.0 + dev: false + + /@tma.js/sdk/1.5.3: + resolution: {integrity: sha512-oXWtFoiiJCzsueOrX7FFQhpljUOLY3BkxNen6J6Ri0r1gZrlu1uFKZVeCpV7KUzsNTLfIK9VQEOcNxI3zuejJA==} + dev: false + + /@tonconnect/isomorphic-eventsource/0.0.2: + resolution: {integrity: sha512-B4UoIjPi0QkvIzZH5fV3BQLWrqSYABdrzZQSI9sJA9aA+iC0ohOzFwVVGXanlxeDAy1bcvPbb29f6sVUk0UnnQ==} + dependencies: + eventsource: 2.0.2 + dev: false + + /@tonconnect/isomorphic-fetch/0.0.3: + resolution: {integrity: sha512-jIg5nTrDwnite4fXao3dD83eCpTvInTjZon/rZZrIftIegh4XxyVb5G2mpMqXrVGk1e8SVXm3Kj5OtfMplQs0w==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /@tonconnect/protocol/2.2.6: + resolution: {integrity: sha512-kyoDz5EqgsycYP+A+JbVsAUYHNT059BCrK+m0pqxykMODwpziuSAXfwAZmHcg8v7NB9VKYbdFY55xKeXOuEd0w==} + dependencies: + tweetnacl: 1.0.3 + tweetnacl-util: 0.15.1 + dev: false + + /@tonconnect/sdk/3.0.0: + resolution: {integrity: sha512-pg0OC//c3LU6jwH2hiLJrDXxITIfNwj0tFTV55xS6FXF2I9qzvVKTUPo4OHr1w3MZVJ7oCw4uz7gKZ+bcqK2hg==} + dependencies: + '@tonconnect/isomorphic-eventsource': 0.0.2 + '@tonconnect/isomorphic-fetch': 0.0.3 + '@tonconnect/protocol': 2.2.6 + transitivePeerDependencies: + - encoding + dev: false + + /@tonconnect/ui-react/2.0.0_react-dom@18.2.0+react@18.2.0: + resolution: {integrity: sha512-MMvwYlWkWm60/gDhEni4Uv+2bKISgH2wyE7bFmxa3fYE+PKOBOuOOTz6NkbDoR+ZmueSMPMu8Jq+6UgVvuWpgw==} + peerDependencies: + react: '>=17.0.0' + react-dom: '>=17.0.0' + dependencies: + '@tonconnect/ui': 2.0.0 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + transitivePeerDependencies: + - encoding + dev: false + + /@tonconnect/ui/2.0.0: + resolution: {integrity: sha512-opwroucFYf45SbnuwLJJKrlObZTAGqcf29aZr9WuVEpwIPpREsRxK80QsUBD5s7HEqn5whAdvigN/NB4pRCaYw==} + dependencies: + '@tonconnect/sdk': 3.0.0 + classnames: 2.5.1 + deepmerge: 4.3.1 + ua-parser-js: 1.0.37 + transitivePeerDependencies: + - encoding + dev: false + + /@types/estree/1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/json5/0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/node/20.12.7: + resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/prop-types/15.7.12: + resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + + /@types/react-dom/18.2.25: + resolution: {integrity: sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==} + dependencies: + '@types/react': 18.2.79 + dev: true + + /@types/react/18.2.79: + resolution: {integrity: sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==} + dependencies: + '@types/prop-types': 15.7.12 + csstype: 3.1.3 + + /@vitejs/plugin-react-swc/3.6.0_vite@5.2.9: + resolution: {integrity: sha512-XFRbsGgpGxGzEV5i5+vRiro1bwcIaZDIdBRP16qwm+jP68ue/S8FJTBEgOeojtVDYrbSua3XFp71kC8VJE6v+g==} + peerDependencies: + vite: ^4 || ^5 + dependencies: + '@swc/core': 1.4.16 + vite: 5.2.9_@types+node@20.12.7 + transitivePeerDependencies: + - '@swc/helpers' + dev: true + + /aria-query/5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: true + + /array-buffer-byte-length/1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + dev: true + + /array-includes/3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + is-string: 1.0.7 + dev: true + + /array-union/1.0.2: + resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==} + engines: {node: '>=0.10.0'} + dependencies: + array-uniq: 1.0.3 + dev: true + + /array-uniq/1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + dev: true + + /array.prototype.findlast/1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.findlastindex/1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flat/1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flatmap/1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.toreversed/1.1.2: + resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.tosorted/1.1.3: + resolution: {integrity: sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-shim-unscopables: 1.0.2 + dev: true + + /arraybuffer.prototype.slice/1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + dev: true + + /ast-types-flow/0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + dev: true + + /async/3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + dev: true + + /available-typed-arrays/1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: true + + /axe-core/4.7.0: + resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} + engines: {node: '>=4'} + dev: true + + /axobject-query/3.2.1: + resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + dependencies: + dequal: 2.0.3 + dev: true + + /balanced-match/1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /brace-expansion/1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces/3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /call-bind/1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: true + + /classnames/2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + dev: false + + /commander/11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: true + + /commondir/1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + + /concat-map/0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /confusing-browser-globals/1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + dev: true + + /csstype/3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + /damerau-levenshtein/1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + dev: true + + /data-view-buffer/1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-length/1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-offset/1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /debug/3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug/4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /deepmerge/4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: false + + /define-data-property/1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: true + + /define-properties/1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: true + + /dequal/2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: true + + /doctrine/2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /email-addresses/5.0.0: + resolution: {integrity: sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==} + dev: true + + /emoji-regex/9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /enhanced-resolve/5.16.0: + resolution: {integrity: sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /eruda/3.0.1: + resolution: {integrity: sha512-6q1Xdwga4JTr1mKSW4mzuWSSbmXgqpm/8Wa1QGFGfCWRjC0bCQjbS4u06M1te1moucIS3hBLlbSTPWYH2W0qbQ==} + dev: false + + /es-abstract/1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + arraybuffer.prototype.slice: 1.0.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 + es-define-property: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.4 + get-symbol-description: 1.0.2 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + internal-slot: 1.0.7 + is-array-buffer: 3.0.4 + is-callable: 1.2.7 + is-data-view: 1.0.1 + is-negative-zero: 2.0.3 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + is-string: 1.0.7 + is-typed-array: 1.1.13 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + safe-array-concat: 1.1.2 + safe-regex-test: 1.0.3 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.2 + typed-array-byte-length: 1.0.1 + typed-array-byte-offset: 1.0.2 + typed-array-length: 1.0.6 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.15 + dev: true + + /es-define-property/1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /es-errors/1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: true + + /es-iterator-helpers/1.0.18: + resolution: {integrity: sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-set-tostringtag: 2.0.3 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + globalthis: 1.0.3 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + iterator.prototype: 1.1.2 + safe-array-concat: 1.1.2 + dev: true + + /es-object-atoms/1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + dev: true + + /es-set-tostringtag/2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + dev: true + + /es-shim-unscopables/1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.2 + dev: true + + /es-to-primitive/1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /esbuild/0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 + dev: true + + /escape-string-regexp/1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /eslint-config-airbnb-base/15.0.0_eslint-plugin-import@2.29.1: + resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.2 + dependencies: + confusing-browser-globals: 1.0.11 + eslint-plugin-import: 2.29.1_0d4492a3f7b47255315d99e4cab71562 + object.assign: 4.1.5 + object.entries: 1.1.8 + semver: 6.3.1 + dev: true + + /eslint-config-airbnb-typescript/18.0.0_eslint-plugin-import@2.29.1: + resolution: {integrity: sha512-oc+Lxzgzsu8FQyFVa4QFaVKiitTYiiW3frB9KYW5OWdPrqFc7FzxgB20hP4cHMlr+MBzGcLl3jnCOVOydL9mIg==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^7.0.0 + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + dependencies: + eslint-config-airbnb-base: 15.0.0_eslint-plugin-import@2.29.1 + transitivePeerDependencies: + - eslint-plugin-import + dev: true + + /eslint-config-airbnb/19.0.4_5d4be150ff0baeaf046374dffc2f81a2: + resolution: {integrity: sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==} + engines: {node: ^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.3 + eslint-plugin-jsx-a11y: ^6.5.1 + eslint-plugin-react: ^7.28.0 + eslint-plugin-react-hooks: ^4.3.0 + dependencies: + eslint-config-airbnb-base: 15.0.0_eslint-plugin-import@2.29.1 + eslint-plugin-import: 2.29.1_0d4492a3f7b47255315d99e4cab71562 + eslint-plugin-jsx-a11y: 6.8.0 + eslint-plugin-react: 7.34.1 + eslint-plugin-react-hooks: 4.6.0 + object.assign: 4.1.5 + object.entries: 1.1.8 + dev: true + + /eslint-import-resolver-node/0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-import-resolver-typescript/3.6.1_eslint-plugin-import@2.29.1: + resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '*' + eslint-plugin-import: '*' + dependencies: + debug: 4.3.4 + enhanced-resolve: 5.16.0 + eslint-module-utils: 2.8.1_0d4492a3f7b47255315d99e4cab71562 + eslint-plugin-import: 2.29.1_0d4492a3f7b47255315d99e4cab71562 + fast-glob: 3.3.2 + get-tsconfig: 4.7.3 + is-core-module: 2.13.1 + is-glob: 4.0.3 + transitivePeerDependencies: + - '@typescript-eslint/parser' + - eslint-import-resolver-node + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-module-utils/2.8.1_0d4492a3f7b47255315d99e4cab71562: + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + debug: 3.2.7 + eslint-import-resolver-typescript: 3.6.1_eslint-plugin-import@2.29.1 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils/2.8.1_17573d850e614ea701420308b63343e6: + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + debug: 3.2.7 + eslint-import-resolver-node: 0.3.9 + eslint-import-resolver-typescript: 3.6.1_eslint-plugin-import@2.29.1 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-import/2.29.1_0d4492a3f7b47255315d99e4cab71562: + resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.1_17573d850e614ea701420308b63343e6 + hasown: 2.0.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.0 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-jsx-a11y/6.8.0: + resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + '@babel/runtime': 7.24.4 + aria-query: 5.3.0 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.2 + ast-types-flow: 0.0.8 + axe-core: 4.7.0 + axobject-query: 3.2.1 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + es-iterator-helpers: 1.0.18 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + dev: true + + /eslint-plugin-react-hooks/4.6.0: + resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + dev: true + + /eslint-plugin-react/7.34.1: + resolution: {integrity: sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.2 + array.prototype.toreversed: 1.1.2 + array.prototype.tosorted: 1.1.3 + doctrine: 2.1.0 + es-iterator-helpers: 1.0.18 + estraverse: 5.3.0 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + object.hasown: 1.1.4 + object.values: 1.2.0 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.11 + dev: true + + /eslint-plugin-simple-import-sort/12.1.0: + resolution: {integrity: sha512-Y2fqAfC11TcG/WP3TrI1Gi3p3nc8XJyEOJYHyEPEGI/UAgNx6akxxlX74p7SbAQdLcgASKhj8M0GKvH3vq/+ig==} + peerDependencies: + eslint: '>=5.0.0' + dev: true + + /estraverse/5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils/2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /eventsource/2.0.2: + resolution: {integrity: sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==} + engines: {node: '>=12.0.0'} + dev: false + + /fast-glob/3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fastq/1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + dependencies: + reusify: 1.0.4 + dev: true + + /filename-reserved-regex/2.0.0: + resolution: {integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==} + engines: {node: '>=4'} + dev: true + + /filenamify/4.3.0: + resolution: {integrity: sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==} + engines: {node: '>=8'} + dependencies: + filename-reserved-regex: 2.0.0 + strip-outer: 1.0.1 + trim-repeated: 1.0.0 + dev: true + + /fill-range/7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-cache-dir/3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + dev: true + + /find-up/4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /for-each/0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /fs-extra/11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fs.realpath/1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents/2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind/1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /function.prototype.name/1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names/1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /get-intrinsic/1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: true + + /get-symbol-description/1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + dev: true + + /get-tsconfig/4.7.3: + resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + + /gh-pages/6.1.1: + resolution: {integrity: sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.5 + commander: 11.1.0 + email-addresses: 5.0.0 + filenamify: 4.3.0 + find-cache-dir: 3.3.2 + fs-extra: 11.2.0 + globby: 6.1.0 + dev: true + + /glob-parent/5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob/7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globalthis/1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + + /globby/6.1.0: + resolution: {integrity: sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==} + engines: {node: '>=0.10.0'} + dependencies: + array-union: 1.0.2 + glob: 7.2.3 + object-assign: 4.1.1 + pify: 2.3.0 + pinkie-promise: 2.0.1 + dev: true + + /globrex/0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + dev: true + + /gopd/1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /graceful-fs/4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /has-bigints/1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-property-descriptors/1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: true + + /has-proto/1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols/1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag/1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /hasown/2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /inflight/1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits/2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /internal-slot/1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + dev: true + + /is-array-buffer/3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-async-function/2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-bigint/1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-boolean-object/1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-callable/1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module/2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.2 + dev: true + + /is-data-view/1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + dependencies: + is-typed-array: 1.1.13 + dev: true + + /is-date-object/1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-extglob/2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-finalizationregistry/1.0.2: + resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-generator-function/1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-glob/4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-map/2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + dev: true + + /is-negative-zero/2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object/1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-number/7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-regex/1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-set/2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + dev: true + + /is-shared-array-buffer/1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-string/1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-symbol/1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array/1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.15 + dev: true + + /is-weakmap/2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + dev: true + + /is-weakref/1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-weakset/2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /isarray/2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /iterator.prototype/1.1.2: + resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} + dependencies: + define-properties: 1.2.1 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + reflect.getprototypeof: 1.0.6 + set-function-name: 2.0.2 + dev: true + + /js-tokens/4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + /json5/1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /jsonfile/6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsx-ast-utils/3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.2 + object.assign: 4.1.5 + object.values: 1.2.0 + dev: true + + /language-subtag-registry/0.3.22: + resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + dev: true + + /language-tags/1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + dependencies: + language-subtag-registry: 0.3.22 + dev: true + + /locate-path/5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /loose-envify/1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + + /make-dir/3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + dev: true + + /merge2/1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch/4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /minimatch/3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist/1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /ms/2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms/2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /nanoid/3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /node-fetch/2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /object-assign/4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-inspect/1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-keys/1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign/4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.entries/1.1.8: + resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /object.fromentries/2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /object.groupby/1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + dev: true + + /object.hasown/1.1.4: + resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /object.values/1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /once/1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /p-limit/2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-locate/4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-try/2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /path-exists/4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-parse/1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /picocolors/1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch/2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify/2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /pinkie-promise/2.0.1: + resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} + engines: {node: '>=0.10.0'} + dependencies: + pinkie: 2.0.4 + dev: true + + /pinkie/2.0.4: + resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} + engines: {node: '>=0.10.0'} + dev: true + + /pkg-dir/4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /possible-typed-array-names/1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: true + + /postcss/8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.2.0 + dev: true + + /prop-types/15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: true + + /queue-microtask/1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /react-dom/18.2.0_react@18.2.0: + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + + /react-is/16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: true + + /react-router-dom/6.22.3_react-dom@18.2.0+react@18.2.0: + resolution: {integrity: sha512-7ZILI7HjcE+p31oQvwbokjk6OA/bnFxrhJ19n82Ex9Ph8fNAq+Hm/7KchpMGlTgWhUxRHMMCut+vEtNpWpowKw==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + dependencies: + '@remix-run/router': 1.15.3 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-router: 6.22.3_react@18.2.0 + dev: false + + /react-router/6.22.3_react@18.2.0: + resolution: {integrity: sha512-dr2eb3Mj5zK2YISHK++foM9w4eBnO23eKnZEDs7c880P6oKbrjz/Svg9+nxqtHQK+oMW4OtjZca0RqPglXxguQ==} + engines: {node: '>=14.0.0'} + peerDependencies: + react: '>=16.8' + dependencies: + '@remix-run/router': 1.15.3 + react: 18.2.0 + dev: false + + /react/18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + + /reflect.getprototypeof/1.0.6: + resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + globalthis: 1.0.3 + which-builtin-type: 1.1.3 + dev: true + + /regenerator-runtime/0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + + /regexp.prototype.flags/1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + dev: true + + /resolve-pkg-maps/1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + + /resolve/1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /resolve/2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify/1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rollup/4.14.3: + resolution: {integrity: sha512-ag5tTQKYsj1bhrFC9+OEWqb5O6VYgtQDO9hPDBMmIbePwhfSr+ExlcU741t8Dhw5DkPCQf6noz0jb36D6W9/hw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.14.3 + '@rollup/rollup-android-arm64': 4.14.3 + '@rollup/rollup-darwin-arm64': 4.14.3 + '@rollup/rollup-darwin-x64': 4.14.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.14.3 + '@rollup/rollup-linux-arm-musleabihf': 4.14.3 + '@rollup/rollup-linux-arm64-gnu': 4.14.3 + '@rollup/rollup-linux-arm64-musl': 4.14.3 + '@rollup/rollup-linux-powerpc64le-gnu': 4.14.3 + '@rollup/rollup-linux-riscv64-gnu': 4.14.3 + '@rollup/rollup-linux-s390x-gnu': 4.14.3 + '@rollup/rollup-linux-x64-gnu': 4.14.3 + '@rollup/rollup-linux-x64-musl': 4.14.3 + '@rollup/rollup-win32-arm64-msvc': 4.14.3 + '@rollup/rollup-win32-ia32-msvc': 4.14.3 + '@rollup/rollup-win32-x64-msvc': 4.14.3 + fsevents: 2.3.3 + dev: true + + /run-parallel/1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-array-concat/1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-regex-test/1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + dev: true + + /scheduler/0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /semver/6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /set-function-length/1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + dev: true + + /set-function-name/2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + dev: true + + /side-channel/1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + dev: true + + /source-map-js/1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + dev: true + + /string.prototype.matchall/4.0.11: + resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + regexp.prototype.flags: 1.5.2 + set-function-name: 2.0.2 + side-channel: 1.0.6 + dev: true + + /string.prototype.trim/1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimend/1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimstart/1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /strip-bom/3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-outer/1.0.1: + resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==} + engines: {node: '>=0.10.0'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /supports-preserve-symlinks-flag/1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /tapable/2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /to-regex-range/5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /tr46/0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /trim-repeated/1.0.0: + resolution: {integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==} + engines: {node: '>=0.10.0'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /tsconfck/3.0.3_typescript@5.4.5: + resolution: {integrity: sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + dependencies: + typescript: 5.4.5 + dev: true + + /tsconfig-paths/3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tweetnacl-util/0.15.1: + resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} + dev: false + + /tweetnacl/1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + dev: false + + /typed-array-buffer/1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-length/1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-offset/1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + dev: true + + /typed-array-length/1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + possible-typed-array-names: 1.0.0 + dev: true + + /typescript/5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /ua-parser-js/1.0.37: + resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} + dev: false + + /unbox-primitive/1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /undici-types/5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /universalify/2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /vite-tsconfig-paths/4.3.2_typescript@5.4.5+vite@5.2.9: + resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==} + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + debug: 4.3.4 + globrex: 0.1.2 + tsconfck: 3.0.3_typescript@5.4.5 + vite: 5.2.9_@types+node@20.12.7 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /vite/5.2.9_@types+node@20.12.7: + resolution: {integrity: sha512-uOQWfuZBlc6Y3W/DTuQ1Sr+oIXWvqljLvS881SVmAj00d5RdgShLcuXWxseWPd4HXwiYBFW/vXHfKFeqj9uQnw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.12.7 + esbuild: 0.20.2 + postcss: 8.4.38 + rollup: 4.14.3 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /webidl-conversions/3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-url/5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /which-boxed-primitive/1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-builtin-type/1.1.3: + resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + engines: {node: '>= 0.4'} + dependencies: + function.prototype.name: 1.1.6 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.0.5 + is-finalizationregistry: 1.0.2 + is-generator-function: 1.0.10 + is-regex: 1.1.4 + is-weakref: 1.0.2 + isarray: 2.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.15 + dev: true + + /which-collection/1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + dev: true + + /which-typed-array/1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: true + + /wrappy/1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true diff --git a/apps/react/public/tonconnect-manifest.json b/apps/react/public/tonconnect-manifest.json new file mode 100644 index 000000000..0bb056f4f --- /dev/null +++ b/apps/react/public/tonconnect-manifest.json @@ -0,0 +1,5 @@ +{ + "url": "https://ton.vote", + "name": "TON Vote", + "iconUrl": "https://ton.vote/logo.png" +} \ No newline at end of file diff --git a/apps/react/src/components/App.tsx b/apps/react/src/components/App.tsx new file mode 100644 index 000000000..4c9b83a5b --- /dev/null +++ b/apps/react/src/components/App.tsx @@ -0,0 +1,63 @@ +import { useIntegration } from '@tma.js/react-router-integration'; +import { + bindMiniAppCSSVars, + bindThemeParamsCSSVars, + bindViewportCSSVars, + initNavigator, + useMiniApp, + useThemeParams, + useViewport, +} from '@tma.js/sdk-react'; +import { type FC, useEffect, useMemo } from 'react'; +import { + Navigate, + Route, + Router, + Routes, +} from 'react-router-dom'; + +import { routes } from '@/navigation/routes.tsx'; + +export const App: FC = () => { + const miniApp = useMiniApp(); + const themeParams = useThemeParams(); + const viewport = useViewport(); + + useEffect(() => { + return bindMiniAppCSSVars(miniApp, themeParams); + }, [miniApp, themeParams]); + + useEffect(() => { + return bindThemeParamsCSSVars(themeParams); + }, [themeParams]); + + useEffect(() => { + if (viewport) { + return bindViewportCSSVars(viewport); + } + }, [viewport]); + + // Create new application navigator and attach it to the browser history, so it could modify + // it and listen to its changes. + const navigator = useMemo(() => initNavigator( + 'app-navigation-state', + { hashMode: 'default' }, + ), []); + const [location, reactNavigator] = useIntegration(navigator); + + // Don't forget to attach the navigator to allow it to control the BackButton state as well + // as browser history. + useEffect(() => { + navigator.attach(); + return () => navigator.detach(); + }, [navigator]); + + return ( + + + {routes.map((route) => )} + }/> + + + ); +}; diff --git a/apps/react/src/components/DisplayData/DisplayData.css b/apps/react/src/components/DisplayData/DisplayData.css new file mode 100644 index 000000000..226ee602d --- /dev/null +++ b/apps/react/src/components/DisplayData/DisplayData.css @@ -0,0 +1,19 @@ +.display-data__line { + display: flex; + align-items: center; + margin-bottom: 8px; + gap: 10px; + flex-flow: wrap; +} + +.display-data__line-title { + border: 1px solid var(--tg-theme-accent-text-color); + background-color: var(--tg-theme-bg-color); + border-radius: 5px; + padding: 2px 8px 4px; + box-sizing: border-box; +} + +.display-data__line-value { + word-break: break-word; +} diff --git a/apps/react/src/components/DisplayData/DisplayData.tsx b/apps/react/src/components/DisplayData/DisplayData.tsx new file mode 100644 index 000000000..618ba0ccc --- /dev/null +++ b/apps/react/src/components/DisplayData/DisplayData.tsx @@ -0,0 +1,40 @@ +import { isRGB, type RGB as RGBType } from '@tma.js/sdk'; +import type { FC, ReactNode } from 'react'; + +import { RGB } from '@/components/RGB/RGB.tsx'; + +import './DisplayData.css'; + +export interface DisplayDataRow { + title: string; + value?: RGBType | string | boolean | ReactNode; +} + +export interface DisplayDataProps { + rows: DisplayDataRow[]; +} + +export const DisplayData: FC = ({ rows }) => ( +
+ {rows.map(({ title, value }, idx) => { + let valueNode: ReactNode; + + if (value === undefined) { + valueNode = empty; + } else if (typeof value === 'string' && isRGB(value)) { + valueNode = ; + } else if (typeof value === 'boolean') { + valueNode = value ? '✔️' : '❌'; + } else { + valueNode = value; + } + + return ( +
+ {title} + {valueNode} +
+ ); + })} +
+); diff --git a/apps/react/src/components/ErrorBoundary.tsx b/apps/react/src/components/ErrorBoundary.tsx new file mode 100644 index 000000000..595089462 --- /dev/null +++ b/apps/react/src/components/ErrorBoundary.tsx @@ -0,0 +1,44 @@ +import { + Component, + type ComponentType, + type GetDerivedStateFromError, + type PropsWithChildren, + type ReactNode, +} from 'react'; + +export interface ErrorBoundaryProps extends PropsWithChildren { + fallback?: ReactNode | ComponentType<{ error: unknown }>; +} + +interface ErrorBoundaryState { + error?: unknown; +} + +export class ErrorBoundary extends Component { + state: ErrorBoundaryState = {}; + + // eslint-disable-next-line max-len + static getDerivedStateFromError: GetDerivedStateFromError = (error) => ({ error }); + + componentDidCatch(error: Error) { + this.setState({ error }); + } + + render() { + const { + state: { + error, + }, + props: { + fallback: Fallback, + children, + }, + } = this; + + return 'error' in this.state + ? typeof Fallback === 'function' + ? + : Fallback + : children; + } +} diff --git a/apps/react/src/components/Link/Link.css b/apps/react/src/components/Link/Link.css new file mode 100644 index 000000000..7251d5071 --- /dev/null +++ b/apps/react/src/components/Link/Link.css @@ -0,0 +1,4 @@ +.link { + text-decoration: none; + color: var(--tg-theme-link-color); +} \ No newline at end of file diff --git a/apps/react/src/components/Link/Link.tsx b/apps/react/src/components/Link/Link.tsx new file mode 100644 index 000000000..515c5b2db --- /dev/null +++ b/apps/react/src/components/Link/Link.tsx @@ -0,0 +1,46 @@ +import { classNames, useUtils } from '@tma.js/sdk-react'; +import { type FC, type MouseEventHandler, useCallback } from 'react'; +import { Link as RouterLink, type LinkProps } from 'react-router-dom'; + +import './Link.css'; + +export const Link: FC = (props) => { + const { + className, + onClick: propsOnClick, + to, + } = props; + const utils = useUtils(); + + const onClick = useCallback>((e) => { + propsOnClick?.(e); + + // Compute if target path is external. In this case we would like to open link using + // TMA method. + let path: string; + if (typeof to === 'string') { + path = to; + } else { + const { search = '', pathname = '', hash = '' } = to; + path = `${pathname}?${search}#${hash}`; + } + + const targetUrl = new URL(path, window.location.toString()); + const currentUrl = new URL(window.location.toString()); + const isExternal = targetUrl.protocol !== currentUrl.protocol + || targetUrl.host !== currentUrl.host; + + if (isExternal) { + e.preventDefault(); + return utils.openLink(targetUrl.toString()); + } + }, [to, propsOnClick, utils]); + + return ( + + ); +}; diff --git a/apps/react/src/components/Page/Page.css b/apps/react/src/components/Page/Page.css new file mode 100644 index 000000000..8c7b788da --- /dev/null +++ b/apps/react/src/components/Page/Page.css @@ -0,0 +1,8 @@ +.page { + padding: 0 10px; + box-sizing: border-box; +} + +.page__disclaimer { + margin-bottom: 16px; +} \ No newline at end of file diff --git a/apps/react/src/components/Page/Page.tsx b/apps/react/src/components/Page/Page.tsx new file mode 100644 index 000000000..3007a5a36 --- /dev/null +++ b/apps/react/src/components/Page/Page.tsx @@ -0,0 +1,16 @@ +import type { FC, PropsWithChildren, ReactNode } from 'react'; + +import './Page.css'; + +export interface PageProps extends PropsWithChildren { + title: string; + disclaimer?: ReactNode; +} + +export const Page: FC = ({ title, children, disclaimer }) => ( +
+

{title}

+ {disclaimer &&
{disclaimer}
} + {children} +
+); diff --git a/apps/react/src/components/RGB/RGB.css b/apps/react/src/components/RGB/RGB.css new file mode 100644 index 000000000..fec07994e --- /dev/null +++ b/apps/react/src/components/RGB/RGB.css @@ -0,0 +1,12 @@ +.rgb { + display: inline-flex; + align-items: center; + gap: 5px; +} + +.rgb__icon { + width: 18px; + aspect-ratio: 1; + border: 1px solid #555; + border-radius: 50%; +} \ No newline at end of file diff --git a/apps/react/src/components/RGB/RGB.tsx b/apps/react/src/components/RGB/RGB.tsx new file mode 100644 index 000000000..2973cc663 --- /dev/null +++ b/apps/react/src/components/RGB/RGB.tsx @@ -0,0 +1,15 @@ +import { classNames, type RGB as RGBType } from '@tma.js/sdk'; +import type { FC } from 'react'; + +import './RGB.css'; + +export type RGBProps = JSX.IntrinsicElements['div'] & { + color: RGBType; +}; + +export const RGB: FC = ({ color, className, ...rest }) => ( + + + {color} + +); diff --git a/apps/react/src/components/Root.tsx b/apps/react/src/components/Root.tsx new file mode 100644 index 000000000..6818ea1ed --- /dev/null +++ b/apps/react/src/components/Root.tsx @@ -0,0 +1,50 @@ +import { retrieveLaunchParams, SDKProvider } from '@tma.js/sdk-react'; +import { TonConnectUIProvider } from '@tonconnect/ui-react'; +import { type FC, useEffect, useMemo } from 'react'; + +import { App } from '@/components/App.tsx'; +import { ErrorBoundary } from '@/components/ErrorBoundary.tsx'; + +const ErrorBoundaryError: FC<{ error: unknown }> = ({ error }) => ( +
+

An unhandled error occurred:

+
+ + {error instanceof Error + ? error.message + : typeof error === 'string' + ? error + : JSON.stringify(error)} + +
+
+); + +const Inner: FC = () => { + const debug = retrieveLaunchParams().startParam === 'debug' + + const manifestUrl = useMemo(() => { + return new URL('tonconnect-manifest.json', window.location.href).toString(); + }, []); + + // Enable debug mode to see all the methods sent and events received. + useEffect(() => { + if (debug) { + import('eruda').then((lib) => lib.default.init()); + } + }, [debug]); + + return ( + + + + + + ); +}; + +export const Root: FC = () => ( + + + +); diff --git a/apps/react/src/index.css b/apps/react/src/index.css new file mode 100644 index 000000000..334d2cf5e --- /dev/null +++ b/apps/react/src/index.css @@ -0,0 +1,25 @@ +body { + font-family: -apple-system, BlinkMacSystemFont, 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + line-height: 1.5; + + background: var(--tg-theme-secondary-bg-color, white); + color: var(--tg-theme-text-color, black); +} + +blockquote { + margin: 0; +} + +blockquote p { + padding: 15px; + background: #eee; + border-radius: 5px; +} + +pre { + overflow: auto; +} \ No newline at end of file diff --git a/apps/react/src/index.tsx b/apps/react/src/index.tsx new file mode 100644 index 000000000..ecac1385a --- /dev/null +++ b/apps/react/src/index.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; + +import { Root } from '@/components/Root'; + +import './index.css'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/apps/react/src/navigation/routes.tsx b/apps/react/src/navigation/routes.tsx new file mode 100644 index 000000000..5301c624e --- /dev/null +++ b/apps/react/src/navigation/routes.tsx @@ -0,0 +1,44 @@ +import type { ComponentType, JSX } from 'react'; + +import { IndexPage } from '@/pages/IndexPage/IndexPage'; +import { InitDataPage } from '@/pages/InitDataPage/InitDataPage'; +import { LaunchParamsPage } from '@/pages/LaunchParamsPage/LaunchParamsPage.tsx'; +import { ThemeParamsPage } from '@/pages/ThemeParamsPage/ThemeParamsPage.tsx'; +import { TONConnectPage } from '@/pages/TONConnectPage/TONConnectPage'; + +interface Route { + path: string; + Component: ComponentType; + title?: string; + icon?: JSX.Element; +} + +export const routes: Route[] = [ + { path: '/', Component: IndexPage }, + { path: '/init-data', Component: InitDataPage, title: 'Init Data' }, + { path: '/theme-params', Component: ThemeParamsPage, title: 'Theme Params' }, + { path: '/launch-params', Component: LaunchParamsPage, title: 'Launch Params' }, + { + path: '/ton-connect', + Component: TONConnectPage, + title: 'TON Connect', + icon: ( + + + + + ), + }, +]; diff --git a/apps/react/src/pages/IndexPage/IndexPage.css b/apps/react/src/pages/IndexPage/IndexPage.css new file mode 100644 index 000000000..eddc134e6 --- /dev/null +++ b/apps/react/src/pages/IndexPage/IndexPage.css @@ -0,0 +1,23 @@ +.index-page__links { + list-style: none; + padding-left: 0; +} + +.index-page__link { + font-weight: bold; + display: inline-flex; + gap: 5px; +} + +.index-page__link-item + .index-page__link-item { + margin-top: 10px; +} + +.index-page__link-icon { + width: 20px; + display: block; +} + +.index-page__link-icon svg { + display: block; +} \ No newline at end of file diff --git a/apps/react/src/pages/IndexPage/IndexPage.tsx b/apps/react/src/pages/IndexPage/IndexPage.tsx new file mode 100644 index 000000000..9be5a6f8c --- /dev/null +++ b/apps/react/src/pages/IndexPage/IndexPage.tsx @@ -0,0 +1,30 @@ +import type { FC } from 'react'; + +import { Link } from '@/components/Link/Link.tsx'; +import { Page } from '@/components/Page/Page.tsx'; +import { routes } from '@/navigation/routes.tsx'; + +import './IndexPage.css'; + +export const IndexPage: FC = () => ( + +

+ This page is a home page in this boilerplate. You can use the links below to visit other + pages with their own functionality. +

+
    + {routes.map(({ path, title, icon }) => title && ( +
  • + + {icon && ( + + {icon} + + )} + {title} + +
  • + ))} +
+
+); diff --git a/apps/react/src/pages/InitDataPage/InitDataPage.css b/apps/react/src/pages/InitDataPage/InitDataPage.css new file mode 100644 index 000000000..fab4ae0a7 --- /dev/null +++ b/apps/react/src/pages/InitDataPage/InitDataPage.css @@ -0,0 +1,7 @@ +.init-data-page__section + .init-data-page__section { + margin-top: 12px; +} + +.init-data-page__section-title { + margin-bottom: 4px; +} \ No newline at end of file diff --git a/apps/react/src/pages/InitDataPage/InitDataPage.tsx b/apps/react/src/pages/InitDataPage/InitDataPage.tsx new file mode 100644 index 000000000..2311163f5 --- /dev/null +++ b/apps/react/src/pages/InitDataPage/InitDataPage.tsx @@ -0,0 +1,130 @@ +// import { useInitData, useInitDataRaw } from '@tma.js/sdk-react'; +import { type FC, type ReactNode, useMemo } from 'react'; +import { useInitData, useLaunchParams, type User } from '@tma.js/sdk-react'; + +import { DisplayData, type DisplayDataRow } from '@/components/DisplayData/DisplayData.tsx'; +import { Link } from '@/components/Link/Link.tsx'; +import { Page } from '@/components/Page/Page.tsx'; + +import './InitDataPage.css'; + +function getUserRows(user: User): DisplayDataRow[] { + return [ + { title: 'id', value: user.id.toString() }, + { title: 'last_name', value: user.lastName }, + { title: 'first_name', value: user.firstName }, + { title: 'is_bot', value: user.isBot }, + { title: 'is_premium', value: user.isPremium }, + { title: 'language_code', value: user.languageCode }, + ]; +} + +export const InitDataPage: FC = () => { + const initDataRaw = useLaunchParams().initDataRaw; + const initData = useInitData(); + + const initDataRows = useMemo(() => { + if (!initData || !initDataRaw) { + return; + } + const { + hash, + queryId, + chatType, + chatInstance, + authDate, + startParam, + canSendAfter, + canSendAfterDate, + } = initData; + return [ + { title: 'raw', value: initDataRaw }, + { title: 'auth_date', value: authDate.toLocaleString() }, + { title: 'auth_date (raw)', value: authDate.getTime() / 1000 }, + { title: 'hash', value: hash }, + { title: 'can_send_after', value: canSendAfterDate?.toISOString() }, + { title: 'can_send_after (raw)', value: canSendAfter }, + { title: 'query_id', value: queryId }, + { title: 'start_param', value: startParam }, + { title: 'chat_type', value: chatType }, + { title: 'chat_instance', value: chatInstance }, + ]; + }, [initData, initDataRaw]); + + const userRows = useMemo(() => { + return initData && initData.user ? getUserRows(initData.user) : undefined; + }, [initData]); + + const receiverRows = useMemo(() => { + return initData && initData.receiver ? getUserRows(initData.receiver) : undefined; + }, [initData]); + + const chatRows = useMemo(() => { + if (!initData?.chat) { + return; + } + const { id, title, type, username, photoUrl } = initData.chat; + + return [ + { title: 'id', value: id.toString() }, + { title: 'title', value: title }, + { title: 'type', value: type }, + { title: 'username', value: username }, + { title: 'photo_url', value: photoUrl }, + ]; + }, [initData]); + + let contentNode: ReactNode; + + if (!initDataRows) { + contentNode = Application was launched with missing init data; + } else { + contentNode = ( + <> +
+

Init data

+ +
+ +
+

User

+ {userRows + ? + : User information missing} +
+ +
+

Receiver

+ {receiverRows + ? + : Receiver information missing} +
+ +
+

Chat

+ {chatRows + ? + : Chat information missing} +
+ + ); + } + + return ( + + This page displays application + {' '} + + init data + + . + + )} + > + {contentNode} + + ); +}; diff --git a/apps/react/src/pages/LaunchParamsPage/LaunchParamsPage.tsx b/apps/react/src/pages/LaunchParamsPage/LaunchParamsPage.tsx new file mode 100644 index 000000000..922f2762c --- /dev/null +++ b/apps/react/src/pages/LaunchParamsPage/LaunchParamsPage.tsx @@ -0,0 +1,38 @@ +import { useLaunchParams } from '@tma.js/sdk-react'; +import type { FC } from 'react'; + +import { DisplayData } from '@/components/DisplayData/DisplayData.tsx'; +import { Link } from '@/components/Link/Link.tsx'; +import { Page } from '@/components/Page/Page.tsx'; + +export const LaunchParamsPage: FC = () => { + const lp = useLaunchParams(); + + return ( + + This page displays application + {' '} + + launch parameters + + . + + )} + > + View }, + { title: 'tgWebAppThemeParams', value: View }, + ]} + /> + + ); +}; diff --git a/apps/react/src/pages/TONConnectPage/TONConnectPage.css b/apps/react/src/pages/TONConnectPage/TONConnectPage.css new file mode 100644 index 000000000..f70f76dbb --- /dev/null +++ b/apps/react/src/pages/TONConnectPage/TONConnectPage.css @@ -0,0 +1,34 @@ +.ton-connect-page__button-container { + display: flex; + align-items: center; + justify-content: flex-end; +} + +.ton-connect-page__provider { + display: flex; + align-items: center; + gap: 15px; + margin-bottom: 16px; +} + +.ton-connect-page__provider-image { + border-radius: 5px; +} + +.ton-connect-page__provider-meta { + display: flex; + flex-direction: column; +} + +.ton-connect-page__provider-wallet-name { + font-weight: bold; + font-size: 20px; + margin: 0; +} + +.ton-connect-page__provider-app-name { + opacity: .4; + font-weight: 400; + font-size: 14px; + vertical-align: top; +} \ No newline at end of file diff --git a/apps/react/src/pages/TONConnectPage/TONConnectPage.tsx b/apps/react/src/pages/TONConnectPage/TONConnectPage.tsx new file mode 100644 index 000000000..c3977069a --- /dev/null +++ b/apps/react/src/pages/TONConnectPage/TONConnectPage.tsx @@ -0,0 +1,80 @@ +import { useUtils } from '@tma.js/sdk-react'; +import { TonConnectButton, useTonWallet } from '@tonconnect/ui-react'; +import type { FC, ReactNode } from 'react'; + +import { DisplayData } from '@/components/DisplayData/DisplayData.tsx'; +import { Link } from '@/components/Link/Link.tsx'; +import { Page } from '@/components/Page/Page.tsx'; + +import './TONConnectPage.css'; + +export const TONConnectPage: FC = () => { + const wallet = useTonWallet(); + const utils = useUtils(); + let content: ReactNode; + + if (wallet) { + const { + chain, + publicKey, + address, + } = wallet.account; + content = ( + <> + {'imageUrl' in wallet && ( +
+ Provider logo +
+

+ {wallet.name} +   + + ( + {wallet.appName} + ) + +

+ { + e.preventDefault(); + utils.openLink(wallet.aboutUrl); + }} + > + About connected wallet + +
+
+ )} + + + ); + } else { + content = ( +

+ To display the data related to the TON Connect, it is required to connect your wallet. +

+ ); + } + + return ( + + {content} +
+ +
+
+ ); +}; diff --git a/apps/react/src/pages/ThemeParamsPage/ThemeParamsPage.tsx b/apps/react/src/pages/ThemeParamsPage/ThemeParamsPage.tsx new file mode 100644 index 000000000..e5f6be2d0 --- /dev/null +++ b/apps/react/src/pages/ThemeParamsPage/ThemeParamsPage.tsx @@ -0,0 +1,39 @@ +import { useThemeParams } from '@tma.js/sdk-react'; +import type { FC } from 'react'; + +import { DisplayData } from '@/components/DisplayData/DisplayData.tsx'; +import { Link } from '@/components/Link/Link.tsx'; +import { Page } from '@/components/Page/Page.tsx'; + +export const ThemeParamsPage: FC = () => { + const themeParams = useThemeParams(); + + return ( + + This page displays current + {' '} + + theme parameters + + . It is reactive, so, changing theme externally will lead to this page updates. + + )} + > + ({ + title: title + .replace(/[A-Z]/g, (m) => `_${m.toLowerCase()}`) + .replace(/background/, 'bg'), + value, + })) + } + /> + + ); +}; diff --git a/apps/react/src/vite-env.d.ts b/apps/react/src/vite-env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/apps/react/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/react/tsconfig.json b/apps/react/tsconfig.json new file mode 100644 index 000000000..35fc1b819 --- /dev/null +++ b/apps/react/tsconfig.json @@ -0,0 +1,36 @@ +{ + "compilerOptions": { + "allowImportingTsExtensions": true, + "isolatedModules": true, + "jsx": "react-jsx", + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "paths": { + "@/*": [ + "./src/*" + ] + }, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ES2020", + "useDefineForClassFields": true + }, + "include": [ + "src" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/apps/react/tsconfig.node.json b/apps/react/tsconfig.node.json new file mode 100644 index 000000000..b5a343184 --- /dev/null +++ b/apps/react/tsconfig.node.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": [ + "vite.config.ts" + ] +} diff --git a/apps/react/vite.config.ts b/apps/react/vite.config.ts new file mode 100644 index 000000000..9eea6a6fb --- /dev/null +++ b/apps/react/vite.config.ts @@ -0,0 +1,27 @@ +import { readFileSync } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { defineConfig } from 'vite'; +import tsconfigPaths from 'vite-tsconfig-paths'; +import react from '@vitejs/plugin-react-swc'; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: '/reactjs-template/', + plugins: [react(), tsconfigPaths()], + // Uncomment the next lines in case, you would like to run Vite dev server using HTTPS and in case, + // you have key and certificate. You retrieve your certificate and key using mkcert. + // Learn more: + // https://docs.telegram-mini-apps.com/platform/getting-app-link#mkcert + // + server: { + port: 443, + https: { + cert: readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), './tma.internal.pem')), + key: readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), './tma.internal-key.pem')), + }, + host: 'tma.internal', + }, + publicDir: './public', +}); + diff --git a/apps/solid/.eslintrc.cjs b/apps/solid/.eslintrc.cjs new file mode 100644 index 000000000..bc5584fe1 --- /dev/null +++ b/apps/solid/.eslintrc.cjs @@ -0,0 +1,33 @@ +module.exports = { + env: { + browser: true, + es2021: true + }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:solid/typescript' + ], + overrides: [ + { + env: { + node: true + }, + files: [ + '.eslintrc.{js,cjs}' + ], + parserOptions: { + sourceType: 'script' + } + } + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module' + }, + plugins: [ + '@typescript-eslint' + ], + rules: {} +}; diff --git a/apps/solid/.github/deployment-branches.png b/apps/solid/.github/deployment-branches.png new file mode 100644 index 000000000..a3797c16b Binary files /dev/null and b/apps/solid/.github/deployment-branches.png differ diff --git a/apps/solid/.github/workflows/github-pages-deploy.yml b/apps/solid/.github/workflows/github-pages-deploy.yml new file mode 100644 index 000000000..84efcc9fd --- /dev/null +++ b/apps/solid/.github/workflows/github-pages-deploy.yml @@ -0,0 +1,61 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy static content to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ['master'] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: 'pages' + cancel-in-progress: true + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 18 + registry-url: 'https://registry.npmjs.org' + + - name: Install pnpm + uses: pnpm/action-setup@v2 + id: pnpm-install + with: + version: 8 + run_install: true + + - name: Build + run: pnpm run build + + - name: Setup Pages + uses: actions/configure-pages@v3 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + with: + # Upload dist repository + path: './dist' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 \ No newline at end of file diff --git a/apps/solid/.gitignore b/apps/solid/.gitignore new file mode 100644 index 000000000..8199050b8 --- /dev/null +++ b/apps/solid/.gitignore @@ -0,0 +1,4 @@ +.idea +*.pem +node_modules +dist \ No newline at end of file diff --git a/apps/solid/README.md b/apps/solid/README.md new file mode 100644 index 000000000..159d1a5ad --- /dev/null +++ b/apps/solid/README.md @@ -0,0 +1,155 @@ +# Telegram Mini Apps Solid.js Boilerplate + +This boilerplate demonstrates how developers can implement a single-page application on the Telegram +Mini Apps platform using the following technologies: + +- [Solid.js](https://www.solidjs.com/) +- [TON Connect](https://docs.ton.org/develop/dapps/ton-connect/overview) +- [TypeScript](https://www.typescriptlang.org/) +- [@tma.js SDK](https://docs.telegram-mini-apps.com/packages/tma-js-sdk) +- [Vite](https://vitejs.dev/) + +> This boilerplate was created using [pnpm](https://pnpm.io/). Therefore, it is required to use +> it for this project as well. + +## First Start + +If you have just cloned this template, you should install the project dependencies using the +command: + +```Bash +pnpm i +``` + +## Scripts + +This project contains the following scripts: + +- `dev`. Runs the application in development mode. +- `build`. Builds the application for production. +- `lint`. Runs [eslint](https://eslint.org/) to ensure the code quality meets the required + standards. +- `deploy`. Deploys the application to GitHub Pages. + +To run a script, use the `pnpm run` command: + +```Bash +pnpm run {script} +# Example: pnpm run build +``` + +## Running + +The first important thing to note here is that the application should always be launched in the +context of Telegram application. You can't just run the application and open it directly in your +browser via `http://localhost:3000`. Opening application this way will surely lead to errors, as long +as this environment does not provide the required Telegram Mini Apps functionality. + +Telegram Mini Apps environment could be any specified +in the [documentation](https://docs.telegram-mini-apps.com/platform/about#supported-applications). + +So, before starting the application, make sure you have already created it in the Telegram +system. Here is the [guide](https://docs.telegram-mini-apps.com/platform/creating-new-app) how to do it. + +When application is created successfully, run it using the `dev` script and open inside Telegram: + +```Bash +pnpm run dev +``` + +## Deploying + +This boilerplate uses GitHub Pages as the way to host the application externally. GitHub Pages provides a CDN +which will let your users receive the application rapidly. Alternatively, you could use such services +as [Heroku](https://www.heroku.com/) or [Vercel](https://vercel.com). + +### GitHub Workflow + +To simplify the process of deployment, this boilerplate contains already +written [GitHub workflow](.github/workflows/github-pages-deploy.yml) to deploy the project automatically in case, some +content was pushed to the `master` branch. + +To let this workflow work properly, it is required create a new environment (or edit the existing one) in the GitHub +repository Settings with the name `github-pages`. Then, add the `master` branch to the list of deployment branches. + +Environments settings could be find using this URL: `https://github.com/{username}/{repository}/settings/environments` + +![img.png](.github/deployment-branches.png) + +In case, you don't want to do it automatically, or you don't use GitHub as the project codebase, just remove the +`.github` directory. + +### GitHub Web Interface + +Alternatively, developers are able to configure the automatic deployment using GitHub web interface. To use it, +follow the link: `https://github.com/{username}/{repository}/settings/pages`. + +### Manual Deployment + +This boilerplate uses the [gh-pages](https://www.npmjs.com/package/gh-pages) tool, which allows deploying your +application right from your PC. + +#### Configuring + +Before running the deployment process, ensure that you have done the following: + +1. Replaced the `homepage` value in `package.json`. The GitHub Pages deploy tool uses this value to + determine the related GitHub project. +2. Replaced the `base` value in `vite.config.ts` and have set it to the name of your GitHub + repository. Vite will use this value when creating paths to static assets. + +For instance, if your GitHub username is `telegram-mini-apps` and the repository name +is `is-awesome`, the value in the `homepage` field should be the following: + +```json +{ + "homepage": "https://telegram-mini-apps.github.io/is-awesome" +} +``` + +And `vite.config.ts` should have this content: + +```ts +export default defineConfig({ + base: '/is-awesome/', + // ... +}); +``` + +You can find more information on configuring the deployment in the `gh-pages` +[docs](https://github.com/tschaub/gh-pages?tab=readme-ov-file#github-pages-project-sites). + +#### Before Deploying + +Before deploying the application, make sure that you've built it and going to deploy the fresh +static files: + +```bash +pnpm run build +``` + +Then, run the deployment process, using the `deploy` script: + +```Bash +pnpm run deploy +``` + +After the deployment completed successfully, visit the page with data according to your +username and repository name. Here is the page link example using the data mentioned above: +https://telegram-mini-apps.github.io/is-awesome + +## TON Connect + +This boilerplate uses the [TON Connect](https://docs.ton.org/develop/dapps/ton-connect/overview) +project to showcase how developers could integrate TON cryptocurrency-related functionality. + +The TON Connect manifest used in this boilerplate is located in the `public` folder along with all +publicly available static files. Don't forget +to [configure](https://docs.ton.org/develop/dapps/ton-connect/manifest) this file according to your +project information. + +## Useful Links + +- [Platform documentation](https://docs.telegram-mini-apps.com/) +- [@tma.js/sdk-solid documentation](https://docs.telegram-mini-apps.com/packages/tma-js-sdk-solid) +- [Telegram developers community chat](https://t.me/devs) diff --git a/apps/solid/index.html b/apps/solid/index.html new file mode 100644 index 000000000..747e7c516 --- /dev/null +++ b/apps/solid/index.html @@ -0,0 +1,20 @@ + + + + + + + Vite + Solid + TS + + + + + + +
+ + + diff --git a/apps/solid/package.json b/apps/solid/package.json new file mode 100644 index 000000000..d868cfe09 --- /dev/null +++ b/apps/solid/package.json @@ -0,0 +1,44 @@ +{ + "name": "solidjs-template", + "private": true, + "version": "0.0.1", + "type": "module", + "main": "index.js", + "homepage": "https://telegram-mini-apps.github.io/solidjs-template", + "scripts": { + "deploy": "gh-pages -d dist", + "dev": "vite", + "build": "tsc --noEmit && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint:fix": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0 --fix", + "preview": "vite preview", + "predeploy": "pnpm run build" + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "@solidjs/router": "^0.13.1", + "@tma.js/sdk-solid": "workspace:*", + "@tma.js/solid-router-integration": "workspace:*", + "@tonconnect/ui": "^2.0.0", + "eruda": "^3.0.1", + "solid-js": "^1.8.16" + }, + "devDependencies": { + "@eslint/js": "^9.2.0", + "@types/node": "^20.12.5", + "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/parser": "^7.8.0", + "eslint": "^8.57.0", + "eslint-plugin-solid": "^0.14.0", + "gh-pages": "^6.1.1", + "globals": "^15.2.0", + "solid-devtools": "^0.30.1", + "typescript": "^5.4.4", + "typescript-eslint": "^7.8.0", + "vite": "^5.2.11", + "vite-plugin-solid": "^2.10.2", + "vite-tsconfig-paths": "^4.3.2" + } +} diff --git a/apps/solid/pnpm-lock.yaml b/apps/solid/pnpm-lock.yaml new file mode 100644 index 000000000..f5ee27e02 --- /dev/null +++ b/apps/solid/pnpm-lock.yaml @@ -0,0 +1,3710 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@solidjs/router': + specifier: ^0.13.1 + version: 0.13.1(solid-js@1.8.16) + '@tma.js/sdk': + specifier: ^1.5.1 + version: 1.5.1 + '@tma.js/sdk-solid': + specifier: ^2.0.1 + version: 2.0.1(@tma.js/sdk@1.5.1)(solid-js@1.8.16) + '@tonconnect/ui': + specifier: ^2.0.0 + version: 2.0.0 + eruda: + specifier: ^3.0.1 + version: 3.0.1 + solid-js: + specifier: ^1.8.16 + version: 1.8.16 + +devDependencies: + '@types/node': + specifier: ^20.12.5 + version: 20.12.5 + '@typescript-eslint/eslint-plugin': + specifier: ^7.6.0 + version: 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/parser': + specifier: ^7.6.0 + version: 7.6.0(eslint@8.57.0)(typescript@5.4.4) + eslint: + specifier: ^8.0.0 + version: 8.57.0 + eslint-config-airbnb-base: + specifier: ^15.0.0 + version: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-config-airbnb-typescript: + specifier: ^18.0.0 + version: 18.0.0(@typescript-eslint/eslint-plugin@7.6.0)(@typescript-eslint/parser@7.6.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-plugin-jsx-a11y: + specifier: ^6.8.0 + version: 6.8.0(eslint@8.57.0) + eslint-plugin-simple-import-sort: + specifier: ^12.0.0 + version: 12.0.0(eslint@8.57.0) + eslint-plugin-solid: + specifier: ^0.13.2 + version: 0.13.2(eslint@8.57.0)(typescript@5.4.4) + gh-pages: + specifier: ^6.1.1 + version: 6.1.1 + solid-devtools: + specifier: ^0.30.1 + version: 0.30.1(solid-js@1.8.16)(vite@5.2.8) + typescript: + specifier: ^5.4.4 + version: 5.4.4 + vite: + specifier: ^5.2.8 + version: 5.2.8(@types/node@20.12.5) + vite-plugin-solid: + specifier: ^2.10.2 + version: 2.10.2(solid-js@1.8.16)(vite@5.2.8) + vite-tsconfig-paths: + specifier: ^4.3.2 + version: 4.3.2(typescript@5.4.4)(vite@5.2.8) + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@ampproject/remapping@2.3.0: + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@babel/code-frame@7.24.2: + resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.24.2 + picocolors: 1.0.0 + dev: true + + /@babel/compat-data@7.24.4: + resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.24.4: + resolution: {integrity: sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.4 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) + '@babel/helpers': 7.24.4 + '@babel/parser': 7.24.4 + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.1 + '@babel/types': 7.24.0 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.24.4: + resolution: {integrity: sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + dev: true + + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.24.4 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.23.0 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.24.0 + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-module-imports@7.18.6: + resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-module-imports@7.24.3: + resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.24.3 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/helper-plugin-utils@7.24.0: + resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/helper-string-parser@7.24.1: + resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helpers@7.24.4: + resolution: {integrity: sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.1 + '@babel/types': 7.24.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.24.2: + resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.0 + dev: true + + /@babel/parser@7.24.4: + resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.4): + resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.24.0 + dev: true + + /@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.4): + resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.24.0 + dev: true + + /@babel/runtime@7.24.4: + resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + + /@babel/template@7.24.0: + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + dev: true + + /@babel/traverse@7.24.1: + resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.24.0: + resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.24.1 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + + /@esbuild/aix-ppc64@0.20.2: + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.20.2: + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.20.2: + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.20.2: + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.20.2: + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.20.2: + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.20.2: + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.20.2: + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.20.2: + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.20.2: + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.20.2: + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.20.2: + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.20.2: + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.20.2: + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.20.2: + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.20.2: + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.20.2: + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.20.2: + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.20.2: + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.20.2: + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.20.2: + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.20.2: + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.20.2: + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.57.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.57.0: + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.3: + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + dev: true + + /@jridgewell/gen-mapping@0.3.5: + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + dev: true + + /@jridgewell/resolve-uri@3.1.2: + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.2.1: + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.25: + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + dev: true + + /@nothing-but/utils@0.12.1: + resolution: {integrity: sha512-1qZU1Q5El0IjE7JT/ucvJNzdr2hL3W8Rm27xNf1p6gb3Nw8pGnZmxp6/GEW9h+I1k1cICxXNq25hBwknTQ7yhg==} + dev: true + + /@rollup/rollup-android-arm-eabi@4.14.1: + resolution: {integrity: sha512-fH8/o8nSUek8ceQnT7K4EQbSiV7jgkHq81m9lWZFIXjJ7lJzpWXbQFpT/Zh6OZYnpFykvzC3fbEvEAFZu03dPA==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.14.1: + resolution: {integrity: sha512-Y/9OHLjzkunF+KGEoJr3heiD5X9OLa8sbT1lm0NYeKyaM3oMhhQFvPB0bNZYJwlq93j8Z6wSxh9+cyKQaxS7PQ==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.14.1: + resolution: {integrity: sha512-+kecg3FY84WadgcuSVm6llrABOdQAEbNdnpi5X3UwWiFVhZIZvKgGrF7kmLguvxHNQy+UuRV66cLVl3S+Rkt+Q==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.14.1: + resolution: {integrity: sha512-2pYRzEjVqq2TB/UNv47BV/8vQiXkFGVmPFwJb+1E0IFFZbIX8/jo1olxqqMbo6xCXf8kabANhp5bzCij2tFLUA==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.14.1: + resolution: {integrity: sha512-mS6wQ6Do6/wmrF9aTFVpIJ3/IDXhg1EZcQFYHZLHqw6AzMBjTHWnCG35HxSqUNphh0EHqSM6wRTT8HsL1C0x5g==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.14.1: + resolution: {integrity: sha512-p9rGKYkHdFMzhckOTFubfxgyIO1vw//7IIjBBRVzyZebWlzRLeNhqxuSaZ7kCEKVkm/kuC9fVRW9HkC/zNRG2w==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.14.1: + resolution: {integrity: sha512-nDY6Yz5xS/Y4M2i9JLQd3Rofh5OR8Bn8qe3Mv/qCVpHFlwtZSBYSPaU4mrGazWkXrdQ98GB//H0BirGR/SKFSw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-powerpc64le-gnu@4.14.1: + resolution: {integrity: sha512-im7HE4VBL+aDswvcmfx88Mp1soqL9OBsdDBU8NqDEYtkri0qV0THhQsvZtZeNNlLeCUQ16PZyv7cqutjDF35qw==} + cpu: [ppc64le] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.14.1: + resolution: {integrity: sha512-RWdiHuAxWmzPJgaHJdpvUUlDz8sdQz4P2uv367T2JocdDa98iRw2UjIJ4QxSyt077mXZT2X6pKfT2iYtVEvOFw==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-s390x-gnu@4.14.1: + resolution: {integrity: sha512-VMgaGQ5zRX6ZqV/fas65/sUGc9cPmsntq2FiGmayW9KMNfWVG/j0BAqImvU4KTeOOgYSf1F+k6at1UfNONuNjA==} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.14.1: + resolution: {integrity: sha512-9Q7DGjZN+hTdJomaQ3Iub4m6VPu1r94bmK2z3UeWP3dGUecRC54tmVu9vKHTm1bOt3ASoYtEz6JSRLFzrysKlA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.14.1: + resolution: {integrity: sha512-JNEG/Ti55413SsreTguSx0LOVKX902OfXIKVg+TCXO6Gjans/k9O6ww9q3oLGjNDaTLxM+IHFMeXy/0RXL5R/g==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.14.1: + resolution: {integrity: sha512-ryS22I9y0mumlLNwDFYZRDFLwWh3aKaC72CWjFcFvxK0U6v/mOkM5Up1bTbCRAhv3kEIwW2ajROegCIQViUCeA==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.14.1: + resolution: {integrity: sha512-TdloItiGk+T0mTxKx7Hp279xy30LspMso+GzQvV2maYePMAWdmrzqSNZhUpPj3CGw12aGj57I026PgLCTu8CGg==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.14.1: + resolution: {integrity: sha512-wQGI+LY/Py20zdUPq+XCem7JcPOyzIJBm3dli+56DJsQOHbnXZFEwgmnC6el1TPAfC8lBT3m+z69RmLykNUbew==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@solid-devtools/debugger@0.23.4(solid-js@1.8.16): + resolution: {integrity: sha512-EfTB1Eo313wztQYGJ4Ec/wE70Ay2d603VCXfT3RlyqO5QfLrQGRHX5NXC07hJpQTJJJ3tbNgzO7+ZKo76MM5uA==} + peerDependencies: + solid-js: ^1.8.0 + dependencies: + '@nothing-but/utils': 0.12.1 + '@solid-devtools/shared': 0.13.2(solid-js@1.8.16) + '@solid-primitives/bounds': 0.0.118(solid-js@1.8.16) + '@solid-primitives/cursor': 0.0.112(solid-js@1.8.16) + '@solid-primitives/event-bus': 1.0.11(solid-js@1.8.16) + '@solid-primitives/event-listener': 2.3.3(solid-js@1.8.16) + '@solid-primitives/keyboard': 1.2.8(solid-js@1.8.16) + '@solid-primitives/platform': 0.1.2(solid-js@1.8.16) + '@solid-primitives/rootless': 1.4.5(solid-js@1.8.16) + '@solid-primitives/scheduled': 1.4.3(solid-js@1.8.16) + '@solid-primitives/static-store': 0.0.5(solid-js@1.8.16) + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-devtools/shared@0.13.2(solid-js@1.8.16): + resolution: {integrity: sha512-Y4uaC4EfTVwBR537MZwfaY/eiWAh+hW4mbtnwNuUw/LFmitHSkQhNQTUlLQv/S0chtwrYWQBxvXos1dC7e8R9g==} + peerDependencies: + solid-js: ^1.8.0 + dependencies: + '@solid-primitives/event-bus': 1.0.11(solid-js@1.8.16) + '@solid-primitives/event-listener': 2.3.3(solid-js@1.8.16) + '@solid-primitives/media': 2.2.8(solid-js@1.8.16) + '@solid-primitives/refs': 1.0.8(solid-js@1.8.16) + '@solid-primitives/rootless': 1.4.5(solid-js@1.8.16) + '@solid-primitives/scheduled': 1.4.3(solid-js@1.8.16) + '@solid-primitives/static-store': 0.0.5(solid-js@1.8.16) + '@solid-primitives/styles': 0.0.111(solid-js@1.8.16) + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/bounds@0.0.118(solid-js@1.8.16): + resolution: {integrity: sha512-Qj42w8LlnhJ3r/t+t0c0vrdwIvvQMPgjEFGmLiwREaA85ojLbgL9lSBq2tKvljeLCvRVkgj10KEUf+vc99VCIg==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/event-listener': 2.3.3(solid-js@1.8.16) + '@solid-primitives/resize-observer': 2.0.25(solid-js@1.8.16) + '@solid-primitives/static-store': 0.0.5(solid-js@1.8.16) + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/cursor@0.0.112(solid-js@1.8.16): + resolution: {integrity: sha512-TAtU7qD7ipSLSXHnq8FhhosAPVX+dnOCb/ITcGcLlj8e/C9YKcxDhgBHJ3R/d1xDRb5/vO/szJtEz6fnQD311Q==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/event-bus@1.0.11(solid-js@1.8.16): + resolution: {integrity: sha512-bSwVA4aI2aNHomSbEroUnisMSyDDXJbrw4U8kFEvrcYdlLrJX5i6QeCFx+vj/zdQQw62KAllrEIyWP8KMpPVnQ==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/event-listener@2.3.3(solid-js@1.8.16): + resolution: {integrity: sha512-DAJbl+F0wrFW2xmcV8dKMBhk9QLVLuBSW+TR4JmIfTaObxd13PuL7nqaXnaYKDWOYa6otB00qcCUIGbuIhSUgQ==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/keyboard@1.2.8(solid-js@1.8.16): + resolution: {integrity: sha512-pJtcbkjozS6L1xvTht9rPpyPpX55nAkfBzbFWdf3y0Suwh6qClTibvvObzKOf7uzQ+8aZRDH4LsoGmbTKXtJjQ==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/event-listener': 2.3.3(solid-js@1.8.16) + '@solid-primitives/rootless': 1.4.5(solid-js@1.8.16) + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/media@2.2.8(solid-js@1.8.16): + resolution: {integrity: sha512-jcwTxjEn07W5KEeQIc0nR+07xRjvsWTf115PIwScCWgo6aPkfW3x74aq7lH5F3mLfb/9SeTn0ixz8fBVel3cHg==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/event-listener': 2.3.3(solid-js@1.8.16) + '@solid-primitives/rootless': 1.4.5(solid-js@1.8.16) + '@solid-primitives/static-store': 0.0.8(solid-js@1.8.16) + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/platform@0.1.2(solid-js@1.8.16): + resolution: {integrity: sha512-sSxcZfuUrtxcwV0vdjmGnZQcflACzMfLriVeIIWXKp8hzaS3Or3tO6EFQkTd3L8T5dTq+kTtLvPscXIpL0Wzdg==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + solid-js: 1.8.16 + dev: true + + /@solid-primitives/refs@1.0.8(solid-js@1.8.16): + resolution: {integrity: sha512-+jIsWG8/nYvhaCoG2Vg6CJOLgTmPKFbaCrNQKWfChalgUf9WrVxWw0CdJb3yX15n5lUcQ0jBo6qYtuVVmBLpBw==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/resize-observer@2.0.25(solid-js@1.8.16): + resolution: {integrity: sha512-jVDXkt2MiriYRaz4DYs62185d+6jQ+1DCsR+v7f6XMsIJJuf963qdBRFjtZtKXBaxdPNMyuPeDgf5XQe3EoDJg==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/event-listener': 2.3.3(solid-js@1.8.16) + '@solid-primitives/rootless': 1.4.5(solid-js@1.8.16) + '@solid-primitives/static-store': 0.0.8(solid-js@1.8.16) + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/rootless@1.4.5(solid-js@1.8.16): + resolution: {integrity: sha512-GFJE9GC3ojx0aUKqAUZmQPyU8fOVMtnVNrkdk2yS4kd17WqVSpXpoTmo9CnOwA+PG7FTzdIkogvfLQSLs4lrww==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/scheduled@1.4.3(solid-js@1.8.16): + resolution: {integrity: sha512-HfWN5w7b7FEc6VPLBKnnE302h90jsLMuR28Fcf7neRGGf8jBj6wm6/UFQ00VlKexHFMR6KQ2u4VBh5a1ZcqM8g==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + solid-js: 1.8.16 + dev: true + + /@solid-primitives/static-store@0.0.5(solid-js@1.8.16): + resolution: {integrity: sha512-ssQ+s/wrlFAEE4Zw8GV499yBfvWx7SMm+ZVc11wvao4T5xg9VfXCL9Oa+x4h+vPMvSV/Knv5LrsLiUa+wlJUXQ==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/static-store@0.0.8(solid-js@1.8.16): + resolution: {integrity: sha512-ZecE4BqY0oBk0YG00nzaAWO5Mjcny8Fc06CdbXadH9T9lzq/9GefqcSe/5AtdXqjvY/DtJ5C6CkcjPZO0o/eqg==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/styles@0.0.111(solid-js@1.8.16): + resolution: {integrity: sha512-1mBxOGAPXmfD5oYCvqjKBDN7SuNjz2qz7RdH7KtsuNLQh6lpuSKadtHnLvru0Y8Vz1InqTJisBIy/6P5kyDmPw==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/rootless': 1.4.5(solid-js@1.8.16) + '@solid-primitives/utils': 6.2.3(solid-js@1.8.16) + solid-js: 1.8.16 + dev: true + + /@solid-primitives/utils@6.2.3(solid-js@1.8.16): + resolution: {integrity: sha512-CqAwKb2T5Vi72+rhebSsqNZ9o67buYRdEJrIFzRXz3U59QqezuuxPsyzTSVCacwS5Pf109VRsgCJQoxKRoECZQ==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + solid-js: 1.8.16 + dev: true + + /@solidjs/router@0.13.1(solid-js@1.8.16): + resolution: {integrity: sha512-Rz5Lf0ssWMuN+Wm2GFO0vwZoO/KSwYFSuCUzWrRAvje5M0ZYZrMk5FZxuzdJT+zg8KuqWJQlRALks5E0r+FjAA==} + peerDependencies: + solid-js: ^1.8.6 + dependencies: + solid-js: 1.8.16 + dev: false + + /@tma.js/sdk-solid@2.0.1(@tma.js/sdk@1.5.1)(solid-js@1.8.16): + resolution: {integrity: sha512-UyvzaQgdNJ9DmQuBMI4nluvdFdELD/PONUUlGzI2Rx9fewatt/i6LWePiZ372kndsyK9mBTVMzdWpveR13kTWg==} + peerDependencies: + '@tma.js/sdk': 1.5.1 + solid-js: ^1.0.0 + dependencies: + '@tma.js/sdk': 1.5.1 + solid-js: 1.8.16 + dev: false + + /@tma.js/sdk@1.5.1: + resolution: {integrity: sha512-M0kzo840GntTuhd6ywYof3DPddhOxM7ODd0JlyJeTsJHexL2D0+REuFPLUNddDh66rUfXOaAdFU79WDVa6wy9A==} + dev: false + + /@tonconnect/isomorphic-eventsource@0.0.2: + resolution: {integrity: sha512-B4UoIjPi0QkvIzZH5fV3BQLWrqSYABdrzZQSI9sJA9aA+iC0ohOzFwVVGXanlxeDAy1bcvPbb29f6sVUk0UnnQ==} + dependencies: + eventsource: 2.0.2 + dev: false + + /@tonconnect/isomorphic-fetch@0.0.3: + resolution: {integrity: sha512-jIg5nTrDwnite4fXao3dD83eCpTvInTjZon/rZZrIftIegh4XxyVb5G2mpMqXrVGk1e8SVXm3Kj5OtfMplQs0w==} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + + /@tonconnect/protocol@2.2.6: + resolution: {integrity: sha512-kyoDz5EqgsycYP+A+JbVsAUYHNT059BCrK+m0pqxykMODwpziuSAXfwAZmHcg8v7NB9VKYbdFY55xKeXOuEd0w==} + dependencies: + tweetnacl: 1.0.3 + tweetnacl-util: 0.15.1 + dev: false + + /@tonconnect/sdk@3.0.0: + resolution: {integrity: sha512-pg0OC//c3LU6jwH2hiLJrDXxITIfNwj0tFTV55xS6FXF2I9qzvVKTUPo4OHr1w3MZVJ7oCw4uz7gKZ+bcqK2hg==} + dependencies: + '@tonconnect/isomorphic-eventsource': 0.0.2 + '@tonconnect/isomorphic-fetch': 0.0.3 + '@tonconnect/protocol': 2.2.6 + transitivePeerDependencies: + - encoding + dev: false + + /@tonconnect/ui@2.0.0: + resolution: {integrity: sha512-opwroucFYf45SbnuwLJJKrlObZTAGqcf29aZr9WuVEpwIPpREsRxK80QsUBD5s7HEqn5whAdvigN/NB4pRCaYw==} + dependencies: + '@tonconnect/sdk': 3.0.0 + classnames: 2.5.1 + deepmerge: 4.3.1 + ua-parser-js: 1.0.37 + transitivePeerDependencies: + - encoding + dev: false + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.5 + dev: true + + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + dev: true + + /@types/babel__traverse@7.20.5: + resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + dependencies: + '@babel/types': 7.24.0 + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/node@20.12.5: + resolution: {integrity: sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: true + + /@typescript-eslint/eslint-plugin@7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-gKmTNwZnblUdnTIJu3e9kmeRRzV2j1a/LUO27KNNAnIC5zjy1aSvXSRp4rVNlmAoHlQ7HzX42NbKpcSr4jF80A==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/scope-manager': 7.6.0 + '@typescript-eslint/type-utils': 7.6.0(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/visitor-keys': 7.6.0 + debug: 4.3.4 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.4) + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-usPMPHcwX3ZoPWnBnhhorc14NJw9J4HpSXQX4urF2TPKG0au0XhJoZyX62fmvdHONUkmyUe74Hzm1//XA+BoYg==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 7.6.0 + '@typescript-eslint/types': 7.6.0 + '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.4) + '@typescript-eslint/visitor-keys': 7.6.0 + debug: 4.3.4 + eslint: 8.57.0 + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.21.0: + resolution: {integrity: sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + dev: true + + /@typescript-eslint/scope-manager@7.6.0: + resolution: {integrity: sha512-ngttyfExA5PsHSx0rdFgnADMYQi+Zkeiv4/ZxGYUWd0nLs63Ha0ksmp8VMxAIC0wtCFxMos7Lt3PszJssG/E6w==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.6.0 + '@typescript-eslint/visitor-keys': 7.6.0 + dev: true + + /@typescript-eslint/type-utils@7.6.0(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-NxAfqAPNLG6LTmy7uZgpK8KcuiS2NZD/HlThPXQRGwz6u7MDBWRVliEEl1Gj6U7++kVJTpehkhZzCJLMK66Scw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.4) + '@typescript-eslint/utils': 7.6.0(eslint@8.57.0)(typescript@5.4.4) + debug: 4.3.4 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.4.4) + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.21.0: + resolution: {integrity: sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/types@7.6.0: + resolution: {integrity: sha512-h02rYQn8J+MureCvHVVzhl69/GAfQGPQZmOMjG1KfCl7o3HtMSlPaPUAPu6lLctXI5ySRGIYk94clD/AUMCUgQ==} + engines: {node: ^18.18.0 || >=20.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.21.0(typescript@5.4.4): + resolution: {integrity: sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/visitor-keys': 6.21.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.4) + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/typescript-estree@7.6.0(typescript@5.4.4): + resolution: {integrity: sha512-+7Y/GP9VuYibecrCQWSKgl3GvUM5cILRttpWtnAu8GNL9j11e4tbuGZmZjJ8ejnKYyBRb2ddGQ3rEFCq3QjMJw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 7.6.0 + '@typescript-eslint/visitor-keys': 7.6.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.4) + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.21.0(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 6.21.0 + '@typescript-eslint/types': 6.21.0 + '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.4.4) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/utils@7.6.0(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-x54gaSsRRI+Nwz59TXpCsr6harB98qjXYzsRxGqvA5Ue3kQH+FxS7FYU81g/omn22ML2pZJkisy6Q+ElK8pBCA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 7.6.0 + '@typescript-eslint/types': 7.6.0 + '@typescript-eslint/typescript-estree': 7.6.0(typescript@5.4.4) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.21.0: + resolution: {integrity: sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.21.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@typescript-eslint/visitor-keys@7.6.0: + resolution: {integrity: sha512-4eLB7t+LlNUmXzfOu1VAIAdkjbu5xNSerURS9X/S5TUKWFRpXRQZbmtPqgKmYx8bj3J0irtQXSiWAOY82v+cgw==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.6.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.3): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.3 + dev: true + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + dependencies: + dequal: 2.0.3 + dev: true + + /array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + dev: true + + /array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + get-intrinsic: 1.2.4 + is-string: 1.0.7 + dev: true + + /array-union@1.0.2: + resolution: {integrity: sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==} + engines: {node: '>=0.10.0'} + dependencies: + array-uniq: 1.0.3 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array-uniq@1.0.3: + resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} + engines: {node: '>=0.10.0'} + dev: true + + /array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-shim-unscopables: 1.0.2 + dev: true + + /arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + is-array-buffer: 3.0.4 + is-shared-array-buffer: 1.0.3 + dev: true + + /ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + dev: true + + /async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + dev: true + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: true + + /axe-core@4.7.0: + resolution: {integrity: sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==} + engines: {node: '>=4'} + dev: true + + /axobject-query@3.2.1: + resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==} + dependencies: + dequal: 2.0.3 + dev: true + + /babel-plugin-jsx-dom-expressions@0.37.19(@babel/core@7.24.4): + resolution: {integrity: sha512-nef2eLpWBgFggwrYwN6O3dNKn3RnlX6n4DIamNEAeHwp03kVQUaKUiLaEPnHPJHwxie1KwPelyIY9QikU03vUA==} + peerDependencies: + '@babel/core': ^7.20.12 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-module-imports': 7.18.6 + '@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.4) + '@babel/types': 7.24.0 + html-entities: 2.3.3 + validate-html-nesting: 1.2.2 + dev: true + + /babel-preset-solid@1.8.16(@babel/core@7.24.4): + resolution: {integrity: sha512-b4HFg/xaKM+H3Tu5iUlZ/43TJOZnhi85xrm3JrXDQ0s4cmtmU37bXXYzb2m55G4QKiFjxLAjvb7sUorPrAMs5w==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.4 + babel-plugin-jsx-dom-expressions: 0.37.19(@babel/core@7.24.4) + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001607 + electron-to-chromium: 1.4.730 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.23.0) + dev: true + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /caniuse-lite@1.0.30001607: + resolution: {integrity: sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==} + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /classnames@2.5.1: + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} + dev: false + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: true + + /commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /confusing-browser-globals@1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + /damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + dev: true + + /data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-data-view: 1.0.1 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: false + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: true + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: true + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /electron-to-chromium@1.4.730: + resolution: {integrity: sha512-oJRPo82XEqtQAobHpJIR3zW5YO3sSRRkPz2an4yxi1UvqhsGm54vR/wzTFV74a3soDOJ8CKW7ajOOX5ESzddwg==} + dev: true + + /email-addresses@5.0.0: + resolution: {integrity: sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /eruda@3.0.1: + resolution: {integrity: sha512-6q1Xdwga4JTr1mKSW4mzuWSSbmXgqpm/8Wa1QGFGfCWRjC0bCQjbS4u06M1te1moucIS3hBLlbSTPWYH2W0qbQ==} + dev: false + + /es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + arraybuffer.prototype.slice: 1.0.3 + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + data-view-buffer: 1.0.1 + data-view-byte-length: 1.0.1 + data-view-byte-offset: 1.0.0 + es-define-property: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.0.0 + es-set-tostringtag: 2.0.3 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.4 + get-symbol-description: 1.0.2 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + internal-slot: 1.0.7 + is-array-buffer: 3.0.4 + is-callable: 1.2.7 + is-data-view: 1.0.1 + is-negative-zero: 2.0.3 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + is-string: 1.0.7 + is-typed-array: 1.1.13 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + safe-array-concat: 1.1.2 + safe-regex-test: 1.0.3 + string.prototype.trim: 1.2.9 + string.prototype.trimend: 1.0.8 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.2 + typed-array-byte-length: 1.0.1 + typed-array-byte-offset: 1.0.2 + typed-array-length: 1.0.6 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.15 + dev: true + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: true + + /es-iterator-helpers@1.0.18: + resolution: {integrity: sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + es-set-tostringtag: 2.0.3 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + globalthis: 1.0.3 + has-property-descriptors: 1.0.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + internal-slot: 1.0.7 + iterator.prototype: 1.1.2 + safe-array-concat: 1.1.2 + dev: true + + /es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + dev: true + + /es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + dev: true + + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.2 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /esbuild@0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 + dev: true + + /escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0): + resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} + engines: {node: ^10.12.0 || >=12.0.0} + peerDependencies: + eslint: ^7.32.0 || ^8.2.0 + eslint-plugin-import: ^2.25.2 + dependencies: + confusing-browser-globals: 1.0.11 + eslint: 8.57.0 + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.6.0)(eslint@8.57.0) + object.assign: 4.1.5 + object.entries: 1.1.8 + semver: 6.3.1 + dev: true + + /eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.6.0)(@typescript-eslint/parser@7.6.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + resolution: {integrity: sha512-oc+Lxzgzsu8FQyFVa4QFaVKiitTYiiW3frB9KYW5OWdPrqFc7FzxgB20hP4cHMlr+MBzGcLl3jnCOVOydL9mIg==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^7.0.0 + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + dependencies: + '@typescript-eslint/eslint-plugin': 7.6.0(@typescript-eslint/parser@7.6.0)(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.4) + eslint: 8.57.0 + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0) + transitivePeerDependencies: + - eslint-plugin-import + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils@2.8.1(@typescript-eslint/parser@7.6.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): + resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.4) + debug: 3.2.7 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.6.0)(eslint@8.57.0): + resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 7.6.0(eslint@8.57.0)(typescript@5.4.4) + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.6.0)(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) + hasown: 2.0.2 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.0 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0): + resolution: {integrity: sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 + dependencies: + '@babel/runtime': 7.24.4 + aria-query: 5.3.0 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.2 + ast-types-flow: 0.0.8 + axe-core: 4.7.0 + axobject-query: 3.2.1 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + es-iterator-helpers: 1.0.18 + eslint: 8.57.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + dev: true + + /eslint-plugin-simple-import-sort@12.0.0(eslint@8.57.0): + resolution: {integrity: sha512-8o0dVEdAkYap0Cn5kNeklaKcT1nUsa3LITWEuFk3nJifOoD+5JQGoyDUW2W/iPWwBsNBJpyJS9y4je/BgxLcyQ==} + peerDependencies: + eslint: '>=5.0.0' + dependencies: + eslint: 8.57.0 + dev: true + + /eslint-plugin-solid@0.13.2(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-Ndeuc6MEO11YVqzIzxtKKEG0t4HPJ4ob/WQyduwpTW//NtyZqWx/gPii5GF656DLqBbsfsmMaX0zkFQ8ElyOdQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@typescript-eslint/utils': 6.21.0(eslint@8.57.0)(typescript@5.4.4) + eslint: 8.57.0 + estraverse: 5.3.0 + is-html: 2.0.0 + kebab-case: 1.0.2 + known-css-properties: 0.24.0 + style-to-object: 0.3.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.1 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /eventsource@2.0.2: + resolution: {integrity: sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==} + engines: {node: '>=12.0.0'} + dev: false + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + dependencies: + reusify: 1.0.4 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /filename-reserved-regex@2.0.0: + resolution: {integrity: sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==} + engines: {node: '>=4'} + dev: true + + /filenamify@4.3.0: + resolution: {integrity: sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==} + engines: {node: '>=8'} + dependencies: + filename-reserved-regex: 2.0.0 + strip-outer: 1.0.1 + trim-repeated: 1.0.0 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.3.1 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: true + + /get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + dev: true + + /gh-pages@6.1.1: + resolution: {integrity: sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + async: 3.2.5 + commander: 11.1.0 + email-addresses: 5.0.0 + filenamify: 4.3.0 + find-cache-dir: 3.3.2 + fs-extra: 11.2.0 + globby: 6.1.0 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globby@6.1.0: + resolution: {integrity: sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==} + engines: {node: '>=0.10.0'} + dependencies: + array-union: 1.0.2 + glob: 7.2.3 + object-assign: 4.1.1 + pify: 2.3.0 + pinkie-promise: 2.0.1 + dev: true + + /globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: true + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /html-entities@2.3.3: + resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + dev: true + + /html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + dev: true + + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /inline-style-parser@0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + dev: true + + /internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + dev: true + + /is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-async-function@2.0.0: + resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.2 + dev: true + + /is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + dependencies: + is-typed-array: 1.1.13 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-finalizationregistry@1.0.2: + resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-html@2.0.0: + resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==} + engines: {node: '>=8'} + dependencies: + html-tags: 3.3.1 + dev: true + + /is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + dev: true + + /is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + dev: true + + /is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.15 + dev: true + + /is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /iterator.prototype@1.1.2: + resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} + dependencies: + define-properties: 1.2.1 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + reflect.getprototypeof: 1.0.6 + set-function-name: 2.0.2 + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.2 + object.assign: 4.1.5 + object.values: 1.2.0 + dev: true + + /kebab-case@1.0.2: + resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /known-css-properties@0.24.0: + resolution: {integrity: sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==} + dev: true + + /language-subtag-registry@0.3.22: + resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + dev: true + + /language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + dependencies: + language-subtag-registry: 0.3.22 + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + dependencies: + semver: 6.3.1 + dev: true + + /merge-anything@5.1.7: + resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.16 + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + dependencies: + whatwg-url: 5.0.0 + dev: false + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: true + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.entries@1.1.8: + resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + dev: true + + /object.values@1.2.0: + resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + dev: true + + /pinkie-promise@2.0.1: + resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} + engines: {node: '>=0.10.0'} + dependencies: + pinkie: 2.0.4 + dev: true + + /pinkie@2.0.4: + resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} + engines: {node: '>=0.10.0'} + dev: true + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: true + + /postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.2.0 + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /reflect.getprototypeof@1.0.6: + resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + globalthis: 1.0.3 + which-builtin-type: 1.1.3 + dev: true + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + + /regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup@4.14.1: + resolution: {integrity: sha512-4LnHSdd3QK2pa1J6dFbfm1HN0D7vSK/ZuZTsdyUAlA6Rr1yTouUTL13HaDOGJVgby461AhrNGBS7sCGXXtT+SA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.14.1 + '@rollup/rollup-android-arm64': 4.14.1 + '@rollup/rollup-darwin-arm64': 4.14.1 + '@rollup/rollup-darwin-x64': 4.14.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.14.1 + '@rollup/rollup-linux-arm64-gnu': 4.14.1 + '@rollup/rollup-linux-arm64-musl': 4.14.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.14.1 + '@rollup/rollup-linux-riscv64-gnu': 4.14.1 + '@rollup/rollup-linux-s390x-gnu': 4.14.1 + '@rollup/rollup-linux-x64-gnu': 4.14.1 + '@rollup/rollup-linux-x64-musl': 4.14.1 + '@rollup/rollup-win32-arm64-msvc': 4.14.1 + '@rollup/rollup-win32-ia32-msvc': 4.14.1 + '@rollup/rollup-win32-x64-msvc': 4.14.1 + fsevents: 2.3.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-regex: 1.1.4 + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /seroval-plugins@1.0.5(seroval@1.0.5): + resolution: {integrity: sha512-8+pDC1vOedPXjKG7oz8o+iiHrtF2WswaMQJ7CKFpccvSYfrzmvKY9zOJWCg+881722wIHfwkdnRmiiDm9ym+zQ==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + dependencies: + seroval: 1.0.5 + + /seroval@1.0.5: + resolution: {integrity: sha512-TM+Z11tHHvQVQKeNlOUonOWnsNM+2IBwZ4vwoi4j3zKzIpc5IDw8WPwCfcc8F17wy6cBcJGbZbFOR0UCuTZHQA==} + engines: {node: '>=10'} + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + dev: true + + /set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /solid-devtools@0.30.1(solid-js@1.8.16)(vite@5.2.8): + resolution: {integrity: sha512-axpXL4JV1dnGhuei+nSGS8ewGeNkmIgFDsAlO90YyYY5t8wU1R0aYAQtL+I+5KICLKPBvfkzdcFa2br7AV4lAw==} + peerDependencies: + solid-js: ^1.8.0 + solid-start: ^0.3.0 + vite: ^2.2.3 || ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + solid-start: + optional: true + vite: + optional: true + dependencies: + '@babel/core': 7.24.4 + '@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.4) + '@babel/types': 7.24.0 + '@solid-devtools/debugger': 0.23.4(solid-js@1.8.16) + '@solid-devtools/shared': 0.13.2(solid-js@1.8.16) + solid-js: 1.8.16 + vite: 5.2.8(@types/node@20.12.5) + transitivePeerDependencies: + - supports-color + dev: true + + /solid-js@1.8.16: + resolution: {integrity: sha512-rja94MNU9flF3qQRLNsu60QHKBDKBkVE1DldJZPIfn2ypIn3NV2WpSbGTQIvsyGPBo+9E2IMjwqnqpbgfWuzeg==} + dependencies: + csstype: 3.1.3 + seroval: 1.0.5 + seroval-plugins: 1.0.5(seroval@1.0.5) + + /solid-refresh@0.6.3(solid-js@1.8.16): + resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} + peerDependencies: + solid-js: ^1.3 + dependencies: + '@babel/generator': 7.24.4 + '@babel/helper-module-imports': 7.24.3 + '@babel/types': 7.24.0 + solid-js: 1.8.16 + dev: true + + /source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + dev: true + + /string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-abstract: 1.23.3 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-object-atoms: 1.0.0 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strip-outer@1.0.1: + resolution: {integrity: sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==} + engines: {node: '>=0.10.0'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /style-to-object@0.3.0: + resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} + dependencies: + inline-style-parser: 0.1.1 + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + dev: false + + /trim-repeated@1.0.0: + resolution: {integrity: sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==} + engines: {node: '>=0.10.0'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /ts-api-utils@1.3.0(typescript@5.4.4): + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.4.4 + dev: true + + /tsconfck@3.0.3(typescript@5.4.4): + resolution: {integrity: sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + dependencies: + typescript: 5.4.4 + dev: true + + /tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tweetnacl-util@0.15.1: + resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} + dev: false + + /tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + dev: false + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + dev: true + + /typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + dev: true + + /typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-proto: 1.0.3 + is-typed-array: 1.1.13 + possible-typed-array-names: 1.0.0 + dev: true + + /typescript@5.4.4: + resolution: {integrity: sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /ua-parser-js@1.0.37: + resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} + dev: false + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.7 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /update-browserslist-db@1.0.13(browserslist@4.23.0): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.23.0 + escalade: 3.1.2 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /validate-html-nesting@1.2.2: + resolution: {integrity: sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==} + dev: true + + /vite-plugin-solid@2.10.2(solid-js@1.8.16)(vite@5.2.8): + resolution: {integrity: sha512-AOEtwMe2baBSXMXdo+BUwECC8IFHcKS6WQV/1NEd+Q7vHPap5fmIhLcAzr+DUJ04/KHx/1UBU0l1/GWP+rMAPQ==} + peerDependencies: + '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.* + solid-js: ^1.7.2 + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + '@testing-library/jest-dom': + optional: true + dependencies: + '@babel/core': 7.24.4 + '@types/babel__core': 7.20.5 + babel-preset-solid: 1.8.16(@babel/core@7.24.4) + merge-anything: 5.1.7 + solid-js: 1.8.16 + solid-refresh: 0.6.3(solid-js@1.8.16) + vite: 5.2.8(@types/node@20.12.5) + vitefu: 0.2.5(vite@5.2.8) + transitivePeerDependencies: + - supports-color + dev: true + + /vite-tsconfig-paths@4.3.2(typescript@5.4.4)(vite@5.2.8): + resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==} + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + debug: 4.3.4 + globrex: 0.1.2 + tsconfck: 3.0.3(typescript@5.4.4) + vite: 5.2.8(@types/node@20.12.5) + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /vite@5.2.8(@types/node@20.12.5): + resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.12.5 + esbuild: 0.20.2 + postcss: 8.4.38 + rollup: 4.14.1 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vitefu@0.2.5(vite@5.2.8): + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 5.2.8(@types/node@20.12.5) + dev: true + + /webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + dev: false + + /whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + dev: false + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-builtin-type@1.1.3: + resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} + engines: {node: '>= 0.4'} + dependencies: + function.prototype.name: 1.1.6 + has-tostringtag: 1.0.2 + is-async-function: 2.0.0 + is-date-object: 1.0.5 + is-finalizationregistry: 1.0.2 + is-generator-function: 1.0.10 + is-regex: 1.1.4 + is-weakref: 1.0.2 + isarray: 2.0.5 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.15 + dev: true + + /which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + dev: true + + /which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/apps/solid/public/tonconnect-manifest.json b/apps/solid/public/tonconnect-manifest.json new file mode 100644 index 000000000..0bb056f4f --- /dev/null +++ b/apps/solid/public/tonconnect-manifest.json @@ -0,0 +1,5 @@ +{ + "url": "https://ton.vote", + "name": "TON Vote", + "iconUrl": "https://ton.vote/logo.png" +} \ No newline at end of file diff --git a/apps/solid/src/components/App.tsx b/apps/solid/src/components/App.tsx new file mode 100644 index 000000000..58ea97be8 --- /dev/null +++ b/apps/solid/src/components/App.tsx @@ -0,0 +1,53 @@ +import { Navigate, Route } from '@solidjs/router'; +import { + initNavigator, + bindMiniAppCSSVars, + bindThemeParamsCSSVars, + bindViewportCSSVars, + useMiniApp, + useThemeParams, + useViewport, +} from '@tma.js/sdk-solid'; +import { createRouter } from '@tma.js/solid-router-integration'; +import { createEffect, For, onCleanup } from 'solid-js'; + +import { routes } from '@/navigation/routes.js'; + +export function App() { + const miniApp = useMiniApp(); + const themeParams = useThemeParams(); + const viewport = useViewport(); + + createEffect(() => { + onCleanup(bindMiniAppCSSVars(miniApp(), themeParams())); + }); + createEffect(() => { + onCleanup(bindThemeParamsCSSVars(themeParams())); + }); + createEffect(() => { + const vp = viewport(); + if (vp) { + onCleanup(bindViewportCSSVars(vp)); + } + }); + + // Create new application navigator and attach it to the browser history, so it could modify + // it and listen to its changes. + const navigator = initNavigator('app-navigator-state', { hashMode: 'default' }); + void navigator.attach(); + + onCleanup(() => { + navigator.detach(); + }); + + const Router = createRouter(navigator); + + return ( + + + {(route) => } + + }/> + + ); +} diff --git a/apps/solid/src/components/DisplayData/DisplayData.css b/apps/solid/src/components/DisplayData/DisplayData.css new file mode 100644 index 000000000..226ee602d --- /dev/null +++ b/apps/solid/src/components/DisplayData/DisplayData.css @@ -0,0 +1,19 @@ +.display-data__line { + display: flex; + align-items: center; + margin-bottom: 8px; + gap: 10px; + flex-flow: wrap; +} + +.display-data__line-title { + border: 1px solid var(--tg-theme-accent-text-color); + background-color: var(--tg-theme-bg-color); + border-radius: 5px; + padding: 2px 8px 4px; + box-sizing: border-box; +} + +.display-data__line-value { + word-break: break-word; +} diff --git a/apps/solid/src/components/DisplayData/DisplayData.tsx b/apps/solid/src/components/DisplayData/DisplayData.tsx new file mode 100644 index 000000000..2d7feccc5 --- /dev/null +++ b/apps/solid/src/components/DisplayData/DisplayData.tsx @@ -0,0 +1,39 @@ +import { isRGB, type RGB as RGBType } from '@tma.js/sdk-solid'; +import { type Component, For, type JSXElement, Match, Switch } from 'solid-js'; + +import { RGB } from '@/components/RGB/RGB.js'; + +import './DisplayData.css'; + +export interface DisplayDataRow { + title: string; + value?: RGBType | string | boolean | JSXElement; +} + +export interface DisplayDataProps { + rows: DisplayDataRow[]; +} + +export const DisplayData: Component = (props) => { + return ( +
+ + {(row) => ( +
+ {row.title} + + + + {(color) => } + + + ✔️ + empty + + +
+ )} +
+
+ ); +}; diff --git a/apps/solid/src/components/Link/Link.css b/apps/solid/src/components/Link/Link.css new file mode 100644 index 000000000..7251d5071 --- /dev/null +++ b/apps/solid/src/components/Link/Link.css @@ -0,0 +1,4 @@ +.link { + text-decoration: none; + color: var(--tg-theme-link-color); +} \ No newline at end of file diff --git a/apps/solid/src/components/Link/Link.tsx b/apps/solid/src/components/Link/Link.tsx new file mode 100644 index 000000000..42d62b965 --- /dev/null +++ b/apps/solid/src/components/Link/Link.tsx @@ -0,0 +1,31 @@ +import { A, type AnchorProps } from '@solidjs/router'; +import { classNames, useUtils } from '@tma.js/sdk-solid'; +import type { Component } from 'solid-js'; + +import './Link.css'; + +export const Link: Component = (props) => { + const utils = useUtils(); + + const onClick = (e: MouseEvent) => { + // Compute if target path is external. In this case we would like to open link using + // TMA method. + const targetUrl = new URL(props.href, window.location.toString()); + const currentUrl = new URL(window.location.toString()); + const isExternal = targetUrl.protocol !== currentUrl.protocol + || targetUrl.host !== currentUrl.host; + + if (isExternal) { + e.preventDefault(); + return utils().openLink(targetUrl.toString()); + } + }; + + return ( + + ); +}; diff --git a/apps/solid/src/components/Page/Page.css b/apps/solid/src/components/Page/Page.css new file mode 100644 index 000000000..8c7b788da --- /dev/null +++ b/apps/solid/src/components/Page/Page.css @@ -0,0 +1,8 @@ +.page { + padding: 0 10px; + box-sizing: border-box; +} + +.page__disclaimer { + margin-bottom: 16px; +} \ No newline at end of file diff --git a/apps/solid/src/components/Page/Page.tsx b/apps/solid/src/components/Page/Page.tsx new file mode 100644 index 000000000..34674065d --- /dev/null +++ b/apps/solid/src/components/Page/Page.tsx @@ -0,0 +1,18 @@ +import type { Component, JSX, ParentProps } from 'solid-js'; + +import './Page.css'; + +export interface PageProps extends ParentProps { + title: string; + disclaimer?: JSX.Element; +} + +export const Page: Component = (props) => { + return ( +
+

{props.title}

+ {props.disclaimer &&
{props.disclaimer}
} + {props.children} +
+ ); +}; diff --git a/apps/solid/src/components/RGB/RGB.css b/apps/solid/src/components/RGB/RGB.css new file mode 100644 index 000000000..fec07994e --- /dev/null +++ b/apps/solid/src/components/RGB/RGB.css @@ -0,0 +1,12 @@ +.rgb { + display: inline-flex; + align-items: center; + gap: 5px; +} + +.rgb__icon { + width: 18px; + aspect-ratio: 1; + border: 1px solid #555; + border-radius: 50%; +} \ No newline at end of file diff --git a/apps/solid/src/components/RGB/RGB.tsx b/apps/solid/src/components/RGB/RGB.tsx new file mode 100644 index 000000000..1c2638881 --- /dev/null +++ b/apps/solid/src/components/RGB/RGB.tsx @@ -0,0 +1,15 @@ +import { classNames, type RGB as RGBType } from '@tma.js/sdk-solid'; +import { type Component, type JSX, splitProps } from 'solid-js'; + +import './RGB.css'; + +export type RGBProps = JSX.IntrinsicElements['span'] & { + color: RGBType; +}; + +export const RGB: Component = (props) => ( + + + {props.color} + +); diff --git a/apps/solid/src/components/Root.tsx b/apps/solid/src/components/Root.tsx new file mode 100644 index 000000000..df991d989 --- /dev/null +++ b/apps/solid/src/components/Root.tsx @@ -0,0 +1,56 @@ +import { + retrieveLaunchParams, + SDKProvider, + setDebug, +} from '@tma.js/sdk-solid'; +import { ErrorBoundary, type Component, Switch, Match } from 'solid-js'; + +import { App } from '@/components/App.js'; +import { TonConnectUIProvider } from '@/tonconnect/TonConnectUIProvider.js'; + +const Inner: Component = () => { + if (retrieveLaunchParams().startParam === 'debug') { + setDebug(true); + import('eruda').then((lib) => lib.default.init()); + } + + return ( + + + + + + ); +}; + +export const Root: Component = () => { + return ( + { + console.error('ErrorBoundary handled error:', err); + + return ( +
+

ErrorBoundary handled error:

+
+ + + + {v => v()} + + + {v => v()} + + + +
+
+ ); + }} + > + +
+ ); +}; diff --git a/apps/solid/src/index.css b/apps/solid/src/index.css new file mode 100644 index 000000000..334d2cf5e --- /dev/null +++ b/apps/solid/src/index.css @@ -0,0 +1,25 @@ +body { + font-family: -apple-system, BlinkMacSystemFont, 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + line-height: 1.5; + + background: var(--tg-theme-secondary-bg-color, white); + color: var(--tg-theme-text-color, black); +} + +blockquote { + margin: 0; +} + +blockquote p { + padding: 15px; + background: #eee; + border-radius: 5px; +} + +pre { + overflow: auto; +} \ No newline at end of file diff --git a/apps/solid/src/index.tsx b/apps/solid/src/index.tsx new file mode 100644 index 000000000..7920feac8 --- /dev/null +++ b/apps/solid/src/index.tsx @@ -0,0 +1,17 @@ +/* @refresh reload */ +import { render } from 'solid-js/web'; + +import './index.css'; + +import { Root } from '@/components/Root.js'; + +const root = document.getElementById('root'); + +if (import.meta.env.DEV && !(root instanceof HTMLElement)) { + throw new Error( + 'Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got misspelled?', + ); +} + +render(() => (), root!); + diff --git a/apps/solid/src/navigation/routes.tsx b/apps/solid/src/navigation/routes.tsx new file mode 100644 index 000000000..9bde4e58a --- /dev/null +++ b/apps/solid/src/navigation/routes.tsx @@ -0,0 +1,44 @@ +import type { Component } from 'solid-js'; + +import { IndexPage } from '@/pages/IndexPage/IndexPage.js'; +import { InitDataPage } from '@/pages/InitDataPage/InitDataPage.js'; +import { LaunchParamsPage } from '@/pages/LaunchParamsPage.js'; +import { ThemeParamsPage } from '@/pages/ThemeParamsPage.js'; +import { TonConnectPage } from '@/pages/TonConnectPage/TonConnectPage.js'; + +interface Route { + path: string; + Component: Component; + title?: string; + Icon?: Component; +} + +export const routes: Route[] = [ + { path: '/', Component: IndexPage }, + { path: '/init-data', Component: InitDataPage, title: 'Init Data' }, + { path: '/theme-params', Component: ThemeParamsPage, title: 'Theme Params' }, + { path: '/launch-params', Component: LaunchParamsPage, title: 'Launch Params' }, + { + path: '/ton-connect', + Component: TonConnectPage, + title: 'TON Connect', + Icon: () => ( + + + + + ), + }, +]; diff --git a/apps/solid/src/pages/IndexPage/IndexPage.css b/apps/solid/src/pages/IndexPage/IndexPage.css new file mode 100644 index 000000000..eddc134e6 --- /dev/null +++ b/apps/solid/src/pages/IndexPage/IndexPage.css @@ -0,0 +1,23 @@ +.index-page__links { + list-style: none; + padding-left: 0; +} + +.index-page__link { + font-weight: bold; + display: inline-flex; + gap: 5px; +} + +.index-page__link-item + .index-page__link-item { + margin-top: 10px; +} + +.index-page__link-icon { + width: 20px; + display: block; +} + +.index-page__link-icon svg { + display: block; +} \ No newline at end of file diff --git a/apps/solid/src/pages/IndexPage/IndexPage.tsx b/apps/solid/src/pages/IndexPage/IndexPage.tsx new file mode 100644 index 000000000..6b43b192f --- /dev/null +++ b/apps/solid/src/pages/IndexPage/IndexPage.tsx @@ -0,0 +1,39 @@ +import { For, Show, type Component } from 'solid-js'; +import { Dynamic } from 'solid-js/web'; + +import { Link } from '@/components/Link/Link.js'; +import { Page } from '@/components/Page/Page.js'; +import { routes } from '@/navigation/routes.js'; + +import './IndexPage.css'; + +export const IndexPage: Component = () => { + return ( + +

+ This page is a home page in this boilerplate. You can use the links below to visit other + pages with their own functionality. +

+ +
+ ); +}; diff --git a/apps/solid/src/pages/InitDataPage/InitDataPage.css b/apps/solid/src/pages/InitDataPage/InitDataPage.css new file mode 100644 index 000000000..fab4ae0a7 --- /dev/null +++ b/apps/solid/src/pages/InitDataPage/InitDataPage.css @@ -0,0 +1,7 @@ +.init-data-page__section + .init-data-page__section { + margin-top: 12px; +} + +.init-data-page__section-title { + margin-bottom: 4px; +} \ No newline at end of file diff --git a/apps/solid/src/pages/InitDataPage/InitDataPage.tsx b/apps/solid/src/pages/InitDataPage/InitDataPage.tsx new file mode 100644 index 000000000..4ea8ee95f --- /dev/null +++ b/apps/solid/src/pages/InitDataPage/InitDataPage.tsx @@ -0,0 +1,115 @@ +import { retrieveLaunchParams, useInitData, type User } from '@tma.js/sdk-solid'; +import { createMemo, Show } from 'solid-js'; +import type { Component } from 'solid-js'; + +import { DisplayData, type DisplayDataRow } from '@/components/DisplayData/DisplayData.js'; +import { Link } from '@/components/Link/Link.js'; +import { Page } from '@/components/Page/Page.js'; + +import './InitDataPage.css'; + +function getUserRows(user: User): DisplayDataRow[] { + return [ + { title: 'id', value: user.id.toString() }, + { title: 'last_name', value: user.lastName }, + { title: 'first_name', value: user.firstName }, + { title: 'is_bot', value: user.isBot }, + { title: 'is_premium', value: user.isPremium }, + { title: 'language_code', value: user.languageCode }, + ]; +} + +export const InitDataPage: Component = () => { + const initData = useInitData(); + const initDataRaw = retrieveLaunchParams().initDataRaw; + + const initDataRows = createMemo(() => { + const complete = initData(); + + return complete && initDataRaw + ? [ + { title: 'raw', value: initDataRaw }, + { title: 'auth_date', value: complete.authDate.toLocaleString() }, + { title: 'auth_date (raw)', value: complete.authDate.getTime() / 1000 }, + { title: 'hash', value: complete.hash }, + { title: 'can_send_after', value: complete.canSendAfterDate?.toISOString() }, + { title: 'can_send_after (raw)', value: complete.canSendAfter }, + { title: 'query_id', value: complete.queryId }, + { title: 'start_param', value: complete.startParam }, + { title: 'chat_type', value: complete.chatType }, + { title: 'chat_instance', value: complete.chatInstance }, + ] + : undefined; + }); + + const userRows = createMemo(() => { + const user = initData()?.user; + return user ? getUserRows(user) : undefined; + }); + + const receiverRows = createMemo(() => { + const receiver = initData()?.receiver; + return receiver ? getUserRows(receiver) : undefined; + }); + + const chatRows = createMemo(() => { + const chat = initData()?.chat; + return chat + ? [ + { title: 'id', value: chat.id.toString() }, + { title: 'title', value: chat.title }, + { title: 'type', value: chat.type }, + { title: 'username', value: chat.username }, + { title: 'photo_url', value: chat.photoUrl }, + ] + : undefined; + }); + + return ( + + This page displays application + {' '} + + init data + + . + + )} + > + Application was launched with missing init data
}> + {(rows) => ( + <> +
+

Init data

+ +
+ +
+

User

+ User information missing
}> + {(uRows) => } + +
+ +
+

Receiver

+ Receiver information missing}> + {(rRows) => } + +
+ +
+

Chat

+ Chat information missing}> + {(cRows) => } + +
+ + )} + + + ); +}; diff --git a/apps/solid/src/pages/LaunchParamsPage.tsx b/apps/solid/src/pages/LaunchParamsPage.tsx new file mode 100644 index 000000000..c451e5d5a --- /dev/null +++ b/apps/solid/src/pages/LaunchParamsPage.tsx @@ -0,0 +1,38 @@ +import { retrieveLaunchParams } from '@tma.js/sdk-solid'; +import type { Component } from 'solid-js'; + +import { DisplayData } from '@/components/DisplayData/DisplayData.js'; +import { Link } from '@/components/Link/Link.js'; +import { Page } from '@/components/Page/Page.js'; + +export const LaunchParamsPage: Component = () => { + const lp = retrieveLaunchParams(); + + return ( + + This page displays application + {' '} + + launch parameters + + . + + )} + > + View }, + { title: 'tgWebAppThemeParams', value: View }, + ]} + /> + + ); +}; diff --git a/apps/solid/src/pages/ThemeParamsPage.tsx b/apps/solid/src/pages/ThemeParamsPage.tsx new file mode 100644 index 000000000..79b7ccd85 --- /dev/null +++ b/apps/solid/src/pages/ThemeParamsPage.tsx @@ -0,0 +1,39 @@ +import { useThemeParams } from '@tma.js/sdk-solid'; +import type { Component } from 'solid-js'; + +import { DisplayData } from '@/components/DisplayData/DisplayData.js'; +import { Link } from '@/components/Link/Link.js'; +import { Page } from '@/components/Page/Page.js'; + +export const ThemeParamsPage: Component = () => { + const themeParams = useThemeParams(); + + return ( + + This page displays current + {' '} + + theme parameters + + . It is reactive, so, changing theme externally will lead to this page updates. + + )} + > + ({ + title: title + .replace(/[A-Z]/g, (m) => `_${m.toLowerCase()}`) + .replace(/background/, 'bg'), + value, + })) + } + /> + + ); +}; diff --git a/apps/solid/src/pages/TonConnectPage/TonConnectPage.css b/apps/solid/src/pages/TonConnectPage/TonConnectPage.css new file mode 100644 index 000000000..f70f76dbb --- /dev/null +++ b/apps/solid/src/pages/TonConnectPage/TonConnectPage.css @@ -0,0 +1,34 @@ +.ton-connect-page__button-container { + display: flex; + align-items: center; + justify-content: flex-end; +} + +.ton-connect-page__provider { + display: flex; + align-items: center; + gap: 15px; + margin-bottom: 16px; +} + +.ton-connect-page__provider-image { + border-radius: 5px; +} + +.ton-connect-page__provider-meta { + display: flex; + flex-direction: column; +} + +.ton-connect-page__provider-wallet-name { + font-weight: bold; + font-size: 20px; + margin: 0; +} + +.ton-connect-page__provider-app-name { + opacity: .4; + font-weight: 400; + font-size: 14px; + vertical-align: top; +} \ No newline at end of file diff --git a/apps/solid/src/pages/TonConnectPage/TonConnectPage.tsx b/apps/solid/src/pages/TonConnectPage/TonConnectPage.tsx new file mode 100644 index 000000000..8f56ab528 --- /dev/null +++ b/apps/solid/src/pages/TonConnectPage/TonConnectPage.tsx @@ -0,0 +1,73 @@ +import { Show, type Component } from 'solid-js'; + +import { DisplayData } from '@/components/DisplayData/DisplayData.js'; +import { Link } from '@/components/Link/Link.js'; +import { Page } from '@/components/Page/Page.js'; +import { TonConnectButton } from '@/tonconnect/TonConnectButton.js'; +import { useTonWallet } from '@/tonconnect/useTonWallet.js'; + +import './TonConnectPage.css'; + +export const TonConnectPage: Component = () => { + const wallet = useTonWallet(); + + return ( + + + To display the data related to the TON Connect, it is required to connect your wallet. +

+ } + > + {(walletBasic) => { + const walletExtended = () => { + const w = walletBasic(); + return 'imageUrl' in w ? w : null; + }; + const account = () => walletBasic().account; + + return ( + <> + + {(w) => ( +
+ Provider logo +
+

+ {w().name}  + + ({w().appName}) + +

+ + About connected wallet + +
+
+ )} +
+ + + ); + }} +
+
+ +
+
+ ); +}; diff --git a/apps/solid/src/tonconnect/TonConnectButton.tsx b/apps/solid/src/tonconnect/TonConnectButton.tsx new file mode 100644 index 000000000..8b3108c94 --- /dev/null +++ b/apps/solid/src/tonconnect/TonConnectButton.tsx @@ -0,0 +1,18 @@ +import { onCleanup, onMount, type Component } from 'solid-js'; + +import { useTonConnectUI } from '@/tonconnect/TonConnectUIContext.js'; + +export const TonConnectButton: Component = () => { + const [, { setUIOptions }] = useTonConnectUI(); + const buttonRootId = 'ton-connect-button'; + + onMount(() => { + setUIOptions({ buttonRootId }); + }); + + onCleanup(() => { + setUIOptions({ buttonRootId: null }); + }); + + return
; +}; diff --git a/apps/solid/src/tonconnect/TonConnectUIContext.ts b/apps/solid/src/tonconnect/TonConnectUIContext.ts new file mode 100644 index 000000000..9d9695354 --- /dev/null +++ b/apps/solid/src/tonconnect/TonConnectUIContext.ts @@ -0,0 +1,19 @@ +import { createContext, useContext } from 'solid-js'; +import type { TonConnectUI, TonConnectUiOptions } from '@tonconnect/ui'; + +export type TonConnectUIContextType = [ + get: () => TonConnectUI, + { + setUIOptions(options: TonConnectUiOptions): void; + }, +]; + +export const TonConnectUIContext = createContext(); + +export function useTonConnectUI(): TonConnectUIContextType { + const context = useContext(TonConnectUIContext); + if (!context) { + throw new Error('Unable to get TonConnectUIContext'); + } + return context; +} diff --git a/apps/solid/src/tonconnect/TonConnectUIProvider.tsx b/apps/solid/src/tonconnect/TonConnectUIProvider.tsx new file mode 100644 index 000000000..add0a011f --- /dev/null +++ b/apps/solid/src/tonconnect/TonConnectUIProvider.tsx @@ -0,0 +1,36 @@ +import { TonConnectUI, type TonConnectUiOptions } from '@tonconnect/ui'; +import { createMemo, type Component, type ParentProps } from 'solid-js'; + +import { TonConnectUIContext } from '@/tonconnect/TonConnectUIContext.js'; + +export interface TonConnectUIProviderProps extends ParentProps { + manifestUrl: string; +} + +// FIXME: Well, we found this code in the official tonconnect implementation for React. Doesn't +// seem to work the other way due to **constructor side effects**. Sad. +// https://github.com/ton-connect/sdk/blob/main/packages/ui-react/src/components/TonConnectUIProvider.tsx#L75 +let cached: TonConnectUI | undefined; + +export const TonConnectUIProvider: Component = (props) => { + const tonConnectUI = createMemo(() => { + return cached || (cached = new TonConnectUI({ + manifestUrl: props.manifestUrl, + })); + }); + + return ( + + {props.children} + + ); +}; diff --git a/apps/solid/src/tonconnect/useTonConnectUI.ts b/apps/solid/src/tonconnect/useTonConnectUI.ts new file mode 100644 index 000000000..e81d464f0 --- /dev/null +++ b/apps/solid/src/tonconnect/useTonConnectUI.ts @@ -0,0 +1,14 @@ +import { useContext } from 'solid-js'; + +import { + TonConnectUIContext, + type TonConnectUIContextType, +} from '@/tonconnect/TonConnectUIContext.js'; + +export function useTonConnectUI(): TonConnectUIContextType { + const context = useContext(TonConnectUIContext); + if (!context) { + throw new Error('Unable to get TonConnectUIContext'); + } + return context; +} diff --git a/apps/solid/src/tonconnect/useTonWallet.ts b/apps/solid/src/tonconnect/useTonWallet.ts new file mode 100644 index 000000000..57356e640 --- /dev/null +++ b/apps/solid/src/tonconnect/useTonWallet.ts @@ -0,0 +1,24 @@ +import { createEffect, createSignal, onCleanup, type Accessor } from 'solid-js'; +import type { Wallet, WalletInfoWithOpenMethod } from '@tonconnect/ui'; + +import { useTonConnectUI } from './useTonConnectUI.js'; + +/** + * Use it to get user's current ton wallet. If wallet is not connected hook will return null. + * @see Original React code: + * https://github.com/ton-connect/sdk/blob/main/packages/ui-react/src/hooks/useTonWallet.ts + */ +export function useTonWallet(): Accessor { + const [tonConnectUI] = useTonConnectUI(); + const [wallet, setWallet] = createSignal( + tonConnectUI().wallet || null, + ); + + createEffect(() => onCleanup( + tonConnectUI().onStatusChange((value) => { + setWallet(value); + }), + )); + + return wallet; +} diff --git a/apps/solid/tsconfig.json b/apps/solid/tsconfig.json new file mode 100644 index 000000000..989b1faff --- /dev/null +++ b/apps/solid/tsconfig.json @@ -0,0 +1,40 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "isolatedModules": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "lib": [ + "ES2020", + "DOM", + "DOM.Iterable" + ], + "module": "NodeNext", + "moduleResolution": "NodeNext", + "noEmit": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "paths": { + "@/*": [ + "./src/*" + ] + }, + "resolveJsonModule": true, + "skipLibCheck": true, + "strict": true, + "target": "ESNext", + "types": [ + "vite/client" + ] + }, + "include": [ + "src" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ] +} diff --git a/apps/solid/tsconfig.node.json b/apps/solid/tsconfig.node.json new file mode 100644 index 000000000..42872c59f --- /dev/null +++ b/apps/solid/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/apps/solid/vite.config.ts b/apps/solid/vite.config.ts new file mode 100644 index 000000000..b8a99d871 --- /dev/null +++ b/apps/solid/vite.config.ts @@ -0,0 +1,36 @@ +// import { readFileSync } from 'node:fs'; +// import { dirname, resolve } from 'node:path'; +// import { fileURLToPath } from 'node:url'; +import { defineConfig } from 'vite'; +import solidPlugin from 'vite-plugin-solid'; +import tsconfigPaths from 'vite-tsconfig-paths'; + +export default defineConfig({ + base: '/solidjs-template/', + plugins: [ + /* + Uncomment the following line to enable solid-devtools. + For more info see https://github.com/thetarnav/solid-devtools/tree/main/packages/extension#readme + */ + // devtools(), + solidPlugin(), + tsconfigPaths(), + ], + // Uncomment the next lines in case, you would like to run Vite dev server using HTTPS and in case, + // you have key and certificate. You retrieve your certificate and key using mkcert. + // Learn more: + // https://docs.telegram-mini-apps.com/platform/getting-app-link#mkcert + // + // server: { + // port: 443, + // https: { + // cert: readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), './https-cert.pem')), + // key: readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), './https-key.pem')), + // }, + // host: 'tma.internal', + // }, + build: { + target: 'esnext', + }, + publicDir: './public' +}); diff --git a/package.json b/package.json index 7cd878c0d..0a7456993 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "scripts": { "ci:docs:build": "pnpm run docs:build", "ci:packages:build": "pnpm run packages:build", - "ci:packages:install-deps": "pnpm i --filter {packages/*}", + "ci:packages:install-deps": "pnpm i", "ci:packages:lint": "pnpm run packages:lint", "ci:packages:test": "vitest --run", "ci:packages:typecheck": "pnpm run packages:typecheck", @@ -18,26 +18,26 @@ "packages:typecheck": "turbo run typecheck --filter=\"./packages/*\"" }, "devDependencies": { - "@changesets/cli": "^2.26.2", + "@changesets/cli": "^2.27.1", "@rollup/plugin-node-resolve": "^15.2.3", - "@turbo/gen": "^1.9.7", - "@vitest/coverage-v8": "^0.34.6", - "@vitest/ui": "^0.34.6", + "@turbo/gen": "^1.13.3", + "@vitest/coverage-v8": "^1.6.0", + "@vitest/ui": "^1.6.0", "commitizen": "^4.3.0", "cz-conventional-changelog": "^3.3.0", - "eslint": "^8.56.0", - "happy-dom": "^12.5.0", - "prettier": "^2.5.1", - "tslib": "^2.6.0", - "turbo": "^1.10.14", - "typescript": "5.3.2", - "vite": "^4.5.0", - "vite-plugin-dts": "^3.6.0", - "vite-plugin-solid": "^2.7.0", - "vite-tsconfig-paths": "^4.2.1", - "vitest": "^0.34.6" + "eslint": "^9.2.0", + "happy-dom": "^12.10.3", + "rimraf": "^5.0.5", + "tslib": "^2.6.2", + "turbo": "^1.13.3", + "typescript": "5.4.5", + "vite": "^5.2.11", + "vite-plugin-dts": "^3.9.1", + "vite-plugin-solid": "^2.10.2", + "vite-tsconfig-paths": "^4.3.2", + "vitest": "^1.6.0" }, - "packageManager": "pnpm@7.15.0", + "packageManager": "pnpm@9.1.0", "name": "monorepo", "config": { "commitizen": { diff --git a/packages/build-utils/CHANGELOG.md b/packages/build-utils/CHANGELOG.md deleted file mode 100644 index c0899ed36..000000000 --- a/packages/build-utils/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -# build-utils - -## 0.0.1 - -### Patch Changes - -- a9b7c88: Add new build utilities diff --git a/packages/build-utils/package.json b/packages/build-utils/package.json deleted file mode 100644 index 09321d5d9..000000000 --- a/packages/build-utils/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "build-utils", - "version": "0.0.1", - "private": true, - "license": "MIT", - "main": "dist/index.js", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - } - }, - "type": "module", - "scripts": { - "typecheck": "tsc --noEmit", - "build": "vite build --ssr --outDir dist", - "validate": "pnpm run typecheck && pnpm run build" - }, - "devDependencies": { - "tsconfig": "workspace:*" - } -} diff --git a/packages/build-utils/src/createViteConfig.ts b/packages/build-utils/src/createViteConfig.ts deleted file mode 100644 index 265f9f0a8..000000000 --- a/packages/build-utils/src/createViteConfig.ts +++ /dev/null @@ -1,120 +0,0 @@ -import dts from 'vite-plugin-dts'; -import tsconfigPaths from 'vite-tsconfig-paths'; -import type { LibraryFormats, PluginOption, UserConfig, AliasOptions } from 'vite'; -import type { InlineConfig } from 'vitest'; - -import { formatTmaJSPackageName } from './formatTmaJSPackageName.js'; - -export interface CreateViteConfigOptions { - /** - * Alias options. - */ - alias?: AliasOptions; - - /** - * Should d.ts files be emitted. - * @default true - */ - declarations?: boolean; - - /** - * Should Vite clear output directory. - * @default true - */ - emptyOutDir?: boolean; - - /** - * External dependencies. - */ - external?: string[]; - - /** - * Required package formats. - */ - formats: LibraryFormats[]; - - globals?: Record; - - /** - * NPM package name. - */ - packageName: string; - - /** - * Additional plugins. - */ - plugins?: PluginOption[]; - - /** - * Test options. - */ - test?: InlineConfig; - - /** - * Path to tsconfig file. - * @default './tsconfig.json' - */ - tsconfigPath?: string; -} - -export function createViteConfig(options: CreateViteConfigOptions): UserConfig { - const { - packageName, - formats, - external, - globals, - plugins = [], - test, - declarations = true, - emptyOutDir = true, - alias, - tsconfigPath = './tsconfig.json' - } = options; - - return { - test, - plugins: [ - tsconfigPaths(), - // Creates typescript declarations. - // https://www.npmjs.com/package/vite-plugin-dts - declarations && dts({ - outDir: 'dist/dts', - tsconfigPath, - }), - ...plugins, - ], - resolve: { - alias, - }, - build: { - outDir: 'dist', - emptyOutDir, - - rollupOptions: { - input: 'src/index.ts', - external, - output: { - globals, - }, - }, - - lib: { - name: formatTmaJSPackageName(packageName), - entry: 'src/index.ts', - formats, - fileName(format) { - switch (format) { - case 'cjs': - return 'index.cjs'; - case 'es': - return 'index.mjs'; - case 'iife': - return 'index.iife.js'; - default: - return 'index'; - } - }, - }, - }, - }; -} \ No newline at end of file diff --git a/packages/build-utils/src/createViteIIFEConfig.ts b/packages/build-utils/src/createViteIIFEConfig.ts deleted file mode 100644 index f27780a3d..000000000 --- a/packages/build-utils/src/createViteIIFEConfig.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import type { UserConfig } from 'vite'; - -import { createViteConfig, type CreateViteConfigOptions } from './createViteConfig.js'; - -type Options = Omit; - -export function createViteIIFEConfig({ plugins = [], ...rest }: Options): UserConfig { - return createViteConfig({ - ...rest, - formats: ['iife'], - declarations: false, - emptyOutDir: false, - plugins: [...plugins, nodeResolve()], - }); -} \ No newline at end of file diff --git a/packages/build-utils/src/createVitestConfig.ts b/packages/build-utils/src/createVitestConfig.ts deleted file mode 100644 index 5e9944fdd..000000000 --- a/packages/build-utils/src/createVitestConfig.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { InlineConfig, CoverageOptions, VitestEnvironment } from 'vitest'; - -interface Options { - environment?: VitestEnvironment; - coverage?: Omit, 'provider'>; -} - -export function createVitestConfig(options: Options = {}): InlineConfig { - const { - environment, - coverage, - } = options; - const config: InlineConfig = { - include: ['src/**/__tests__/**/*.ts'], - }; - - if (environment) { - config.environment = environment; - } - - if (coverage) { - config.coverage = { - enabled: true, - provider: 'v8', - include: ['src/**/*.ts'], - exclude: [ - 'src/**/index.ts', - 'src/**/__tests__/**/*', - ], - ...coverage, - }; - } - - return config; -} \ No newline at end of file diff --git a/packages/build-utils/src/formatTmaJSPackageName.ts b/packages/build-utils/src/formatTmaJSPackageName.ts deleted file mode 100644 index c7cd94fe7..000000000 --- a/packages/build-utils/src/formatTmaJSPackageName.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Formats passed value making it a path to a global variable. - * @param value - value to format. - */ -export function formatTmaJSPackageName(value: string): string { - return value - .replace(/^@tma\.js\//, 'tmajs.') - .replace(/-[a-z]/, match => match[1].toUpperCase()); -} \ No newline at end of file diff --git a/packages/build-utils/src/index.ts b/packages/build-utils/src/index.ts deleted file mode 100644 index 59f90cd3a..000000000 --- a/packages/build-utils/src/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './createViteConfig.js'; -export * from './createViteIIFEConfig.js'; -export * from './createVitestConfig.js'; -export * from './formatTmaJSPackageName.js'; diff --git a/packages/build-utils/tsconfig.json b/packages/build-utils/tsconfig.json deleted file mode 100644 index 92ff0cd39..000000000 --- a/packages/build-utils/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "tsconfig/esnext.json", - "compilerOptions": { - "types": [ - "vitest" - ] - }, - "include": [ - "src" - ] -} \ No newline at end of file diff --git a/packages/build-utils/vite.config.ts b/packages/build-utils/vite.config.ts deleted file mode 100644 index 626a2aad9..000000000 --- a/packages/build-utils/vite.config.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { defineConfig } from 'vite'; - -import dts from 'vite-plugin-dts'; - -export default defineConfig({ - plugins: [ - // Creates typescript declarations. - // https://www.npmjs.com/package/vite-plugin-dts - dts({ tsconfigPath: 'tsconfig.json' }), - ], - build: { - lib: { - entry: 'src/index.ts', - formats: ['es'], - fileName: 'index.js', - }, - }, -}); \ No newline at end of file diff --git a/packages/create-mini-app/.eslintrc.cjs b/packages/create-mini-app/.eslintrc.cjs deleted file mode 100644 index 63d117348..000000000 --- a/packages/create-mini-app/.eslintrc.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ['custom/base'], -}; diff --git a/packages/create-mini-app/package.json b/packages/create-mini-app/package.json index 517c865a9..7fca44f17 100644 --- a/packages/create-mini-app/package.json +++ b/packages/create-mini-app/package.json @@ -33,8 +33,6 @@ "devDependencies": { "@types/inquirer": "^9.0.7", "@types/node": "^20.0.0", - "build-utils": "workspace:*", - "eslint-config-custom": "workspace:*", "rollup-plugin-preserve-shebang": "^1.0.1", "test-utils": "workspace:*", "tsconfig": "workspace:*" diff --git a/packages/eslint-config-custom/CHANGELOG.md b/packages/eslint-config-custom/CHANGELOG.md deleted file mode 100644 index dc0f4f5e4..000000000 --- a/packages/eslint-config-custom/CHANGELOG.md +++ /dev/null @@ -1,25 +0,0 @@ -# eslint-config-custom - -## 0.1.0 - -### Minor Changes - -- 4edb39c: Add new rules to eslint config. Jest config now uses babel-jest - -## 0.0.3 - -### Patch Changes - -- 894eccb: Implement @twa.js/sdk-solid package - -## 0.0.2 - -### Patch Changes - -- 054d616: Fully rework bridge and release its first major update. Rename utilities in utils package. Make sdk components way better. - -## 0.0.1 - -### Patch Changes - -- a103e42: Optimize imports, fix minor bugs. diff --git a/packages/eslint-config-custom/base.js b/packages/eslint-config-custom/base.js deleted file mode 100644 index f8b3d072e..000000000 --- a/packages/eslint-config-custom/base.js +++ /dev/null @@ -1,15 +0,0 @@ -module.exports = { - extends: [ - 'airbnb-base', - 'airbnb-typescript/base', - ], - parserOptions: { - project: './tsconfig.json', - }, - plugins: [ - 'simple-import-sort', - 'import', - ], - rules: require('./rules'), - ignorePatterns: ['**/__tests__/*'], -}; diff --git a/packages/eslint-config-custom/index.js b/packages/eslint-config-custom/index.js deleted file mode 100644 index d4dd6bd1f..000000000 --- a/packages/eslint-config-custom/index.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - base: require('./base'), - react: require('./react'), - solid: require('./solid'), -}; \ No newline at end of file diff --git a/packages/eslint-config-custom/package.json b/packages/eslint-config-custom/package.json deleted file mode 100644 index 0abe3ad77..000000000 --- a/packages/eslint-config-custom/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "eslint-config-custom", - "version": "0.1.0", - "private": true, - "license": "MIT", - "dependencies": { - "eslint-config-airbnb": "^19.0.4", - "eslint-config-airbnb-base": "^15.0.0", - "eslint-config-airbnb-typescript": "^17.1.0", - "eslint-plugin-import": "^2.29.0", - "eslint-plugin-simple-import-sort": "^10.0.0", - "eslint-plugin-solid": "^0.13.0" - }, - "publishConfig": { - "access": "public" - } -} diff --git a/packages/eslint-config-custom/react.js b/packages/eslint-config-custom/react.js deleted file mode 100644 index 4b9182f1d..000000000 --- a/packages/eslint-config-custom/react.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - extends: [ - 'airbnb', - 'airbnb-typescript', - 'airbnb/hooks', - ], - parserOptions: { - project: './tsconfig.json', - }, - plugins: [ - 'simple-import-sort', - 'import', - ], - rules: { - ...require('./rules'), - 'react/jsx-props-no-spreading': 0, - 'react/prop-types': 0, - 'react/require-default-props': 0, - }, -}; diff --git a/packages/eslint-config-custom/rules.js b/packages/eslint-config-custom/rules.js deleted file mode 100644 index 8dfb9d04f..000000000 --- a/packages/eslint-config-custom/rules.js +++ /dev/null @@ -1,48 +0,0 @@ -module.exports = { - '@typescript-eslint/consistent-type-imports': 'error', - '@typescript-eslint/indent': 0, - // Sometimes this rule decreases readability. - 'arrow-body-style': 0, - 'consistent-return': 0, - 'import/extensions': 0, - // We use special module resolution, that's why we need extensions. - 'import/first': 'error', - 'import/newline-after-import': 'error', - 'import/no-duplicates': 'error', - // We have extraneous deps, because we have workspace. - 'import/no-extraneous-dependencies': 0, - // We don't use default exports anywhere. - 'import/prefer-default-export': 0, - // We select line endings depending on current OS. - // See: https://stackoverflow.com/q/39114446/2771889 - 'linebreak-style': ['error', (process.platform === 'win32' ? 'windows' : 'unix')], - 'no-await-in-loop': 0, - 'no-console': 0, - 'no-continue': 0, - 'no-nested-ternary': 0, - // Sometimes we need to write "void promise". - 'no-void': 0, - 'object-curly-newline': ['error', { consistent: true }], - 'simple-import-sort/imports': [ - 2, - { - groups: [ - // Side effect imports. - [/^\u0000/.source], - - // Node.js builtins. - [/^node:/.source], - - // Externals. - [/^/.source], - - // Special current package imports. - // Paths starting with "~/". Then go their types. - [/^~\//.source, /^~\/.+\u0000$/.source], - - // Relative imports. - [/^\.[^.]/.source, /^\.\./.source], - ], - }, - ], -}; \ No newline at end of file diff --git a/packages/eslint-config-custom/solid.js b/packages/eslint-config-custom/solid.js deleted file mode 100644 index c0b4d041b..000000000 --- a/packages/eslint-config-custom/solid.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - extends: [ - 'airbnb-base', - 'airbnb-typescript/base', - 'plugin:solid/typescript' - ], - plugins: [ - 'simple-import-sort', - 'import', - 'solid' - ], - parser: '@typescript-eslint/parser', - parserOptions: { - project: './tsconfig.json', - }, - rules: require('./rules'), -}; diff --git a/packages/init-data-node/.eslintrc.cjs b/packages/init-data-node/.eslintrc.cjs deleted file mode 100644 index 63d117348..000000000 --- a/packages/init-data-node/.eslintrc.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ['custom/base'], -}; diff --git a/packages/init-data-node/package.json b/packages/init-data-node/package.json index 919f8689d..4d09481d9 100644 --- a/packages/init-data-node/package.json +++ b/packages/init-data-node/package.json @@ -22,16 +22,15 @@ "type": "module", "sideEffects": false, "files": [ - "dist", - "src" + "dist" ], "main": "./dist/index.cjs", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "types": "./dist/dts/index.d.ts", "exports": { ".": { "types": "./dist/dts/index.d.ts", - "import": "./dist/index.mjs", + "import": "./dist/index.js", "require": "./dist/index.cjs", "default": "./dist/index.cjs" } @@ -45,8 +44,6 @@ }, "devDependencies": { "@types/node": "^20.0.0", - "build-utils": "workspace:*", - "eslint-config-custom": "workspace:*", "tsconfig": "workspace:*" }, "publishConfig": { diff --git a/packages/init-data-node/src/index.ts b/packages/init-data-node/src/index.ts index 50d4389c1..ca8770d93 100644 --- a/packages/init-data-node/src/index.ts +++ b/packages/init-data-node/src/index.ts @@ -1,3 +1,8 @@ -export type { InitDataParsed as InitData } from '@tma.js/sdk'; -export { parse } from './parse.js'; export { validate, type ValidateOptions } from './validate.js'; +export { + type Chat, + type ChatType, + type InitDataParsed, + parseInitData as parse, + type User, +} from '@tma.js/sdk'; diff --git a/packages/init-data-node/src/parse.ts b/packages/init-data-node/src/parse.ts deleted file mode 100644 index 8b0580e2c..000000000 --- a/packages/init-data-node/src/parse.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { parseInitData } from '@tma.js/sdk'; - -export { parseInitData as parse }; diff --git a/packages/init-data-node/src/__tests__/validate.ts b/packages/init-data-node/src/validate.test.ts similarity index 97% rename from packages/init-data-node/src/__tests__/validate.ts rename to packages/init-data-node/src/validate.test.ts index ecab4d589..b1d7a763d 100644 --- a/packages/init-data-node/src/__tests__/validate.ts +++ b/packages/init-data-node/src/validate.test.ts @@ -2,7 +2,7 @@ import { URLSearchParams } from 'node:url'; import { expect, it } from 'vitest'; -import { validate } from '../validate.js'; +import { validate } from './validate.js'; const sp = 'query_id=AAHdF6IQAAAAAN0XohDhrOrc&user=%7B%22id%22%3A279058397%2C%22first_name%22%3A%22Vladislav%22%2C%22last_name%22%3A%22Kibenko%22%2C%22username%22%3A%22vdkfrost%22%2C%22language_code%22%3A%22ru%22%2C%22is_premium%22%3Atrue%7D&auth_date=1662771648&hash=c501b71e775f74ce10e377dea85a7ea24ecd640b223ea86dfe453e0eaed2e2b2'; const secretToken = '5768337691:AAH5YkoiEuPk8-FZa32hStHTqXiLPtAEhx8'; diff --git a/packages/init-data-node/tsconfig.json b/packages/init-data-node/tsconfig.json index bb76e7f23..e37c9eda5 100644 --- a/packages/init-data-node/tsconfig.json +++ b/packages/init-data-node/tsconfig.json @@ -4,7 +4,7 @@ "src" ], "exclude": [ - "src/**/__tests__" + "src/**/*.test.ts" ], "references": [ { diff --git a/packages/init-data-node/vite.config.ts b/packages/init-data-node/vite.config.ts index 043805573..cc343f004 100644 --- a/packages/init-data-node/vite.config.ts +++ b/packages/init-data-node/vite.config.ts @@ -1,17 +1,32 @@ -import { createViteConfig, createVitestConfig } from 'build-utils'; +import { defineConfig } from 'vitest/config'; +import dts from 'vite-plugin-dts'; -import packageJson from './package.json'; - -export default createViteConfig({ - packageName: packageJson.name, - formats: ['es', 'cjs'], - external: ['node:crypto', 'node:url'], - test: createVitestConfig({ +export default defineConfig({ + test: { + include: ['src/**/*.test.ts'], coverage: { + enabled: true, + provider: 'v8', + include: ['src/**/*.ts'], + exclude: ['src/**/*.test.ts'], branches: 100, functions: 100, statements: 100, lines: 100, }, - }), + }, + plugins: [ + dts({ outDir: 'dist/dts' }), + ], + build: { + outDir: 'dist', + emptyOutDir: true, + sourcemap: true, + rollupOptions: { external: ['node:crypto', 'node:url'] }, + lib: { + entry: 'src/index.ts', + formats: ['es', 'cjs'], + fileName: 'index', + }, + }, }); diff --git a/packages/react-router-integration/.eslintrc.cjs b/packages/react-router-integration/.eslintrc.cjs deleted file mode 100644 index c5a358286..000000000 --- a/packages/react-router-integration/.eslintrc.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ['custom/react'], -}; diff --git a/packages/react-router-integration/package.json b/packages/react-router-integration/package.json index c5cff9482..8132febe6 100644 --- a/packages/react-router-integration/package.json +++ b/packages/react-router-integration/package.json @@ -26,12 +26,12 @@ "dist" ], "main": "./dist/index.cjs", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "types": "./dist/dts/index.d.ts", "exports": { ".": { "types": "./dist/dts/index.d.ts", - "import": "./dist/index.mjs", + "import": "./dist/index.js", "require": "./dist/index.cjs", "default": "./dist/index.cjs" } @@ -43,7 +43,7 @@ "build": "vite build" }, "peerDependencies": { - "@tma.js/sdk": "workspace:*", + "@tma.js/sdk-react": "workspace:*", "@types/react": "^17.0.0 || ^18.0.0", "react": "^17.0.0 || ^18.0.0", "react-router-dom": "^6.22.3" @@ -58,8 +58,6 @@ }, "devDependencies": { "@tma.js/sdk-react": "workspace:^", - "build-utils": "workspace:*", - "eslint-config-custom": "workspace:*", "react-router-dom": "^6.22.3", "tsconfig": "workspace:*" }, diff --git a/packages/react-router-integration/src/createNavigator.ts b/packages/react-router-integration/src/createNavigator.ts deleted file mode 100644 index 16987b2af..000000000 --- a/packages/react-router-integration/src/createNavigator.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { HashNavigatorOptions } from '@tma.js/sdk'; -import { HashNavigator, isPageReload } from '@tma.js/sdk'; - -function instantiate(options?: HashNavigatorOptions): HashNavigator { - // If page was reloaded, we assume that navigator had to previously save - // its state in the session storage. - if (isPageReload()) { - const stateRaw = sessionStorage.getItem('hash-navigator-state'); - if (stateRaw) { - try { - const { cursor, entries } = JSON.parse(stateRaw); - return new HashNavigator(entries, cursor, options); - } catch (e) { - console.error('Unable to restore hash navigator state.', e); - } - } - } - - // In case, we could not restore its state, or it is the fresh start, we - // can create an empty navigator. - return new HashNavigator([{}], 0, options); -} - -/** - * Creates Telegram Mini Apps navigator. - * @param options - navigator creation options. - */ -export function createNavigator(options?: HashNavigatorOptions): HashNavigator { - const navigator = instantiate(options); - - const saveState = () => sessionStorage.setItem('hash-navigator-state', JSON.stringify({ - cursor: navigator.cursor, - entries: navigator.getEntries(), - })); - - // Whenever navigator changes its state, we save it in the session storage. - navigator.on('change', saveState); - - // Save initial state to make sure nothing will break when page will be reloaded. - saveState(); - - return navigator; -} diff --git a/packages/react-router-integration/src/index.ts b/packages/react-router-integration/src/index.ts index 99ded2b7f..e363317c8 100644 --- a/packages/react-router-integration/src/index.ts +++ b/packages/react-router-integration/src/index.ts @@ -1,3 +1 @@ -export * from './createNavigator.js'; -export * from './useBackButtonIntegration.js'; -export * from './useNavigatorIntegration.js'; +export { useIntegration } from './useIntegration.js'; diff --git a/packages/react-router-integration/src/useBackButtonIntegration.ts b/packages/react-router-integration/src/useBackButtonIntegration.ts deleted file mode 100644 index 9244ce981..000000000 --- a/packages/react-router-integration/src/useBackButtonIntegration.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { BackButton, HashNavigator } from '@tma.js/sdk'; -import { useEffect } from 'react'; - -/** - * Controls specified Back Button visibility state and moves navigator's cursor back if user - * pressed the Back Button. - * @param nav - Mini Apps navigator. - * @param backButton - Mini Apps Back Button. - */ -export function useBackButtonIntegration(nav: HashNavigator, backButton: BackButton): void { - // When Mini Apps navigator changes its location, we should actualize the reactive values. - useEffect(() => { - return nav.on('change', () => { - if (nav.canGoBack) { - backButton.show(); - } else { - backButton.hide(); - } - }); - }, [nav, backButton]); - - // When user presses the Back Button, we navigate back. - useEffect(() => { - return backButton.on('click', () => nav.back()); - }, [backButton, nav]); -} diff --git a/packages/react-router-integration/src/useIntegration.ts b/packages/react-router-integration/src/useIntegration.ts new file mode 100644 index 000000000..3d4d3165f --- /dev/null +++ b/packages/react-router-integration/src/useIntegration.ts @@ -0,0 +1,52 @@ +import { useCallback, useEffect, useMemo, useState } from 'react'; +import type { Location, Navigator, To, NavigateOptions } from 'react-router-dom'; +import { BrowserNavigator, createSafeURL, urlToPath } from '@tma.js/sdk-react'; + +/** + * Uses the passed Mini Apps navigator and returns a tuple containing reactive values + * representing current location and react-router-dom navigator. + * @param nav - Mini Apps navigator. + */ +export function useIntegration(nav: BrowserNavigator): [Location, Navigator] { + // Creates location based on the Mini Apps navigator. + const createLocation = useCallback((): Location => ({ + state: nav.state, + key: nav.id, + pathname: nav.pathname, + hash: nav.hash, + search: nav.search, + }), [nav]); + + const [location, setLocation] = useState(createLocation); + + const navigate = useCallback((to: To, state?: any, options?: NavigateOptions) => { + options ||= {}; + if (state === undefined) { + state = options.state; + } + const path = urlToPath(to); + if (options.replace) { + nav.replace(path, state); + } else { + nav.push(path, state); + } + }, [nav]); + + // Create Navigator appropriate to the react-router-dom package. + const navigator = useMemo(() => ({ + go(delta) { + nav.go(delta); + }, + push: navigate, + replace: navigate, + createHref: (to) => nav.renderPath(urlToPath(to)), + encodeLocation: (to) => createSafeURL(nav.renderPath(urlToPath(to))), + }), [nav]); + + // When Mini Apps navigator changes its location, we should actualize the reactive values. + useEffect(() => { + return nav.on('change', () => setLocation(createLocation())); + }, [nav, createLocation]); + + return [location, navigator]; +} diff --git a/packages/react-router-integration/src/useNavigatorIntegration.ts b/packages/react-router-integration/src/useNavigatorIntegration.ts deleted file mode 100644 index bf63ce37d..000000000 --- a/packages/react-router-integration/src/useNavigatorIntegration.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { HashNavigator } from '@tma.js/sdk'; -import { useCallback, useEffect, useMemo, useState } from 'react'; -import type { Location, Navigator, To } from 'react-router-dom'; - -function formatTo(to: To): string { - return typeof to === 'string' - ? to - : `${to.pathname}${to.search}${to.hash}`; -} - -/** - * Uses passed Mini Apps navigator and returns tuple containing reactive values representing - * current location and react-router-dom navigator. - * @param nav - Mini Apps navigator. - */ -export function useNavigatorIntegration(nav: HashNavigator): [Location, Navigator] { - // Creates location based on the Mini Apps navigator. - const createLocation = useCallback(() => ({ - state: null, - key: '', - pathname: nav.pathname, - hash: nav.hash, - search: nav.search, - }), [nav]); - - const [location, setLocation] = useState(createLocation); - - // Create Navigator appropriate to the react-router-dom package. - const navigator = useMemo(() => ({ - go: nav.go.bind(nav), - push: nav.push.bind(nav), - replace: nav.replace.bind(nav), - createHref: (to) => `#${formatTo(to)}`, - encodeLocation: (to) => new URL(formatTo(to), 'http://localhost'), - }), [nav]); - - // When Mini Apps navigator changes its location, we should actualize the reactive values. - useEffect(() => { - return nav.on('change', () => setLocation(createLocation())); - }, [nav, createLocation]); - - return [location, navigator]; -} diff --git a/packages/react-router-integration/tsconfig.json b/packages/react-router-integration/tsconfig.json index 101ab7693..f50eab2d8 100644 --- a/packages/react-router-integration/tsconfig.json +++ b/packages/react-router-integration/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "tsconfig/react-library.json", + "extends": "tsconfig/esnext-dom.json", "include": [ "src" ], diff --git a/packages/react-router-integration/vite.config.ts b/packages/react-router-integration/vite.config.ts index bf2c90644..1253d8640 100644 --- a/packages/react-router-integration/vite.config.ts +++ b/packages/react-router-integration/vite.config.ts @@ -1,15 +1,22 @@ -import { createViteConfig } from 'build-utils'; +import dts from 'vite-plugin-dts'; +import { defineConfig } from 'vite'; -import packageJson from './package.json'; - -export default createViteConfig({ - packageName: packageJson.name, - formats: ['es', 'cjs'], - external: [ - '@tma.js/sdk', - 'react' +export default defineConfig({ + plugins: [ + dts({ outDir: 'dist/dts' }), ], - globals: { - react: 'React', + build: { + outDir: 'dist', + emptyOutDir: true, + sourcemap: true, + rollupOptions: { + external: ['@tma.js/sdk-react', 'react', 'react-router-dom'], + }, + lib: { + entry: 'src/index.ts', + formats: ['es', 'cjs'], + fileName: 'index', + }, }, }); + diff --git a/packages/sdk-react/.eslintrc.cjs b/packages/sdk-react/.eslintrc.cjs deleted file mode 100644 index c5a358286..000000000 --- a/packages/sdk-react/.eslintrc.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ['custom/react'], -}; diff --git a/packages/sdk-react/package.json b/packages/sdk-react/package.json index a8ab6cd97..781530596 100644 --- a/packages/sdk-react/package.json +++ b/packages/sdk-react/package.json @@ -25,12 +25,12 @@ "dist" ], "main": "./dist/index.cjs", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "types": "./dist/dts/index.d.ts", "exports": { ".": { "types": "./dist/dts/index.d.ts", - "import": "./dist/index.mjs", + "import": "./dist/index.js", "require": "./dist/index.cjs", "default": "./dist/index.cjs" } @@ -41,10 +41,12 @@ "typecheck": "tsc --noEmit", "build": "vite build" }, + "dependencies": { + "@tma.js/sdk": "workspace:*" + }, "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0", - "react": "^17.0.0 || ^18.0.0", - "@tma.js/sdk": "workspace:*" + "react": "^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -52,9 +54,9 @@ } }, "devDependencies": { - "build-utils": "workspace:*", - "eslint-config-custom": "workspace:*", - "tsconfig": "workspace:*" + "tsconfig": "workspace:*", + "@types/react": "^18.0.0", + "react": "^18.0.0" }, "publishConfig": { "access": "public" diff --git a/packages/sdk-react/src/DisplayGate.tsx b/packages/sdk-react/src/DisplayGate.tsx deleted file mode 100644 index 0fbe75b88..000000000 --- a/packages/sdk-react/src/DisplayGate.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import React, { type ComponentType, type PropsWithChildren, type ReactNode } from 'react'; - -import { useSDKContext } from './provider/index.js'; - -export interface DisplayGateProps extends PropsWithChildren { - /** - * Element or component, which will be displayed in case, SDK is not loading, didn't receive - * any error during initialization as well as the initialization result. - */ - initial?: ReactNode | ComponentType; - - /** - * Element or component which will be displayed in case, SDK initialization failed. - */ - error?: ReactNode | ComponentType<{ error: unknown }>; - - /** - * Element or component which will be displayed in case, SDK is currently loading. - */ - loading?: ReactNode | ComponentType; -} - -function render(Component: ReactNode | ComponentType): ReactNode; -function render(Component: ReactNode | ComponentType, props: T): ReactNode; -function render(Component: ReactNode | ComponentType, props = {}): ReactNode { - return typeof Component === 'function' ? : Component; -} - -/** - * This component is the layer controlling the application display. It displays application in - * case, the SDK is initialized, displays an error if something went wrong, and a loader - * if the SDK is warming up. - */ -export function DisplayGate(props: DisplayGateProps): ReactNode { - const { loading, initResult, error } = useSDKContext(); - - if (initResult) { - return props.children; - } - return error - ? render(props.error, { error }) - : render(loading ? props.loading : props.initial); -} diff --git a/packages/sdk-react/src/SDKProvider/SDKContext.ts b/packages/sdk-react/src/SDKProvider/SDKContext.ts new file mode 100644 index 000000000..fe8a1f2ee --- /dev/null +++ b/packages/sdk-react/src/SDKProvider/SDKContext.ts @@ -0,0 +1,17 @@ +import { createContext, useContext } from 'react'; + +import type { SDKContextType } from './SDKProvider.types.js'; + +export const SDKContext = createContext(undefined); + +/** + * @throws Error useSDK was used outside SDKProvider. + * @returns SDK context. + */ +export function useSDK(): SDKContextType { + const context = useContext(SDKContext); + if (!context) { + throw new Error('useSDK was used outside the SDKProvider.'); + } + return context; +} diff --git a/packages/sdk-react/src/SDKProvider/SDKProvider.tsx b/packages/sdk-react/src/SDKProvider/SDKProvider.tsx new file mode 100644 index 000000000..51fd7e610 --- /dev/null +++ b/packages/sdk-react/src/SDKProvider/SDKProvider.tsx @@ -0,0 +1,113 @@ +import { initWeb, isIframe, setDebug } from '@tma.js/sdk'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import type { AnyFn } from '@tma.js/sdk'; + +import { SDKContext } from './SDKContext.js'; +import { + SDKContextType, + SDKProviderProps, + SDKContextItem, +} from './SDKProvider.types.js'; + +/** + * Provides access to the SDK components and initializes some event listeners for the web version + * of Telegram. + */ +export function SDKProvider({ children, acceptCustomStyles, debug }: SDKProviderProps) { + // Mount flag. We need it to safely call state setters, as long as React forbids these + // operations on unmounted components. + const mounted = useRef(true); + + // Map, containing all registered factory results. + const [cache, setCache] = useState>>( + () => new Map(), + ); + + // Safely mutates cache with specified function. + const mutateCache = useCallback((mutate?: (state: typeof cache) => void) => { + if (mounted.current) { + setCache(c => { + if (mutate) { + mutate(c); + } + return new Map(c); + }); + } + }, []); + + // Forcefully refreshes the cache. We need this function to notify subscribers about cache + // changes. + const forceRefresh = useCallback(() => mutateCache(), [mutateCache]); + + // List of trackable components. We don't use memo or signals as long there is no real + // reason to track this list changes. We use only to remove "change" listeners on the component + // unmount. + const trackable = useRef<{ on: any; off: any }[]>([]); + + const context = useMemo(() => ({ + use(factory, ...args) { + const cached = cache.get(factory); + if (cached) { + return cached; + } + + let item: SDKContextItem; + try { + item = { result: factory(...args) }; + } catch (error) { + item = { error }; + } + + if ('error' in item || !item.result) { + cache.set(factory, item); + return item; + } + + const processResult = (result: any): SDKContextItem => { + if ('on' in result) { + result.on('change', forceRefresh); + trackable.current.push(result); + } + return { result }; + }; + + if (item.result as any instanceof Promise) { + item.result.then( + (result: any) => mutateCache(c => c.set(factory, processResult(result))), + (error: any) => mutateCache(c => c.set(factory, { error })), + ); + cache.set(factory, {}); + return {}; + } + + cache.set(factory, item = processResult(item.result)); + return item; + }, + }), [cache]); + + // Effect, responsible for debug mode. + useEffect(() => { + setDebug(debug || false); + }, [debug]); + + // Effect, responsible for changing mount state. + useEffect(() => { + return () => { + mounted.current = false; + }; + }, []); + + // Effect, responsible for initializing the app in the web version of Telegram. + useEffect(() => { + if (isIframe()) { + return initWeb(acceptCustomStyles); + } + }, [acceptCustomStyles]); + + // Effect, responsible for removing all components "change" listeners. + useEffect(() => { + return () => trackable.current.forEach(item => item.off('change', forceRefresh)); + }, [forceRefresh]); + + return {children}; +} diff --git a/packages/sdk-react/src/SDKProvider/SDKProvider.types.ts b/packages/sdk-react/src/SDKProvider/SDKProvider.types.ts new file mode 100644 index 000000000..424a745de --- /dev/null +++ b/packages/sdk-react/src/SDKProvider/SDKProvider.types.ts @@ -0,0 +1,44 @@ +import type { AnyFn } from '@tma.js/sdk'; +import type { PropsWithChildren } from 'react'; + +export interface SDKProviderProps extends PropsWithChildren { + /** + * True if SDK should accept styles sent from the Telegram web application. This option is only + * used in web versions of Telegram. + * @default true + */ + acceptCustomStyles?: boolean; + /** + * Enables debug mode. + * @default false + */ + debug?: boolean; +} + +/** + * SDKContext item. + */ +export type SDKContextItem = ({ + /** + * This item execution result. The property may be missing in case, execution is async. + */ + result?: T; +} | { + /** + * An error occurred during execution. + */ + error: unknown; +}); + +export interface SDKContextType { + /** + * Uses specified factory with the passed arguments. In case, this factory was called + * previously, a cached result will be returned. + * @param factory - factory function. + * @param args - factory arguments. + */ + use( + factory: Fn, + ...args: Parameters + ): SDKContextItem>>; +} diff --git a/packages/sdk-react/src/createHOCs.tsx b/packages/sdk-react/src/createHOCs.tsx new file mode 100644 index 000000000..a8434f620 --- /dev/null +++ b/packages/sdk-react/src/createHOCs.tsx @@ -0,0 +1,61 @@ +import type { ComponentType } from 'react'; +import type { PartialBy } from '@tma.js/sdk'; + +import type { HookRaw, HookResult } from './createHooks.js'; + +export interface HOC | HookResult> { + /** + * Returns a component which is a HOC, passing some hook result to the wrapped component. + * @param propKey - key, which will be used to pass a hook result. + * @param optionsKey - key, containing hook arguments. + * @param Component - component to wrap. + */ + < + PropKey extends string, + OptionsKey extends string, + Props extends { [K in OptionsKey]?: Parameters } & { [K in PropKey]?: ReturnType } + >( + propKey: PropKey, + optionsKey: OptionsKey, + Component: ComponentType, + ): ComponentType>; +} + +export type HOCs, HResult extends HookResult> = [ + HOC, + HOC +]; + +/** + * Based on the passed hook, creates function returning HOC. Created HOC passes hook result + * to the wrapped component. + * @param useRaw - hook, returning a raw SDK item. + * @param useResult - hook, returning an SDK item with the result. + */ +export function createHOCs, HResult extends HookResult>( + useRaw: HRaw, + useResult: HResult, +): HOCs { + function createHOC | HookResult>( + hook: Hook, + ): HOC { + return < + PropKey extends string, + OptionsKey extends string, + Props extends { [K in OptionsKey]?: Parameters } & { [K in PropKey]?: ReturnType } + >( + propKey: PropKey, + optionsKey: OptionsKey, + Component: ComponentType, + ): ComponentType> => { + return (props: PartialBy) => { + const options: any = props[optionsKey] || []; + const merged: any = { ...props, [propKey]: hook(...options) }; + + return ; + }; + }; + } + + return [createHOC(useRaw), createHOC(useResult)]; +} diff --git a/packages/sdk-react/src/createHoc.tsx b/packages/sdk-react/src/createHoc.tsx deleted file mode 100644 index 115644992..000000000 --- a/packages/sdk-react/src/createHoc.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { type ComponentType } from 'react'; - -import type { Hook } from './createHook.js'; -import type { InitResultKey, InitResultValue } from './types.js'; - -export type Hoc =

}>( - Component: ComponentType

, -) => ComponentType

; - -/** - * Creates HOC for static init result value. - * @param initResultKey - init result key. - * @param hook - hook which returns init result value. - */ -export function createHoc(initResultKey: K, hook: Hook): Hoc { - return (Component: ComponentType) => { - function Wrapper(props: Record) { - const wrappedProps = { - ...props, - [initResultKey]: hook(), - }; - - return ; - } - - Object.defineProperty(Wrapper, 'name', { - value: `With${initResultKey[0].toUpperCase()}${initResultKey.slice(1)}`, - }); - - return Wrapper; - }; -} diff --git a/packages/sdk-react/src/createHook.ts b/packages/sdk-react/src/createHook.ts deleted file mode 100644 index 6df464118..000000000 --- a/packages/sdk-react/src/createHook.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useInitResultDynamicValue, useInitResultValue } from './provider/index.js'; -import type { - DynamicInitResultKey, - InitResultKey, - InitResultValue, - StaticInitResultKey, -} from './types.js'; - -export type Hook = () => InitResultValue; - -/** - * Creates hook to retrieve static init result value. - * @param initResultKey - init result key. - */ -export function createHook(initResultKey: K): Hook; - -/** - * Creates hook to retrieve dynamic init result value. - * @param initResultKey - init result key. - * @param dynamic - flag to let function know this init result value is dynamic. - */ -export function createHook( - initResultKey: K, - dynamic: true, -): Hook; - -export function createHook(initResultKey: InitResultKey, dynamic?: true): Hook { - return dynamic - ? () => useInitResultDynamicValue(initResultKey as DynamicInitResultKey) - : () => useInitResultValue(initResultKey); -} diff --git a/packages/sdk-react/src/createHooks.ts b/packages/sdk-react/src/createHooks.ts new file mode 100644 index 000000000..0c1a308a3 --- /dev/null +++ b/packages/sdk-react/src/createHooks.ts @@ -0,0 +1,47 @@ +import { AnyFn } from '@tma.js/sdk'; +import { useMemo } from 'react'; + +import { useSDK } from './SDKProvider/SDKContext.js'; +import { SDKContextItem } from './SDKProvider/SDKProvider.types.js'; + +type HookFnResult = ReturnType extends Promise + ? T | undefined + : ReturnType; + +export interface HookRaw { + /** + * Hook, which retrieves SDK context item of the specified factory. This hook is safe + * to be used and not throwing errors. + */ + (...args: Parameters): SDKContextItem>; +} + +export interface HookResult { + /** + * Hook, which retrieves a result of the factory. + * @throws An error, if factory execution was unsuccessful. + */ + (...args: Parameters): HookFnResult; +} + +export type Hooks = [useRaw: HookRaw, useResult: HookResult]; + +/** + * @returns Hooks, simplifying work process with the SDK components. + */ +export function createHooks(fn: Fn): Hooks { + const useRaw = (...args: Parameters): SDKContextItem> => { + const sdk = useSDK(); + return useMemo(() => sdk.use(fn, ...args), [sdk]); + }; + + const useResult = (...args: Parameters): HookFnResult => { + const raw = useRaw(...args); + if ('error' in raw) { + throw raw.error; + } + return raw.result as HookFnResult; + }; + + return [useRaw, useResult]; +} diff --git a/packages/sdk-react/src/hooks-hocs/back-button.ts b/packages/sdk-react/src/hooks-hocs/back-button.ts new file mode 100644 index 000000000..d85b7384e --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/back-button.ts @@ -0,0 +1,11 @@ +import { initBackButton } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useBackButtonRaw, useBackButton] = createHooks(initBackButton); + +export const [withBackButtonRaw, withBackButton] = createHOCs( + useBackButtonRaw, + useBackButton, +); diff --git a/packages/sdk-react/src/hooks-hocs/biometry-manager.ts b/packages/sdk-react/src/hooks-hocs/biometry-manager.ts new file mode 100644 index 000000000..7c14194bd --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/biometry-manager.ts @@ -0,0 +1,11 @@ +import { initBiometryManager } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useBiometryManagerRaw, useBiometryManager] = createHooks(initBiometryManager); + +export const [withBiometryManagerRaw, withBiometryManager] = createHOCs( + useBiometryManagerRaw, + useBiometryManager, +); diff --git a/packages/sdk-react/src/hooks-hocs/closing-behavior.ts b/packages/sdk-react/src/hooks-hocs/closing-behavior.ts new file mode 100644 index 000000000..a807ccc35 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/closing-behavior.ts @@ -0,0 +1,11 @@ +import { initClosingBehavior } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useClosingBehaviorRaw, useClosingBehavior] = createHooks(initClosingBehavior); + +export const [withClosingBehaviorRaw, withClosingBehavior] = createHOCs( + useClosingBehaviorRaw, + useClosingBehavior, +); diff --git a/packages/sdk-react/src/hooks-hocs/cloud-storage.ts b/packages/sdk-react/src/hooks-hocs/cloud-storage.ts new file mode 100644 index 000000000..81e9570a8 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/cloud-storage.ts @@ -0,0 +1,11 @@ +import { initCloudStorage } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useCloudStorageRaw, useCloudStorage] = createHooks(initCloudStorage); + +export const [withCloudStorageRaw, withCloudStorage] = createHOCs( + useCloudStorageRaw, + useCloudStorage, +); diff --git a/packages/sdk-react/src/hooks-hocs/haptic-feedback.ts b/packages/sdk-react/src/hooks-hocs/haptic-feedback.ts new file mode 100644 index 000000000..97d308161 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/haptic-feedback.ts @@ -0,0 +1,11 @@ +import { initHapticFeedback } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useHapticFeedbackRaw, useHapticFeedback] = createHooks(initHapticFeedback); + +export const [withHapticFeedbackRaw, withHapticFeedback] = createHOCs( + useHapticFeedbackRaw, + useHapticFeedback, +); diff --git a/packages/sdk-react/src/hooks-hocs/init-data.ts b/packages/sdk-react/src/hooks-hocs/init-data.ts new file mode 100644 index 000000000..c97ba699c --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/init-data.ts @@ -0,0 +1,8 @@ +import { initInitData } from '@tma.js/sdk'; + +import { createHooks } from '../createHooks.js'; +import { createHOCs } from '../createHOCs.js'; + +export const [useInitDataRaw, useInitData] = createHooks(initInitData); + +export const [withInitDataRaw, withInitData] = createHOCs(useInitDataRaw, useInitData); diff --git a/packages/sdk-react/src/hooks-hocs/invoice.ts b/packages/sdk-react/src/hooks-hocs/invoice.ts new file mode 100644 index 000000000..a0e143605 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/invoice.ts @@ -0,0 +1,14 @@ +import { initInvoice } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +/** + * Hook to receive the Invoice component instance. + */ +export const [useInvoiceRaw, useInvoice] = createHooks(initInvoice); + +/** + * HOC to pass the Invoice component instance to the wrapped component. + */ +export const [withInvoiceRaw, withInvoice] = createHOCs(useInvoiceRaw, useInvoice); diff --git a/packages/sdk-solid/src/tools/launch-params.tsx b/packages/sdk-react/src/hooks-hocs/launch-params.ts similarity index 54% rename from packages/sdk-solid/src/tools/launch-params.tsx rename to packages/sdk-react/src/hooks-hocs/launch-params.ts index 25317fa4e..bb7de7223 100644 --- a/packages/sdk-solid/src/tools/launch-params.tsx +++ b/packages/sdk-react/src/hooks-hocs/launch-params.ts @@ -1,8 +1,9 @@ +import { useMemo } from 'react'; import { type LaunchParams, retrieveLaunchParams } from '@tma.js/sdk'; /** - * Hook to retrieve launch parameters. + * @returns Launch parameters. */ export function useLaunchParams(): LaunchParams { - return retrieveLaunchParams(); -} + return useMemo(retrieveLaunchParams, []); +} \ No newline at end of file diff --git a/packages/sdk-react/src/hooks-hocs/main-button.ts b/packages/sdk-react/src/hooks-hocs/main-button.ts new file mode 100644 index 000000000..b93f9d896 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/main-button.ts @@ -0,0 +1,8 @@ +import { initMainButton } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useMainButtonRaw, useMainButton] = createHooks(initMainButton); + +export const [withMainButtonRaw, withMainButton] = createHOCs(useMainButtonRaw, useMainButton); diff --git a/packages/sdk-react/src/hooks-hocs/mini-app.ts b/packages/sdk-react/src/hooks-hocs/mini-app.ts new file mode 100644 index 000000000..e0c5fd8d4 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/mini-app.ts @@ -0,0 +1,8 @@ +import { initMiniApp } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useMiniAppRaw, useMiniApp] = createHooks(initMiniApp); + +export const [withMiniAppRaw, withMiniApp] = createHOCs(useMiniAppRaw, useMiniApp); diff --git a/packages/sdk-react/src/hooks-hocs/popup.ts b/packages/sdk-react/src/hooks-hocs/popup.ts new file mode 100644 index 000000000..26edc65e9 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/popup.ts @@ -0,0 +1,8 @@ +import { initPopup } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [usePopupRaw, usePopup] = createHooks(initPopup); + +export const [withPopupRaw, withPopup] = createHOCs(usePopupRaw, usePopup); diff --git a/packages/sdk-react/src/hooks-hocs/qr-scanner.ts b/packages/sdk-react/src/hooks-hocs/qr-scanner.ts new file mode 100644 index 000000000..ef4c0b57e --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/qr-scanner.ts @@ -0,0 +1,8 @@ +import { initQRScanner } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useQRScannerRaw, useQRScanner] = createHooks(initQRScanner); + +export const [withQRScannerRaw, withQRScanner] = createHOCs(useQRScannerRaw, useQRScanner); diff --git a/packages/sdk-react/src/hooks-hocs/settings-button.ts b/packages/sdk-react/src/hooks-hocs/settings-button.ts new file mode 100644 index 000000000..4281876a6 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/settings-button.ts @@ -0,0 +1,11 @@ +import { initSettingsButton } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useSettingsButtonRaw, useSettingsButton] = createHooks(initSettingsButton); + +export const [withSettingsButtonRaw, withSettingsButton] = createHOCs( + useSettingsButtonRaw, + useSettingsButton, +); diff --git a/packages/sdk-react/src/hooks-hocs/theme-params.ts b/packages/sdk-react/src/hooks-hocs/theme-params.ts new file mode 100644 index 000000000..de99409fa --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/theme-params.ts @@ -0,0 +1,8 @@ +import { initThemeParams } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useThemeParamsRaw, useThemeParams] = createHooks(initThemeParams); + +export const [withThemeParamsRaw, withThemeParams] = createHOCs(useThemeParamsRaw, useThemeParams); diff --git a/packages/sdk-react/src/hooks-hocs/utils.ts b/packages/sdk-react/src/hooks-hocs/utils.ts new file mode 100644 index 000000000..3dd587e16 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/utils.ts @@ -0,0 +1,8 @@ +import { initUtils } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useUtilsRaw, useUtils] = createHooks(initUtils); + +export const [withUtilsRaw, withUtils] = createHOCs(useUtilsRaw, useUtils); diff --git a/packages/sdk-react/src/hooks-hocs/viewport.ts b/packages/sdk-react/src/hooks-hocs/viewport.ts new file mode 100644 index 000000000..a0f993562 --- /dev/null +++ b/packages/sdk-react/src/hooks-hocs/viewport.ts @@ -0,0 +1,8 @@ +import { initViewport } from '@tma.js/sdk'; + +import { createHOCs } from '../createHOCs.js'; +import { createHooks } from '../createHooks.js'; + +export const [useViewportRaw, useViewport] = createHooks(initViewport); + +export const [withViewportRaw, withViewport] = createHOCs(useViewportRaw, useViewport); diff --git a/packages/sdk-react/src/index.ts b/packages/sdk-react/src/index.ts index 66445a600..81b854736 100644 --- a/packages/sdk-react/src/index.ts +++ b/packages/sdk-react/src/index.ts @@ -1,54 +1,99 @@ +export * from '@tma.js/sdk'; export { - useThemeParams, - useInitData, useBackButton, - useClosingBehavior, - useInitDataRaw, - useCloudStorage, - useLaunchParams, - useMainButton, - useHapticFeedback, - useInvoice, - useMiniApp, - usePopup, - usePostEvent, - useQRScanner, - useSettingsButton, - useUtils, - useViewport, + useBackButtonRaw, withBackButton, + withBackButtonRaw, +} from './hooks-hocs/back-button.js'; +export { + useBiometryManager, + useBiometryManagerRaw, + withBiometryManager, + withBiometryManagerRaw, +} from './hooks-hocs/biometry-manager.js'; +export { + useClosingBehavior, + useClosingBehaviorRaw, withClosingBehavior, + withClosingBehaviorRaw, +} from './hooks-hocs/closing-behavior.js'; +export { + useCloudStorage, + useCloudStorageRaw, withCloudStorage, - withInitData, + withCloudStorageRaw, +} from './hooks-hocs/cloud-storage.js'; +export { + useHapticFeedback, + useHapticFeedbackRaw, withHapticFeedback, + withHapticFeedbackRaw, +} from './hooks-hocs/haptic-feedback.js'; +export { + useInitData, + useInitDataRaw, + withInitData, withInitDataRaw, +} from './hooks-hocs/init-data.js'; +export { + useInvoice, + useInvoiceRaw, withInvoice, - withLaunchParams, + withInvoiceRaw, +} from './hooks-hocs/invoice.js'; +export { + useMainButton, + useMainButtonRaw, withMainButton, + withMainButtonRaw, +} from './hooks-hocs/main-button.js'; +export { + useMiniApp, + useMiniAppRaw, withMiniApp, - withPostEvent, + withMiniAppRaw, +} from './hooks-hocs/mini-app.js'; +export { + usePopup, + usePopupRaw, withPopup, - withThemeParams, + withPopupRaw, +} from './hooks-hocs/popup.js'; +export { + useQRScanner, + useQRScannerRaw, withQRScanner, + withQRScannerRaw, +} from './hooks-hocs/qr-scanner.js'; +export { + useSettingsButton, + useSettingsButtonRaw, withSettingsButton, + withSettingsButtonRaw, +} from './hooks-hocs/settings-button.js'; +export { + useThemeParams, + useThemeParamsRaw, + withThemeParams, + withThemeParamsRaw, +} from './hooks-hocs/theme-params.js'; +export { useLaunchParams } from './hooks-hocs/launch-params.js'; +export { + useUtils, + useUtilsRaw, withUtils, + withUtilsRaw, +} from './hooks-hocs/utils.js'; +export { + useViewport, + useViewportRaw, withViewport, -} from './tools/index.js'; -export { - useSDKContext, - withSDKContext, - SDKProvider, - SDKContext, - type SDKProviderProps, - type SDKContextType, - type SDKInitOptions, - type SDKInitResult, -} from './provider/index.js'; -export { - DisplayGate, - type DisplayGateProps, -} from './DisplayGate.js'; + withViewportRaw, +} from './hooks-hocs/viewport.js'; +export { useSDK } from './SDKProvider/SDKContext.js'; +export { SDKProvider } from './SDKProvider/SDKProvider.js'; export type { - InitOptions, - InitResult, -} from './types.js'; + SDKContextType, + SDKContextItem, + SDKProviderProps, +} from './SDKProvider/SDKProvider.types.js'; diff --git a/packages/sdk-react/src/provider/SDKContext.ts b/packages/sdk-react/src/provider/SDKContext.ts deleted file mode 100644 index 0bb2d5a8d..000000000 --- a/packages/sdk-react/src/provider/SDKContext.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createContext } from 'react'; - -import type { SDKContextType } from './types.js'; - -export const SDKContext = createContext({ - loading: false, -}); - -SDKContext.displayName = 'SDKContext'; diff --git a/packages/sdk-react/src/provider/SDKProvider.tsx b/packages/sdk-react/src/provider/SDKProvider.tsx deleted file mode 100644 index b2012e6b2..000000000 --- a/packages/sdk-react/src/provider/SDKProvider.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { init } from '@tma.js/sdk'; -import React, { useEffect, useMemo, useState } from 'react'; - -import { SDKContext } from './SDKContext.js'; -import type { SDKContextType, SDKProviderProps } from './types.js'; -import type { InitResult } from '../types.js'; - -function AsyncProvider({ options, children }: SDKProviderProps) { - const [loading, setLoading] = useState(false); - const [error, setError] = useState(); - const [initResult, setInitResult] = useState(); - - useEffect(() => { - setLoading(true); - - init({ ...options, complete: true }) - .then(setInitResult) - .catch(setError) - .finally(() => setLoading(false)); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const context = useMemo(() => { - const result: SDKContextType = { loading }; - if (error) { - result.error = error; - } - - if (initResult) { - result.initResult = initResult; - } - - return result; - }, [loading, initResult, error]); - - return {children}; -} - -function SyncProvider({ options = {}, children }: SDKProviderProps) { - const context = useMemo(() => { - const result: SDKContextType = { loading: false }; - - try { - result.initResult = init({ ...options, complete: false }); - } catch (e) { - result.error = e; - } - - return result; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return {children}; -} - -/** - * Component which provides access to SDK initialization state. - */ -export function SDKProvider(props: SDKProviderProps) { - const { options = {}, async } = props; - - return options.async || options.complete || async - ? - : ; -} diff --git a/packages/sdk-react/src/provider/index.ts b/packages/sdk-react/src/provider/index.ts deleted file mode 100644 index cf6b755d7..000000000 --- a/packages/sdk-react/src/provider/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './SDKContext.js'; -export * from './SDKProvider.js'; -export * from './types.js'; -export * from './useInitResultDynamicValue.js'; -export * from './useInitResultValue.js'; -export * from './useSDKContext.js'; -export * from './withSDKContext.js'; diff --git a/packages/sdk-react/src/provider/types.ts b/packages/sdk-react/src/provider/types.ts deleted file mode 100644 index 639b25678..000000000 --- a/packages/sdk-react/src/provider/types.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { PropsWithChildren } from 'react'; - -import type { InitOptions, InitResult } from '../types.js'; - -export type SDKInitOptions = InitOptions; - -export type SDKInitResult = InitResult; - -export type SDKProviderProps = PropsWithChildren<{ - /** - * Should initialization be asynchronous. This mode is useful in case, you are using SSR - * and want to perform initialization on the client side only. - * @default false - */ - async?: boolean; - - /** - * Init function options. - */ - options?: SDKInitOptions; -}>; - -export interface SDKContextType { - /** - * Error occurred during initialization. - */ - error?: unknown; - - /** - * Initialization result. - */ - initResult?: SDKInitResult; - - /** - * True if SDK is loading. - */ - loading: boolean; -} diff --git a/packages/sdk-react/src/provider/useInitResultDynamicValue.ts b/packages/sdk-react/src/provider/useInitResultDynamicValue.ts deleted file mode 100644 index d5ef705ed..000000000 --- a/packages/sdk-react/src/provider/useInitResultDynamicValue.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { useEffect, useState } from 'react'; - -import { useInitResultValue } from './useInitResultValue.js'; -import type { - DynamicInitResultKey, - InitResultValue, - Trackable, -} from '../types.js'; - -function shallowCopy(value: T): T { - return Object.create( - Object.getPrototypeOf(value), - Object.getOwnPropertyDescriptors(value), - ); -} - -export function useInitResultDynamicValue( - initResultKey: K, -): InitResultValue { - // Extract init result value. - const initial = useInitResultValue(initResultKey); - - // Create value which will be returned to the external environment. - const [copy, setCopy] = useState(shallowCopy(initial)); - - // Effect which listens to change event and calls update. - useEffect(() => { - return (initial as Trackable).on('change', () => { - setCopy(shallowCopy(initial)); - }); - }, [initial]); - - return copy; -} diff --git a/packages/sdk-react/src/provider/useInitResultValue.ts b/packages/sdk-react/src/provider/useInitResultValue.ts deleted file mode 100644 index d2df294c2..000000000 --- a/packages/sdk-react/src/provider/useInitResultValue.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { useSDKContext } from './useSDKContext.js'; -import type { InitResultKey, InitResultValue } from '../types.js'; - -/** - * Returns value by its field name from SDK init result. - * @param key - init result key. - * @throws {Error} SDK is not initialized. - */ -export function useInitResultValue(key: K): InitResultValue { - const { initResult } = useSDKContext(); - - if (!initResult) { - throw new Error(`Unable to get init result key "${key}" as long as SDK is not initialized`); - } - return initResult[key]; -} diff --git a/packages/sdk-react/src/provider/useSDKContext.ts b/packages/sdk-react/src/provider/useSDKContext.ts deleted file mode 100644 index 750a1b366..000000000 --- a/packages/sdk-react/src/provider/useSDKContext.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useContext } from 'react'; - -import { SDKContext } from './SDKContext.js'; -import type { SDKContextType } from './types.js'; - -/** - * Returns current SDK information. - */ -export function useSDKContext(): SDKContextType { - return useContext(SDKContext); -} diff --git a/packages/sdk-react/src/provider/withSDKContext.tsx b/packages/sdk-react/src/provider/withSDKContext.tsx deleted file mode 100644 index 15070a918..000000000 --- a/packages/sdk-react/src/provider/withSDKContext.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React, { type ComponentType } from 'react'; - -import type { SDKContextType } from './types.js'; -import { useSDKContext } from './useSDKContext.js'; - -/** - * HOC which passes SDK context to wrapped React component. - * @param Component - component to wrap. - */ -export function withSDKContext

( - Component: ComponentType

, -): ComponentType> { - return function WithSDKContext(props: Omit) { - const p = { - ...props, - sdk: useSDKContext(), - } as P; - - return ; - }; -} diff --git a/packages/sdk-react/src/tools/back-button.ts b/packages/sdk-react/src/tools/back-button.ts deleted file mode 100644 index 5a32bd9b7..000000000 --- a/packages/sdk-react/src/tools/back-button.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve BackButton component. - */ -export const useBackButton = createHook('backButton', true); - -/** - * HOC to wrap specified component to pass BackButton instance. - */ -export const withBackButton = createHoc('backButton', useBackButton); diff --git a/packages/sdk-react/src/tools/closing-behavior.ts b/packages/sdk-react/src/tools/closing-behavior.ts deleted file mode 100644 index a35d218ff..000000000 --- a/packages/sdk-react/src/tools/closing-behavior.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve ClosingBehavior component. - */ -export const useClosingBehavior = createHook('closingBehavior', true); - -/** - * HOC to wrap specified component to pass ClosingBehavior instance. - */ -export const withClosingBehavior = createHoc('closingBehavior', useClosingBehavior); diff --git a/packages/sdk-react/src/tools/cloud-storage.ts b/packages/sdk-react/src/tools/cloud-storage.ts deleted file mode 100644 index a3a0e16ee..000000000 --- a/packages/sdk-react/src/tools/cloud-storage.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve CloudStorage component. - */ -export const useCloudStorage = createHook('cloudStorage'); - -/** - * HOC to wrap specified component to pass CloudStorage instance. - */ -export const withCloudStorage = createHoc('cloudStorage', useCloudStorage); diff --git a/packages/sdk-react/src/tools/haptic-feedback.ts b/packages/sdk-react/src/tools/haptic-feedback.ts deleted file mode 100644 index 9028b4dfa..000000000 --- a/packages/sdk-react/src/tools/haptic-feedback.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve HapticFeedback component. - */ -export const useHapticFeedback = createHook('hapticFeedback'); - -/** - * HOC to wrap specified component to pass HapticFeedback instance. - */ -export const withHapticFeedback = createHoc('hapticFeedback', useHapticFeedback); diff --git a/packages/sdk-react/src/tools/index.ts b/packages/sdk-react/src/tools/index.ts deleted file mode 100644 index cd09962d5..000000000 --- a/packages/sdk-react/src/tools/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -export * from './back-button.js'; -export * from './closing-behavior.js'; -export * from './cloud-storage.js'; -export * from './haptic-feedback.js'; -export * from './init-data.js'; -export * from './init-data-raw.js'; -export * from './invoice.js'; -export * from './launch-params.js'; -export * from './main-button.js'; -export * from './mini-app.js'; -export * from './popup.js'; -export * from './post-event.js'; -export * from './settings-button.js'; -export * from './qr-scanner.js'; -export * from './theme-params.js'; -export * from './utils.js'; -export * from './viewport.js'; diff --git a/packages/sdk-react/src/tools/init-data-raw.ts b/packages/sdk-react/src/tools/init-data-raw.ts deleted file mode 100644 index 54afe34b7..000000000 --- a/packages/sdk-react/src/tools/init-data-raw.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve init data raw representation. - */ -export const useInitDataRaw = createHook('initDataRaw'); - -/** - * HOC to wrap specified component to pass init data raw representation. - */ -export const withInitDataRaw = createHoc('initDataRaw', useInitDataRaw); diff --git a/packages/sdk-react/src/tools/init-data.ts b/packages/sdk-react/src/tools/init-data.ts deleted file mode 100644 index beaaebf3c..000000000 --- a/packages/sdk-react/src/tools/init-data.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve InitData component. - */ -export const useInitData = createHook('initData'); - -/** - * HOC to wrap specified component to pass InitData instance. - */ -export const withInitData = createHoc('initData', useInitData); diff --git a/packages/sdk-react/src/tools/invoice.ts b/packages/sdk-react/src/tools/invoice.ts deleted file mode 100644 index 8abd55794..000000000 --- a/packages/sdk-react/src/tools/invoice.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve Invoice component. - */ -export const useInvoice = createHook('invoice', true); - -/** - * HOC to wrap specified component to pass Invoice instance. - */ -export const withInvoice = createHoc('invoice', useInvoice); diff --git a/packages/sdk-react/src/tools/launch-params.tsx b/packages/sdk-react/src/tools/launch-params.tsx deleted file mode 100644 index 490b1eb9e..000000000 --- a/packages/sdk-react/src/tools/launch-params.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { type LaunchParams, retrieveLaunchParams } from '@tma.js/sdk'; -import React, { type ComponentType, useMemo } from 'react'; - -/** - * Hooks to retrieve launch parameters. - */ -export function useLaunchParams(): LaunchParams { - return useMemo(retrieveLaunchParams, []); -} - -/** - * HOC to wrap specified component to pass launch parameters. - * @param Component - wrapped component. - */ -export function withLaunchParams

( - Component: ComponentType

, -) { - return function WithInvoice(props: P) { - return ; - }; -} diff --git a/packages/sdk-react/src/tools/main-button.ts b/packages/sdk-react/src/tools/main-button.ts deleted file mode 100644 index adf9660d3..000000000 --- a/packages/sdk-react/src/tools/main-button.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve MainButton component. - */ -export const useMainButton = createHook('mainButton', true); - -/** - * HOC to wrap specified component to pass MainButton instance. - */ -export const withMainButton = createHoc('mainButton', useMainButton); diff --git a/packages/sdk-react/src/tools/mini-app.ts b/packages/sdk-react/src/tools/mini-app.ts deleted file mode 100644 index bec8ee03b..000000000 --- a/packages/sdk-react/src/tools/mini-app.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve MiniApp component. - */ -export const useMiniApp = createHook('miniApp', true); - -/** - * HOC to wrap specified component to pass MiniApp instance. - */ -export const withMiniApp = createHoc('miniApp', useMiniApp); diff --git a/packages/sdk-react/src/tools/popup.ts b/packages/sdk-react/src/tools/popup.ts deleted file mode 100644 index 534598b58..000000000 --- a/packages/sdk-react/src/tools/popup.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve Popup component. - */ -export const usePopup = createHook('popup', true); - -/** - * HOC to wrap specified component to pass Popup instance. - */ -export const withPopup = createHoc('popup', usePopup); diff --git a/packages/sdk-react/src/tools/post-event.ts b/packages/sdk-react/src/tools/post-event.ts deleted file mode 100644 index 65736306e..000000000 --- a/packages/sdk-react/src/tools/post-event.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve postEvent function. - */ -export const usePostEvent = createHook('postEvent'); - -/** - * HOC to wrap specified component to pass postEvent function. - */ -export const withPostEvent = createHoc('postEvent', usePostEvent); diff --git a/packages/sdk-react/src/tools/qr-scanner.ts b/packages/sdk-react/src/tools/qr-scanner.ts deleted file mode 100644 index 533d60ea3..000000000 --- a/packages/sdk-react/src/tools/qr-scanner.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve QRScanner component. - */ -export const useQRScanner = createHook('qrScanner', true); - -/** - * HOC to wrap specified component to pass QRScanner instance. - */ -export const withQRScanner = createHoc('qrScanner', useQRScanner); diff --git a/packages/sdk-react/src/tools/settings-button.ts b/packages/sdk-react/src/tools/settings-button.ts deleted file mode 100644 index d0c787ad7..000000000 --- a/packages/sdk-react/src/tools/settings-button.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve SettingsButton component. - */ -export const useSettingsButton = createHook('settingsButton', true); - -/** - * HOC to wrap specified component to pass SettingsButton instance. - */ -export const withSettingsButton = createHoc('settingsButton', useSettingsButton); diff --git a/packages/sdk-react/src/tools/theme-params.ts b/packages/sdk-react/src/tools/theme-params.ts deleted file mode 100644 index 8ab72f661..000000000 --- a/packages/sdk-react/src/tools/theme-params.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve ThemeParams component. - */ -export const useThemeParams = createHook('themeParams', true); - -/** - * HOC to wrap specified component to pass ThemeParams instance. - */ -export const withThemeParams = createHoc('themeParams', useThemeParams); diff --git a/packages/sdk-react/src/tools/utils.ts b/packages/sdk-react/src/tools/utils.ts deleted file mode 100644 index b6bb0fec4..000000000 --- a/packages/sdk-react/src/tools/utils.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve Utils component. - */ -export const useUtils = createHook('utils'); - -/** - * HOC to wrap specified component to pass Utils instance. - */ -export const withUtils = createHoc('utils', useUtils); diff --git a/packages/sdk-react/src/tools/viewport.ts b/packages/sdk-react/src/tools/viewport.ts deleted file mode 100644 index 70130c117..000000000 --- a/packages/sdk-react/src/tools/viewport.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createHoc } from '../createHoc.js'; -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve Viewport component. - */ -export const useViewport = createHook('viewport', true); - -/** - * HOC to wrap specified component to pass Viewport instance. - */ -export const withViewport = createHoc('viewport', useViewport); diff --git a/packages/sdk-react/src/types.ts b/packages/sdk-react/src/types.ts deleted file mode 100644 index 6fc11ad2f..000000000 --- a/packages/sdk-react/src/types.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { InitOptions, InitResult } from '@tma.js/sdk'; - -// TODO: Remove in the future. -export { InitOptions, InitResult }; - -export interface Trackable { - on(event: 'change', listener: () => void): () => void; -} - -/** - * SDK init result keys, which describe values with trackable changes. - */ -export type DynamicInitResultKey = { - [K in InitResultKey]-?: InitResultValue extends Trackable ? K : never; -}[InitResultKey]; - -/** - * SDK init result keys, which describe static values. - */ -export type StaticInitResultKey = Exclude; - -/** - * SDK initialization result key. - */ -export type InitResultKey = keyof InitResult; - -/** - * Returns SDK init result value type by its key. - */ -export type InitResultValue = InitResult[K]; diff --git a/packages/sdk-react/tsconfig.json b/packages/sdk-react/tsconfig.json index 101ab7693..75a38cc60 100644 --- a/packages/sdk-react/tsconfig.json +++ b/packages/sdk-react/tsconfig.json @@ -1,5 +1,8 @@ { - "extends": "tsconfig/react-library.json", + "extends": "tsconfig/esnext-dom.json", + "compilerOptions": { + "jsx": "react-jsx" + }, "include": [ "src" ], diff --git a/packages/sdk-react/vite.config.ts b/packages/sdk-react/vite.config.ts index c7c5b4b2d..d104e9313 100644 --- a/packages/sdk-react/vite.config.ts +++ b/packages/sdk-react/vite.config.ts @@ -1,15 +1,21 @@ -import { createViteConfig } from 'build-utils'; +import dts from 'vite-plugin-dts'; +import { defineConfig } from 'vite'; -import packageJson from './package.json'; - -export default createViteConfig({ - packageName: packageJson.name, - formats: ['es', 'cjs'], - external: [ - '@tma.js/sdk', - 'react', +export default defineConfig({ + plugins: [ + dts({ outDir: 'dist/dts' }), ], - globals: { - react: 'React', + build: { + outDir: 'dist', + emptyOutDir: true, + sourcemap: true, + rollupOptions: { + external: ['react', 'react/jsx-runtime'], + }, + lib: { + entry: 'src/index.ts', + formats: ['es', 'cjs'], + fileName: 'index', + }, }, }); diff --git a/packages/sdk-solid/.eslintrc.cjs b/packages/sdk-solid/.eslintrc.cjs deleted file mode 100644 index aef8c443f..000000000 --- a/packages/sdk-solid/.eslintrc.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ['custom/solid'], -}; diff --git a/packages/sdk-solid/package.json b/packages/sdk-solid/package.json index 5d5e75fa3..ce11fbd48 100644 --- a/packages/sdk-solid/package.json +++ b/packages/sdk-solid/package.json @@ -25,12 +25,12 @@ "dist" ], "main": "./dist/index.cjs", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "types": "./dist/dts/index.d.ts", "exports": { ".": { "types": "./dist/dts/index.d.ts", - "import": "./dist/index.mjs", + "import": "./dist/index.js", "require": "./dist/index.cjs", "default": "./dist/index.cjs" } @@ -41,14 +41,14 @@ "typecheck": "tsc --noEmit", "build": "vite build" }, + "dependencies": { + "@tma.js/sdk": "workspace:*" + }, "peerDependencies": { - "@tma.js/sdk": "workspace:*", "solid-js": "^1.0.0" }, "devDependencies": { - "eslint-config-custom": "workspace:*", - "tsconfig": "workspace:*", - "build-utils": "workspace:*" + "tsconfig": "workspace:*" }, "publishConfig": { "access": "public" diff --git a/packages/sdk-solid/src/DisplayGate.tsx b/packages/sdk-solid/src/DisplayGate.tsx deleted file mode 100644 index 194e35d65..000000000 --- a/packages/sdk-solid/src/DisplayGate.tsx +++ /dev/null @@ -1,56 +0,0 @@ -import { - type Component, - type JSX, - Match, - type ParentProps, - Switch, -} from 'solid-js'; - -import { useSDKContext } from './provider/index.js'; - -export interface DisplayGateProps extends ParentProps { - /** - * Element or component, which will be displayed in case, SDK is not loading, didn't receive - * any error during initialization as well as the initialization result. - */ - initial?: JSX.Element | Component; - - /** - * Element or component which will be displayed in case, SDK initialization failed. - */ - error?: JSX.Element | Component<{ error: unknown }>; - - /** - * Element or component which will be displayed in case, SDK is currently loading. - */ - loading?: JSX.Element | Component; -} - -function render(Component: JSX.Element | Component): JSX.Element; -function render(Component: JSX.Element | Component, props: T): JSX.Element; -function render(Component: JSX.Element | Component, props = {}): JSX.Element { - return typeof Component === 'function' ? : Component; -} - -/** - * This component is the layer controlling the application display. It displays application in - * case, the SDK is initialized, displays an error if something went wrong, and a loader - * if the SDK is warming up. - */ -export function DisplayGate(props: DisplayGateProps) { - const { loading, error, initResult } = useSDKContext(); - - return ( - - - {props.children} - - - {render(props.error, { error: error() })} - - - {render(props.loading)} - - - ); -} diff --git a/packages/sdk-solid/src/SDKProvider/SDKContext.ts b/packages/sdk-solid/src/SDKProvider/SDKContext.ts new file mode 100644 index 000000000..811927069 --- /dev/null +++ b/packages/sdk-solid/src/SDKProvider/SDKContext.ts @@ -0,0 +1,17 @@ +import { createContext, useContext } from 'solid-js'; + +import type { SDKContextType } from './SDKProvider.types.js'; + +export const SDKContext = createContext(); + +/** + * @throws Error useSDK was used outside SDKProvider. + * @returns Function to register a factory. + */ +export function useSDK(): SDKContextType { + const context = useContext(SDKContext); + if (!context) { + throw new Error('useSDK was used outside of SDKProvider.'); + } + return context; +} diff --git a/packages/sdk-solid/src/SDKProvider/SDKProvider.tsx b/packages/sdk-solid/src/SDKProvider/SDKProvider.tsx new file mode 100644 index 000000000..57e8679fe --- /dev/null +++ b/packages/sdk-solid/src/SDKProvider/SDKProvider.tsx @@ -0,0 +1,135 @@ +import { AnyFn, initWeb, isIframe, setDebug } from '@tma.js/sdk'; +import { + Accessor, + type Component, + createEffect, + createMemo, + createResource, + from, + onCleanup, +} from 'solid-js'; + +import { SDKContext } from './SDKContext.js'; +import { + SDKContextItem, + SDKContextType, + SDKProviderProps, +} from './SDKProvider.types.js'; + +/** + * Provides access to SDK components and initializes some event listeners for the web version + * of Telegram. + */ +export const SDKProvider: Component = (props) => { + const cache = new Map>(); + + const use: SDKContextType = (factory, ...args) => { + // SDK context already has this value. + if (cache.has(factory)) { + return cache.get(factory)!; + } + + // We are creating a resource as long as factory can sometimes return promise. For example, + // this may happen in case, factory initializes BiometryManager or Viewport. + const [resource] = createResource(() => { + try { + return factory(...args); + } catch (e) { + // Solid can't normally handle errors in a sync way. We need an error to be handled in + // the first frame and this was the only 1 way of doing it I found. + return [e]; + } + }); + + // Signal, which returns computed resource value. + const getResource = createMemo(() => { + // Something went wrong, return an error. + if (resource.error) { + return [resource.error]; + } + + // The resource is loading, return nothing. This usually happens when the factory is async. + if (resource.state !== 'ready') { + return; + } + + // Get a value, stored in the resource and check if it ended up with an error. + const value = resource(); + if (Array.isArray(value)) { + return value; + } + + // Factory may return undefined if it creates the InitData component, for example. + // The returned component may also not allow tracking its changes. It means, it cannot + // be reactive, we just this values as is. + if (!value || !('on' in value)) { + return value; + } + + // Otherwise, we are making value reactive and track its changes. + const get = from((set) => { + set(value); + return value.on('change', () => set(value)); + }); + + // We use this value to retrieve properties having getters. We assume, that if property has + // a getter, it must be reactive. + // NOTE: Yeah, it looks horrible, but I had no other way of doing this. + const prototype = Object.getPrototypeOf(value); + + // Cache with already defined signals. + const propCache: Record> = {}; + + return new Proxy(value, { + get(target: any, property: string | symbol): any { + if (!(property in propCache)) { + const descriptor = Reflect.getOwnPropertyDescriptor(prototype, property); + + // We receive descriptor, describing this property and check if it has getter. In + // case it does, we must make it reactive. Otherwise, we return real value behind + // this property. + propCache[property] = descriptor && ('get' in descriptor) + ? createMemo(() => (get() as any)[property]) + : () => Reflect.get(target, property); + } + return propCache[property](); + }, + }); + }); + + // Define accessor. + function read() { + const v = getResource(); + if (Array.isArray(v)) { + throw v[0]; + } + return v; + } + + // Define accessor "error" property. + Object.defineProperty(read, 'error', { + get() { + const v = getResource(); + return Array.isArray(v) ? v[0] : undefined; + }, + }); + + cache.set(factory, read); + + return read; + } + + // Effect, responsible for debug mode. + createEffect(() => { + setDebug(props.debug || false); + }); + + // Effect, responsible for initializing the app in the web version of Telegram. + createEffect(() => { + if (isIframe()) { + onCleanup(initWeb(props.acceptCustomStyles)); + } + }); + + return {props.children}; +}; diff --git a/packages/sdk-solid/src/SDKProvider/SDKProvider.types.ts b/packages/sdk-solid/src/SDKProvider/SDKProvider.types.ts new file mode 100644 index 000000000..6d3f10fd0 --- /dev/null +++ b/packages/sdk-solid/src/SDKProvider/SDKProvider.types.ts @@ -0,0 +1,39 @@ +import type { AnyFn } from '@tma.js/sdk'; +import type { ParentProps } from 'solid-js'; + +export interface SDKProviderProps extends ParentProps { + /** + * True if SDK should accept styles sent from the Telegram web application. This option is only + * used in web versions of Telegram. + * @default true + */ + acceptCustomStyles?: boolean; + /** + * Enables debug mode. + * @default false + */ + debug?: boolean; +} + +export interface SDKContextItem { + /** + * Returns factory execution result. + * @throws An error, if it occurred during factory call. Use the "error" property before + * to check if something went wrong. + */ + (): ReturnType extends PromiseLike ? T | undefined : ReturnType; + /** + * Error occurred during factory call. + */ + error?: unknown; +} + +export interface SDKContextType { + /** + * Uses specified factory with the passed arguments. In case, this factory was called + * previously, a cached result will be returned. + * @param factory - factory function. + * @param args - factory arguments. + */ + (factory: Fn, ...args: Parameters): SDKContextItem; +} diff --git a/packages/sdk-solid/src/createHOC.tsx b/packages/sdk-solid/src/createHOC.tsx new file mode 100644 index 000000000..b890f04ff --- /dev/null +++ b/packages/sdk-solid/src/createHOC.tsx @@ -0,0 +1,25 @@ +import { type Component, mergeProps } from 'solid-js'; +import type { PartialBy } from '@tma.js/sdk'; + +import type { Hook } from './createHook.js'; + +export interface HOC> { + }>( + prop: PropKey, + Component: Component, + ...args: Parameters + ): Component>; +} + +/** + * Based on the passed hook, creates function returning HOC. Created HOC passes hook result + * to the wrapped component. + * @param hook - hook returning component. + */ +export function createHOC>(hook: H): HOC { + return (prop, Component, ...args) => { + return (props) => { + return ; + }; + }; +} diff --git a/packages/sdk-solid/src/createHook.ts b/packages/sdk-solid/src/createHook.ts index fdf126265..4a073d88b 100644 --- a/packages/sdk-solid/src/createHook.ts +++ b/packages/sdk-solid/src/createHook.ts @@ -1,33 +1,18 @@ -import type { Accessor } from 'solid-js'; +import { AnyFn } from '@tma.js/sdk'; -import { useInitResultDynamicValue, useInitResultValue } from './provider/index.js'; -import type { - DynamicInitResultKey, - InitResultKey, - InitResultValue, - StaticInitResultKey, -} from './types.js'; +import { useSDK } from './SDKProvider/SDKContext.js'; +import { SDKContextItem } from './SDKProvider/SDKProvider.types.js'; -export type Hook = () => Accessor>; - -/** - * Creates hook to retrieve static init result value. - * @param initResultKey - init result key. - */ -export function createHook(initResultKey: K): Hook; +export interface Hook { + (...args: Parameters): SDKContextItem; +} /** - * Creates hook to retrieve dynamic init result value. - * @param initResultKey - init result key. - * @param dynamic - flag to let function know this init result value is dynamic. + * Creates new hook, which firstly attempts to extract a value from the SDK context. In case, + * value is missing, it uses the passed component factory, creates a component, subscribes + * to its changes if required, and returns its reactive copy. + * @param fn */ -export function createHook( - initResultKey: K, - dynamic: true, -): Hook; - -export function createHook(initResultKey: InitResultKey, dynamic?: true): Hook { - return dynamic - ? () => useInitResultDynamicValue(initResultKey as DynamicInitResultKey) - : () => useInitResultValue(initResultKey); +export function createHook(fn: Fn): Hook { + return (...args) => useSDK()(fn, ...args); } diff --git a/packages/sdk-solid/src/hooks-hocs/back-button.ts b/packages/sdk-solid/src/hooks-hocs/back-button.ts new file mode 100644 index 000000000..dbe2e3a13 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/back-button.ts @@ -0,0 +1,14 @@ +import { initBackButton } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the BackButton component instance. + */ +export const useBackButton = createHook(initBackButton); + +/** + * HOC to pass the BackButton component instance to the wrapped component. + */ +export const withBackButton = createHOC(useBackButton); diff --git a/packages/sdk-solid/src/hooks-hocs/biometry-manager.ts b/packages/sdk-solid/src/hooks-hocs/biometry-manager.ts new file mode 100644 index 000000000..4aeeee8f4 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/biometry-manager.ts @@ -0,0 +1,14 @@ +import { initBiometryManager } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the BiometryManager component instance. + */ +export const useBiometryManager = createHook(initBiometryManager); + +/** + * HOC to pass the BiometryManager component instance to the wrapped component. + */ +export const withBiometryManager = createHOC(useBiometryManager); diff --git a/packages/sdk-solid/src/hooks-hocs/closing-behavior.ts b/packages/sdk-solid/src/hooks-hocs/closing-behavior.ts new file mode 100644 index 000000000..84ad13507 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/closing-behavior.ts @@ -0,0 +1,14 @@ +import { initClosingBehavior } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the ClosingBehavior component instance. + */ +export const useClosingBehavior = createHook(initClosingBehavior); + +/** + * HOC to pass the ClosingBehavior component instance to the wrapped component. + */ +export const withClosingBehavior = createHOC(useClosingBehavior); diff --git a/packages/sdk-solid/src/hooks-hocs/cloud-storage.ts b/packages/sdk-solid/src/hooks-hocs/cloud-storage.ts new file mode 100644 index 000000000..b3934c724 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/cloud-storage.ts @@ -0,0 +1,14 @@ +import { initCloudStorage } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the CloudStorage component instance. + */ +export const useCloudStorage = createHook(initCloudStorage); + +/** + * HOC to pass the CloudStorage component instance to the wrapped component. + */ +export const withCloudStorage = createHOC(useCloudStorage); diff --git a/packages/sdk-solid/src/hooks-hocs/haptic-feedback.ts b/packages/sdk-solid/src/hooks-hocs/haptic-feedback.ts new file mode 100644 index 000000000..cdcf95895 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/haptic-feedback.ts @@ -0,0 +1,14 @@ +import { initHapticFeedback } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the HapticFeedback component instance. + */ +export const useHapticFeedback = createHook(initHapticFeedback); + +/** + * HOC to pass the HapticFeedback component instance to the wrapped component. + */ +export const withHapticFeedback = createHOC(useHapticFeedback); diff --git a/packages/sdk-solid/src/hooks-hocs/init-data.ts b/packages/sdk-solid/src/hooks-hocs/init-data.ts new file mode 100644 index 000000000..6f4c8800e --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/init-data.ts @@ -0,0 +1,14 @@ +import { initInitData } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the InitData component instance. + */ +export const useInitData = createHook(initInitData); + +/** + * HOC to pass the InitData component instance to the wrapped component. + */ +export const withInitData = createHOC(useInitData); diff --git a/packages/sdk-solid/src/hooks-hocs/invoice.ts b/packages/sdk-solid/src/hooks-hocs/invoice.ts new file mode 100644 index 000000000..6800250c7 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/invoice.ts @@ -0,0 +1,14 @@ +import { initInvoice } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the Invoice component instance. + */ +export const useInvoice = createHook(initInvoice); + +/** + * HOC to pass the Invoice component instance to the wrapped component. + */ +export const withInvoice = createHOC(useInvoice); diff --git a/packages/sdk-solid/src/hooks-hocs/main-button.ts b/packages/sdk-solid/src/hooks-hocs/main-button.ts new file mode 100644 index 000000000..6ca368ba3 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/main-button.ts @@ -0,0 +1,14 @@ +import { initMainButton } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the MainButton component instance. + */ +export const useMainButton = createHook(initMainButton); + +/** + * HOC to pass the MainButton component instance to the wrapped component. + */ +export const withMainButton = createHOC(useMainButton); diff --git a/packages/sdk-solid/src/hooks-hocs/mini-app.ts b/packages/sdk-solid/src/hooks-hocs/mini-app.ts new file mode 100644 index 000000000..624076643 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/mini-app.ts @@ -0,0 +1,14 @@ +import { initMiniApp } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the MiniApp component instance. + */ +export const useMiniApp = createHook(initMiniApp); + +/** + * HOC to pass the MiniApp component instance to the wrapped component. + */ +export const withMiniApp = createHOC(useMiniApp); diff --git a/packages/sdk-solid/src/hooks-hocs/popup.ts b/packages/sdk-solid/src/hooks-hocs/popup.ts new file mode 100644 index 000000000..5faadee6c --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/popup.ts @@ -0,0 +1,14 @@ +import { initPopup } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the Popup component instance. + */ +export const usePopup = createHook(initPopup); + +/** + * HOC to pass the Popup component instance to the wrapped component. + */ +export const withPopup = createHOC(usePopup); diff --git a/packages/sdk-solid/src/hooks-hocs/qr-scanner.ts b/packages/sdk-solid/src/hooks-hocs/qr-scanner.ts new file mode 100644 index 000000000..c4695d761 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/qr-scanner.ts @@ -0,0 +1,14 @@ +import { initQRScanner } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the QRScanner component instance. + */ +export const useQRScanner = createHook(initQRScanner); + +/** + * HOC to pass the QRScanner component instance to the wrapped component. + */ +export const withQRScanner = createHOC(useQRScanner); diff --git a/packages/sdk-solid/src/hooks-hocs/settings-button.ts b/packages/sdk-solid/src/hooks-hocs/settings-button.ts new file mode 100644 index 000000000..8e65be243 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/settings-button.ts @@ -0,0 +1,14 @@ +import { initSettingsButton } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the SettingsButton component instance. + */ +export const useSettingsButton = createHook(initSettingsButton); + +/** + * HOC to pass the SettingsButton component instance to the wrapped component. + */ +export const withSettingsButton = createHOC(useSettingsButton); diff --git a/packages/sdk-solid/src/hooks-hocs/theme-params.ts b/packages/sdk-solid/src/hooks-hocs/theme-params.ts new file mode 100644 index 000000000..4e6633d0f --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/theme-params.ts @@ -0,0 +1,14 @@ +import { initThemeParams } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the ThemeParams component instance. + */ +export const useThemeParams = createHook(initThemeParams); + +/** + * HOC to pass the ThemeParams component instance to the wrapped component. + */ +export const withThemeParams = createHOC(useThemeParams); diff --git a/packages/sdk-solid/src/hooks-hocs/utils.ts b/packages/sdk-solid/src/hooks-hocs/utils.ts new file mode 100644 index 000000000..48517ea35 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/utils.ts @@ -0,0 +1,14 @@ +import { initUtils } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the Utils component instance. + */ +export const useUtils = createHook(initUtils); + +/** + * HOC to pass the Utils component instance to the wrapped component. + */ +export const withUtils = createHOC(useUtils); diff --git a/packages/sdk-solid/src/hooks-hocs/viewport.ts b/packages/sdk-solid/src/hooks-hocs/viewport.ts new file mode 100644 index 000000000..0fa16d2f3 --- /dev/null +++ b/packages/sdk-solid/src/hooks-hocs/viewport.ts @@ -0,0 +1,14 @@ +import { initViewport } from '@tma.js/sdk'; + +import { createHOC } from '../createHOC.js'; +import { createHook } from '../createHook.js'; + +/** + * Hook to receive the Viewport component instance. + */ +export const useViewport = createHook(initViewport); + +/** + * HOC to pass the Viewport component instance to the wrapped component. + */ +export const withViewport = createHOC(useViewport); diff --git a/packages/sdk-solid/src/index.ts b/packages/sdk-solid/src/index.ts index 2abf7d689..0c6c30d7b 100644 --- a/packages/sdk-solid/src/index.ts +++ b/packages/sdk-solid/src/index.ts @@ -1,33 +1,23 @@ -export { - useThemeParams, - useInitData, - useBackButton, - useClosingBehavior, - useInitDataRaw, - useCloudStorage, - useLaunchParams, - useMainButton, - useHapticFeedback, - useInvoice, - useMiniApp, - usePopup, - usePostEvent, - useQRScanner, - useSettingsButton, - useUtils, - useViewport, -} from './tools/index.js'; -export { - useSDKContext, - SDKProvider, - type SDKProviderProps, - type SDKContextType, -} from './provider/index.js'; -export { - DisplayGate, - type DisplayGateProps, -} from './DisplayGate.js'; +export { useBackButton, withBackButton } from './hooks-hocs/back-button.js'; +export { useBiometryManager, withBiometryManager } from './hooks-hocs/biometry-manager.js'; +export { useClosingBehavior, withClosingBehavior } from './hooks-hocs/closing-behavior.js'; +export { useCloudStorage, withCloudStorage } from './hooks-hocs/cloud-storage.js'; +export { useHapticFeedback, withHapticFeedback } from './hooks-hocs/haptic-feedback.js'; +export { useInitData, withInitData } from './hooks-hocs/init-data.js'; +export { useInvoice, withInvoice } from './hooks-hocs/invoice.js'; +export { useMainButton, withMainButton } from './hooks-hocs/main-button.js'; +export { useMiniApp, withMiniApp } from './hooks-hocs/mini-app.js'; +export { usePopup, withPopup } from './hooks-hocs/popup.js'; +export { useQRScanner, withQRScanner } from './hooks-hocs/qr-scanner.js'; +export { useSettingsButton, withSettingsButton } from './hooks-hocs/settings-button.js'; +export { useThemeParams, withThemeParams } from './hooks-hocs/theme-params.js'; +export { useUtils, withUtils } from './hooks-hocs/utils.js'; +export { useViewport, withViewport } from './hooks-hocs/viewport.js'; +export { useSDK } from './SDKProvider/SDKContext.js'; +export { SDKProvider } from './SDKProvider/SDKProvider.js'; export type { - InitOptions, - InitResult, -} from './types.js'; + SDKContextType, + SDKProviderProps, + SDKContextItem, +} from './SDKProvider/SDKProvider.types.js'; +export * from '@tma.js/sdk'; diff --git a/packages/sdk-solid/src/provider/SDKContext.ts b/packages/sdk-solid/src/provider/SDKContext.ts deleted file mode 100644 index fdf008a66..000000000 --- a/packages/sdk-solid/src/provider/SDKContext.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createContext } from 'solid-js'; - -import type { SDKContextType } from './types.js'; - -export const SDKContext = createContext({ - loading: () => false, - error: () => undefined, - initResult: () => undefined, -}, { name: 'SDKContext' }); diff --git a/packages/sdk-solid/src/provider/SDKProvider.tsx b/packages/sdk-solid/src/provider/SDKProvider.tsx deleted file mode 100644 index 065f921ad..000000000 --- a/packages/sdk-solid/src/provider/SDKProvider.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { init } from '@tma.js/sdk'; -import { createMemo, createResource } from 'solid-js'; - -import { SDKContext } from './SDKContext.js'; -import type { SDKProviderProps } from './types.js'; - -export function SDKProvider(props: SDKProviderProps) { - const [data] = createResource(() => props.options, init); - - const initResult = createMemo(() => { - return data.state === 'ready' ? data() : undefined; - }); - const loading = createMemo(() => data.loading); - const error = createMemo(() => (data.error === undefined ? null : data.error)); - - return ( - - {props.children} - - ); -} diff --git a/packages/sdk-solid/src/provider/index.ts b/packages/sdk-solid/src/provider/index.ts deleted file mode 100644 index b4d806846..000000000 --- a/packages/sdk-solid/src/provider/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './SDKContext.js'; -export * from './SDKProvider.js'; -export * from './types.js'; -export * from './useSDKContext.js'; -export * from './useInitResultDynamicValue.js'; -export * from './useInitResultValue.js'; diff --git a/packages/sdk-solid/src/provider/types.ts b/packages/sdk-solid/src/provider/types.ts deleted file mode 100644 index 363984336..000000000 --- a/packages/sdk-solid/src/provider/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { InitOptions, InitResult } from '@tma.js/sdk'; -import type { Accessor, ParentProps } from 'solid-js'; - -export type SDKProviderProps = ParentProps<{ - /** - * Init function options. - */ - options?: InitOptions; -}>; - -export interface SDKContextType { - /** - * Error occurred during initialization. - */ - error: Accessor; - - /** - * Initialization result. - */ - initResult: Accessor; - - /** - * True if SDK is loading. - */ - loading: Accessor; -} diff --git a/packages/sdk-solid/src/provider/useInitResultDynamicValue.ts b/packages/sdk-solid/src/provider/useInitResultDynamicValue.ts deleted file mode 100644 index 67f11800f..000000000 --- a/packages/sdk-solid/src/provider/useInitResultDynamicValue.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { - type Accessor, - createEffect, - createSignal, - onCleanup, -} from 'solid-js'; - -import { useInitResultValue } from './useInitResultValue.js'; -import type { - DynamicInitResultKey, - InitResultValue, - Trackable, -} from '../types.js'; - -export function useInitResultDynamicValue( - initResultKey: K, -): Accessor> { - // Extract init result value. - const initial = useInitResultValue(initResultKey); - - // Create value which will be returned to the external environment. - const [signal, setSignal] = createSignal(initial(), { equals: false }); - - // Effect which listens to change event and calls update. - createEffect(() => { - onCleanup( - (initial() as Trackable).on('change', () => { - setSignal((prev) => prev); - }), - ); - }); - - return signal; -} diff --git a/packages/sdk-solid/src/provider/useInitResultValue.ts b/packages/sdk-solid/src/provider/useInitResultValue.ts deleted file mode 100644 index c8e4401aa..000000000 --- a/packages/sdk-solid/src/provider/useInitResultValue.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { type Accessor, createMemo } from 'solid-js'; - -import { useSDKContext } from './useSDKContext.js'; -import type { InitResultKey, InitResultValue } from '../types.js'; - -/** - * Returns value by its field name from SDK init result. - * @param key - init result key. - * @throws {Error} SDK is not initialized. - */ -export function useInitResultValue(key: K): Accessor> { - const { initResult } = useSDKContext(); - - // eslint-disable-next-line solid/reactivity - return createMemo>(() => { - const result = initResult(); - - if (!result) { - throw new Error(`Unable to get init result key "${key}" as long as SDK is not initialized`); - } - return result[key]; - }); -} diff --git a/packages/sdk-solid/src/provider/useSDKContext.ts b/packages/sdk-solid/src/provider/useSDKContext.ts deleted file mode 100644 index 0875f8efe..000000000 --- a/packages/sdk-solid/src/provider/useSDKContext.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useContext } from 'solid-js'; - -import { SDKContext } from './SDKContext.js'; -import type { SDKContextType } from './types.js'; - -/** - * Returns current SDK information. - */ -export function useSDKContext(): SDKContextType { - return useContext(SDKContext); -} diff --git a/packages/sdk-solid/src/tools/back-button.ts b/packages/sdk-solid/src/tools/back-button.ts deleted file mode 100644 index 271f3e955..000000000 --- a/packages/sdk-solid/src/tools/back-button.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve BackButton component. - */ -export const useBackButton = createHook('backButton', true); diff --git a/packages/sdk-solid/src/tools/closing-behavior.ts b/packages/sdk-solid/src/tools/closing-behavior.ts deleted file mode 100644 index 724f3953a..000000000 --- a/packages/sdk-solid/src/tools/closing-behavior.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve ClosingBehavior component. - */ -export const useClosingBehavior = createHook('closingBehavior', true); diff --git a/packages/sdk-solid/src/tools/cloud-storage.ts b/packages/sdk-solid/src/tools/cloud-storage.ts deleted file mode 100644 index b88c0f6de..000000000 --- a/packages/sdk-solid/src/tools/cloud-storage.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve CloudStorage component. - */ -export const useCloudStorage = createHook('cloudStorage'); diff --git a/packages/sdk-solid/src/tools/haptic-feedback.ts b/packages/sdk-solid/src/tools/haptic-feedback.ts deleted file mode 100644 index f4cf7d14f..000000000 --- a/packages/sdk-solid/src/tools/haptic-feedback.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve HapticFeedback component. - */ -export const useHapticFeedback = createHook('hapticFeedback'); diff --git a/packages/sdk-solid/src/tools/index.ts b/packages/sdk-solid/src/tools/index.ts deleted file mode 100644 index 8bcd8d4a2..000000000 --- a/packages/sdk-solid/src/tools/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -export * from './back-button.js'; -export * from './closing-behavior.js'; -export * from './cloud-storage.js'; -export * from './haptic-feedback.js'; -export * from './init-data.js'; -export * from './init-data-raw.js'; -export * from './invoice.js'; -export * from './launch-params.js'; -export * from './main-button.js'; -export * from './mini-app.js'; -export * from './popup.js'; -export * from './post-event.js'; -export * from './qr-scanner.js'; -export * from './settings-button.js'; -export * from './theme-params.js'; -export * from './viewport.js'; -export * from './utils.js'; diff --git a/packages/sdk-solid/src/tools/init-data-raw.ts b/packages/sdk-solid/src/tools/init-data-raw.ts deleted file mode 100644 index 34ef7b44e..000000000 --- a/packages/sdk-solid/src/tools/init-data-raw.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve init data raw representation. - */ -export const useInitDataRaw = createHook('initDataRaw'); diff --git a/packages/sdk-solid/src/tools/init-data.ts b/packages/sdk-solid/src/tools/init-data.ts deleted file mode 100644 index 665aa77be..000000000 --- a/packages/sdk-solid/src/tools/init-data.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve InitData component. - */ -export const useInitData = createHook('initData'); diff --git a/packages/sdk-solid/src/tools/invoice.ts b/packages/sdk-solid/src/tools/invoice.ts deleted file mode 100644 index 694d7c733..000000000 --- a/packages/sdk-solid/src/tools/invoice.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve Invoice component. - */ -export const useInvoice = createHook('invoice', true); diff --git a/packages/sdk-solid/src/tools/main-button.ts b/packages/sdk-solid/src/tools/main-button.ts deleted file mode 100644 index a3dd4e078..000000000 --- a/packages/sdk-solid/src/tools/main-button.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve MainButton component. - */ -export const useMainButton = createHook('mainButton', true); diff --git a/packages/sdk-solid/src/tools/mini-app.ts b/packages/sdk-solid/src/tools/mini-app.ts deleted file mode 100644 index 4c30a3ef9..000000000 --- a/packages/sdk-solid/src/tools/mini-app.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve MiniApp component. - */ -export const useMiniApp = createHook('miniApp', true); diff --git a/packages/sdk-solid/src/tools/popup.ts b/packages/sdk-solid/src/tools/popup.ts deleted file mode 100644 index da3618645..000000000 --- a/packages/sdk-solid/src/tools/popup.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve Popup component. - */ -export const usePopup = createHook('popup', true); diff --git a/packages/sdk-solid/src/tools/post-event.ts b/packages/sdk-solid/src/tools/post-event.ts deleted file mode 100644 index 27afffe2d..000000000 --- a/packages/sdk-solid/src/tools/post-event.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve postEvent function. - */ -export const usePostEvent = createHook('postEvent'); diff --git a/packages/sdk-solid/src/tools/qr-scanner.ts b/packages/sdk-solid/src/tools/qr-scanner.ts deleted file mode 100644 index e9de951b1..000000000 --- a/packages/sdk-solid/src/tools/qr-scanner.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve QRScanner component. - */ -export const useQRScanner = createHook('qrScanner', true); diff --git a/packages/sdk-solid/src/tools/settings-button.ts b/packages/sdk-solid/src/tools/settings-button.ts deleted file mode 100644 index 350f1b3ee..000000000 --- a/packages/sdk-solid/src/tools/settings-button.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve SettingsButton component. - */ -export const useSettingsButton = createHook('settingsButton', true); diff --git a/packages/sdk-solid/src/tools/theme-params.ts b/packages/sdk-solid/src/tools/theme-params.ts deleted file mode 100644 index cfdb5d724..000000000 --- a/packages/sdk-solid/src/tools/theme-params.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve ThemeParams component. - */ -export const useThemeParams = createHook('themeParams', true); diff --git a/packages/sdk-solid/src/tools/utils.ts b/packages/sdk-solid/src/tools/utils.ts deleted file mode 100644 index 2a74a1f2f..000000000 --- a/packages/sdk-solid/src/tools/utils.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve Utils component. - */ -export const useUtils = createHook('utils'); diff --git a/packages/sdk-solid/src/tools/viewport.ts b/packages/sdk-solid/src/tools/viewport.ts deleted file mode 100644 index 5b9e3754b..000000000 --- a/packages/sdk-solid/src/tools/viewport.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createHook } from '../createHook.js'; - -/** - * Hook to retrieve Viewport component. - */ -export const useViewport = createHook('viewport', true); diff --git a/packages/sdk-solid/src/types.ts b/packages/sdk-solid/src/types.ts deleted file mode 100644 index 6ff64cf7a..000000000 --- a/packages/sdk-solid/src/types.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { InitOptions, InitResult } from '@tma.js/sdk'; - -export { InitOptions, InitResult }; - -export interface Trackable { - on(event: 'change', listener: () => void): () => void; -} - -/** - * SDK init result keys, which describe values with trackable changes. - */ -export type DynamicInitResultKey = { - [K in InitResultKey]-?: InitResultValue extends Trackable ? K : never; -}[InitResultKey]; - -/** - * SDK init result keys, which describe static values. - */ -export type StaticInitResultKey = Exclude; - -/** - * SDK initialization result key. - */ -export type InitResultKey = keyof InitResult; - -/** - * Returns SDK init result value type by its key. - */ -export type InitResultValue = InitResult[K]; diff --git a/packages/sdk-solid/tsconfig.json b/packages/sdk-solid/tsconfig.json index 93c388f7e..ed174cfa3 100644 --- a/packages/sdk-solid/tsconfig.json +++ b/packages/sdk-solid/tsconfig.json @@ -1,5 +1,11 @@ { - "extends": "tsconfig/solid-library.json", + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "tsconfig/esnext-dom.json", + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "jsx": "preserve", + "jsxImportSource": "solid-js" + }, "include": [ "src" ], @@ -8,4 +14,4 @@ "path": "./tsconfig.node.json" } ] -} \ No newline at end of file +} diff --git a/packages/sdk-solid/tsconfig.node.json b/packages/sdk-solid/tsconfig.node.json index 83dd76b9c..22f762caa 100644 --- a/packages/sdk-solid/tsconfig.node.json +++ b/packages/sdk-solid/tsconfig.node.json @@ -1,5 +1,5 @@ { - "extends": "tsconfig/solid-library.json", + "extends": "./tsconfig.json", "compilerOptions": { "composite": true }, diff --git a/packages/sdk-solid/vite.config.ts b/packages/sdk-solid/vite.config.ts index bafb2d085..83128a8de 100644 --- a/packages/sdk-solid/vite.config.ts +++ b/packages/sdk-solid/vite.config.ts @@ -1,11 +1,23 @@ -import { createViteConfig } from 'build-utils'; import solidPlugin from 'vite-plugin-solid'; +import dts from 'vite-plugin-dts'; +import { defineConfig } from 'vite'; -import packageJson from './package.json'; - -export default createViteConfig({ - packageName: packageJson.name, - formats: ['es', 'cjs'], - external: ['@tma.js/utils', '@tma.js/sdk', 'solid-js'], - plugins: [solidPlugin()], +export default defineConfig({ + plugins: [ + dts({ outDir: 'dist/dts' }), + solidPlugin(), + ], + build: { + outDir: 'dist', + emptyOutDir: true, + sourcemap: true, + rollupOptions: { + external: ['solid-js'], + }, + lib: { + entry: 'src/index.ts', + formats: ['es', 'cjs'], + fileName: 'index', + }, + }, }); diff --git a/packages/sdk/.eslintrc.cjs b/packages/sdk/.eslintrc.cjs deleted file mode 100644 index 63d117348..000000000 --- a/packages/sdk/.eslintrc.cjs +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - extends: ['custom/base'], -}; diff --git a/packages/sdk/build/getConfig.ts b/packages/sdk/build/getConfig.ts new file mode 100644 index 000000000..2756008c1 --- /dev/null +++ b/packages/sdk/build/getConfig.ts @@ -0,0 +1,60 @@ +import { defineConfig, type UserConfigFn } from 'vitest/config'; +import tsconfigPaths from 'vite-tsconfig-paths'; +import dts from 'vite-plugin-dts'; +import { resolve, dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import type { LibraryFormats } from 'vite'; + +export function getConfig({ + filename = 'index', + input, + formats, + declarations = false, +}: { + input: string; + filename?: string; + formats: LibraryFormats[]; + declarations?: boolean; +}): UserConfigFn { + return defineConfig(({ mode }) => { + const tsconfigPath = mode === 'test' + ? './tsconfig.test.json' + : './tsconfig.build.json'; + + return { + plugins: [ + tsconfigPaths({ projects: [tsconfigPath] }), + declarations && dts({ outDir: 'dist/dts', tsconfigPath }), + ], + resolve: { + alias: { + '@': resolve(dirname(fileURLToPath(import.meta.url)), '../src'), + }, + }, + build: { + outDir: 'dist', + emptyOutDir: false, + sourcemap: true, + lib: { + name: 'tmajs.sdk', + entry: input, + formats, + fileName: filename, + }, + }, + test: { + environment: 'happy-dom', + coverage: { + enabled: true, + provider: 'v8', + include: ['src/**/*.ts'], + exclude: ['src/**/*.test.ts'], + branches: 80, + functions: 80, + statements: 80, + lines: 80, + }, + }, + }; + }); +} \ No newline at end of file diff --git a/packages/sdk/create-jsr-config.js b/packages/sdk/create-jsr-config.js deleted file mode 100644 index da4cd68e4..000000000 --- a/packages/sdk/create-jsr-config.js +++ /dev/null @@ -1,12 +0,0 @@ -import { readFileSync, writeFileSync } from 'node:fs'; -import { resolve, dirname } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const dir = dirname(resolve(fileURLToPath(import.meta.url))); -const packageJson = JSON.parse(readFileSync(resolve(dir, 'package.json')).toString()); - -writeFileSync(resolve(dir, 'jsr.json'), JSON.stringify({ - name: '@tma/sdk', - version: packageJson.version, - exports: './src/index.ts', -})); diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 459b5a779..4bcad5770 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -24,13 +24,12 @@ "dist" ], "main": "./dist/index.cjs", - "browser": "./dist/index.iife.js", - "module": "./dist/index.mjs", + "module": "./dist/index.js", "types": "./dist/dts/index.d.ts", "exports": { ".": { "types": "./dist/dts/index.d.ts", - "import": "./dist/index.mjs", + "import": "./dist/index.js", "require": "./dist/index.cjs", "default": "./dist/index.cjs" } @@ -40,13 +39,12 @@ "lint": "eslint src", "lint:fix": "pnpm run lint --fix", "typecheck": "tsc --noEmit -p tsconfig.build.json", - "build": "pnpm run build:default && pnpm run build:iife", - "build:default": "vite build --config vite.config.ts", - "build:iife": "vite build --config vite.iife.config.ts" + "build": "rimraf dist && pnpm run build:default && pnpm run build:iife && pnpm run build:iife:low-level", + "build:default": "vite build -c vite.config.ts", + "build:iife": "vite build -c vite.iife.config.ts", + "build:iife:low-level": "vite build -c vite.iife.low-level.config.ts" }, "devDependencies": { - "build-utils": "workspace:*", - "eslint-config-custom": "workspace:*", "test-utils": "workspace:*", "tsconfig": "workspace:*" }, diff --git a/packages/sdk/src/__tests__/globals.ts b/packages/sdk/src/__tests__/globals.ts deleted file mode 100644 index 2a7c12a63..000000000 --- a/packages/sdk/src/__tests__/globals.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { afterEach, describe, expect, it, vi } from 'vitest'; - -import { - logger, - setDebug, - setTargetOrigin, - targetOrigin, -} from '../globals'; - -afterEach(() => { - vi.restoreAllMocks(); -}); - -describe('logger', () => { - it('should log message in case, debug mode is enabled. Otherwise no output should be shown', () => { - const spy = vi - .spyOn(console, 'log') - .mockImplementation(() => { - }); - - logger.log(123); - expect(spy).not.toHaveBeenCalled(); - - setDebug(true); - logger.log('Some log'); - expect(spy).toHaveBeenCalledTimes(1); - - setDebug(false); - logger.log('Another log'); - expect(spy).toHaveBeenCalledTimes(1); - }); -}); - -describe('setTargetOrigin', () => { - it('should return set value via targetOrigin() function', () => { - setTargetOrigin('my test'); - expect(targetOrigin()).toEqual('my test'); - }); -}); diff --git a/packages/sdk/src/bridge/errors/MethodUnsupportedError.ts b/packages/sdk/src/bridge/errors/MethodUnsupportedError.ts deleted file mode 100644 index c2ca5a41a..000000000 --- a/packages/sdk/src/bridge/errors/MethodUnsupportedError.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Version } from '../../version/types.js'; -import type { MiniAppsMethodName } from '../methods/methods.js'; - -/** - * Error thrown in case, unsupported method was called. - */ -export class MethodUnsupportedError extends Error { - constructor(method: MiniAppsMethodName, version: Version) { - super(`Method "${method}" is unsupported in the Mini Apps version ${version}.`); - Object.setPrototypeOf(this, MethodUnsupportedError.prototype); - } -} diff --git a/packages/sdk/src/bridge/errors/ParameterUnsupportedError.ts b/packages/sdk/src/bridge/errors/ParameterUnsupportedError.ts deleted file mode 100644 index ae639ea28..000000000 --- a/packages/sdk/src/bridge/errors/ParameterUnsupportedError.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Version } from '../../version/types.js'; -import type { MiniAppsMethodName } from '../methods/methods.js'; - -/** - * Error thrown in case, unsupported parameter was used. - */ -export class ParameterUnsupportedError extends Error { - constructor(method: MiniAppsMethodName, param: string, version: Version) { - super(`Parameter "${param}" in method "${method}" is unsupported in the Mini Apps version ${version}.`); - Object.setPrototypeOf(this, ParameterUnsupportedError.prototype); - } -} diff --git a/packages/sdk/src/bridge/events/__tests__/on.ts b/packages/sdk/src/bridge/events/__tests__/on.ts deleted file mode 100644 index 108f34828..000000000 --- a/packages/sdk/src/bridge/events/__tests__/on.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { afterEach, beforeEach, expect, it, vi } from 'vitest'; - -import { createWindow, type WindowSpy } from '../../../../test-utils/createWindow'; -import { dispatchWindowMessageEvent } from '../../../../test-utils/dispatchWindowMessageEvent'; -import { on } from '../on'; - -let windowSpy: WindowSpy; - -beforeEach(() => { - windowSpy = createWindow(); -}); - -afterEach(() => { - windowSpy.mockRestore(); -}); - -it('should call listener in case, Telegram event was created', () => { - const listener = vi.fn(); - on('viewport_changed', listener); - - const eventData = { - height: 123, - width: 321, - is_expanded: false, - is_state_stable: false, - }; - dispatchWindowMessageEvent('viewport_changed', eventData); - - expect(listener).toHaveBeenCalledTimes(1); - expect(listener).toHaveBeenCalledWith(eventData); -}); - -it('should remove listener in case, returned callback was called', () => { - const listener = vi.fn(); - const emit = () => dispatchWindowMessageEvent('viewport_changed', { - height: 123, - width: 321, - is_expanded: false, - is_state_stable: false, - }); - - const off = on('viewport_changed', listener); - emit(); - expect(listener).toHaveBeenCalledTimes(1); - - off(); - emit(); - expect(listener).toHaveBeenCalledTimes(1); -}); diff --git a/packages/sdk/src/bridge/events/__tests__/onTelegramEvent.ts b/packages/sdk/src/bridge/events/__tests__/onTelegramEvent.ts deleted file mode 100644 index 73bc0f2cd..000000000 --- a/packages/sdk/src/bridge/events/__tests__/onTelegramEvent.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { afterEach, beforeEach, expect, it, vi } from 'vitest'; - -import { createWindow, type WindowSpy } from '../../../../test-utils/createWindow'; -import { dispatchWindowMessageEvent } from '../../../../test-utils/dispatchWindowMessageEvent'; -import { onTelegramEvent } from '../onTelegramEvent'; - -afterEach(() => { - vi.restoreAllMocks() -}); - -it('should call passed callback with event type and data in case, window generated "message" event with data, presented as object with properties "eventType" (string) and "eventData" (unknown). Object is converted to string.', () => { - createWindow({ env: 'iframe' }); - const callback = vi.fn(); - onTelegramEvent(callback); - - dispatchWindowMessageEvent('qr_text_received', {}); - - expect(callback).toHaveBeenCalledTimes(1); - expect(callback).toHaveBeenCalledWith('qr_text_received', {}); -}); - -it('should not define event handlers twice in case, window object contains "TelegramGameProxy_receiveEvent" property.', () => { - createWindow(); - (window as any).TelegramGameProxy_receiveEvent = true; - - onTelegramEvent(vi.fn()); - expect(window).not.toHaveProperty('Telegram'); -}); - -it('should call passed callback with event type and data in case, external environment generated event.', () => { - createWindow(); - const callback = vi.fn(); - onTelegramEvent(callback); - - (window as any).TelegramGameProxy_receiveEvent('test', false); - - expect(callback).toHaveBeenCalledTimes(1); - expect(callback).toHaveBeenCalledWith('test', false); -}); - -it('should ignore a message event with unexpected data', () => { - createWindow(); - const callback = vi.fn(); - onTelegramEvent(callback); - - window.dispatchEvent(new MessageEvent('message', { data: null })); - - expect(callback).toHaveBeenCalledTimes(0); -}); diff --git a/packages/sdk/src/bridge/events/createEmitter.ts b/packages/sdk/src/bridge/events/createEmitter.ts deleted file mode 100644 index 283f83e04..000000000 --- a/packages/sdk/src/bridge/events/createEmitter.ts +++ /dev/null @@ -1,105 +0,0 @@ -import type { MiniAppsEventEmitter, MiniAppsEventName } from './events.js'; -import { onTelegramEvent } from './onTelegramEvent.js'; -import { clipboardTextReceived } from './parsers/clipboardTextReceived.js'; -import { customMethodInvoked } from './parsers/customMethodInvoked.js'; -import { invoiceClosed } from './parsers/invoiceClosed.js'; -import { phoneRequested } from './parsers/phoneRequested.js'; -import { popupClosed } from './parsers/popupClosed.js'; -import { qrTextReceived } from './parsers/qrTextReceived.js'; -import { themeChanged } from './parsers/theme-changed.js'; -import { viewportChanged } from './parsers/viewportChanged.js'; -import { writeAccessRequested } from './parsers/writeAccessRequested.js'; -import { EventEmitter } from '../../event-emitter/EventEmitter.js'; -import { logger } from '../../globals.js'; -import { string } from '../../parsing/parsers/string.js'; - -/** - * Returns event emitter which could be safely used, to process events from - * Telegram native application. - */ -export function createEmitter(): MiniAppsEventEmitter { - const emitter: MiniAppsEventEmitter = new EventEmitter(); - const emit: MiniAppsEventEmitter['emit'] = (event: any, ...data: any[]) => { - logger.log('Emitting processed event:', event, ...data); - emitter.emit(event, ...data); - }; - - // Desktop version of Telegram is sometimes not sending the viewport_changed - // event. For example, when main button is shown. That's why we should - // add our own listener to make sure, viewport information is always fresh. - // Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/10 - window.addEventListener('resize', () => { - emit('viewport_changed', { - width: window.innerWidth, - height: window.innerHeight, - is_state_stable: true, - is_expanded: true, - }); - }); - - // In case, any Telegram event was received, we should prepare data before - // passing it to emitter. - onTelegramEvent((eventType: MiniAppsEventName | string, eventData): void => { - logger.log('Received raw event:', eventType, eventData); - - try { - switch (eventType) { - case 'viewport_changed': - return emit(eventType, viewportChanged().parse(eventData)); - - case 'theme_changed': - return emit(eventType, themeChanged().parse(eventData)); - - case 'popup_closed': - // FIXME: Payloads are different on different platforms. - // Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/2 - if ( - // Sent on desktop. - eventData === undefined - // Sent on iOS. - || eventData === null - ) { - return emit(eventType, {}); - } - return emit(eventType, popupClosed().parse(eventData)); - - case 'set_custom_style': - return emit(eventType, string().parse(eventData)); - - case 'qr_text_received': - return emit(eventType, qrTextReceived().parse(eventData)); - - case 'clipboard_text_received': - return emit(eventType, clipboardTextReceived().parse(eventData)); - - case 'invoice_closed': - return emit(eventType, invoiceClosed().parse(eventData)); - - case 'phone_requested': - return emit('phone_requested', phoneRequested().parse(eventData)); - - case 'custom_method_invoked': - return emit('custom_method_invoked', customMethodInvoked().parse(eventData)); - - case 'write_access_requested': - return emit('write_access_requested', writeAccessRequested().parse(eventData)); - - // Events which have no parameters. - case 'main_button_pressed': - case 'back_button_pressed': - case 'settings_button_pressed': - case 'scan_qr_popup_closed': - case 'reload_iframe': - return emit(eventType); - - // All other event listeners will receive unknown type of data. - default: - return emit(eventType as any, eventData); - } - } catch (cause) { - logger.error('Error processing event:', cause); - } - }); - - return emitter; -} diff --git a/packages/sdk/src/bridge/events/__tests__/createEmitter.ts b/packages/sdk/src/bridge/events/event-emitter/createMiniAppsEventEmitter.test.ts similarity index 71% rename from packages/sdk/src/bridge/events/__tests__/createEmitter.ts rename to packages/sdk/src/bridge/events/event-emitter/createMiniAppsEventEmitter.test.ts index f2b00769e..580f8df2d 100644 --- a/packages/sdk/src/bridge/events/__tests__/createEmitter.ts +++ b/packages/sdk/src/bridge/events/event-emitter/createMiniAppsEventEmitter.test.ts @@ -1,21 +1,33 @@ +import { createWindow, type WindowSpy } from '@test-utils/createWindow.js'; +import { dispatchWindowMessageEvent } from '@test-utils/dispatchWindowMessageEvent.js'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { createWindow, type WindowSpy } from '../../../../test-utils/createWindow'; -import { dispatchWindowMessageEvent } from '../../../../test-utils/dispatchWindowMessageEvent'; -import { createEmitter } from '../createEmitter'; -import type { MiniAppsEventName, MiniAppsEventParams } from '../events'; +import { defineEventHandlers as defineEventHandlersFn } from '../event-handlers/defineEventHandlers.js'; +import { createMiniAppsEventEmitter } from './createMiniAppsEventEmitter.js'; +import type { FnToSpy } from '../../../../test-utils/types.js'; +import type { MiniAppsEventName, MiniAppsEventPayload } from '../types.js'; type TestCase = - | [input: any, expected: MiniAppsEventParams] - | MiniAppsEventParams; + | [input: any, expected: MiniAppsEventPayload] + | MiniAppsEventPayload; type TestCases = { - [E in MiniAppsEventName]: MiniAppsEventParams extends undefined + [E in MiniAppsEventName]: MiniAppsEventPayload extends undefined ? [E] : [E, TestCase | TestCase[]]; }[MiniAppsEventName][]; let windowSpy: WindowSpy; +// eslint-disable-next-line max-len +const defineEventHandlers = defineEventHandlersFn as unknown as FnToSpy; + +vi.mock('../event-handlers/defineEventHandlers.js', async () => { + const actual = await vi.importActual('../event-handlers/defineEventHandlers.js'); + + return { + defineEventHandlers: vi.fn((actual as any).defineEventHandlers), + }; +}); beforeEach(() => { windowSpy = createWindow({ @@ -29,8 +41,8 @@ afterEach(() => { }); it('should emit "viewport_changed" event in case, window changed its size', () => { - const emitter = createEmitter(); const spy = vi.fn(); + const [emitter] = createMiniAppsEventEmitter(); emitter.on('viewport_changed', spy); @@ -45,6 +57,12 @@ it('should emit "viewport_changed" event in case, window changed its size', () = }); }); +it('should call defineEventHandlers function to initialize global handlers', () => { + defineEventHandlers.mockClear(); + createMiniAppsEventEmitter(); + expect(defineEventHandlers).toHaveBeenCalledOnce(); +}); + describe('events handling', () => { const testCases: TestCases = [ ['viewport_changed', { @@ -96,8 +114,7 @@ describe('events handling', () => { testCases.forEach(([event, inputOrCaseOrCases]) => { it(`should correctly handle "${event}" event data`, () => { const spy = vi.fn(); - const emitter = createEmitter(); - + const [emitter] = createMiniAppsEventEmitter(); emitter.on(event, spy); // No expected data to be passed to listener. @@ -132,8 +149,7 @@ describe('events handling', () => { it('should not emit event in case, it contains incorrect payload', () => { const spy = vi.fn(); - const emitter = createEmitter(); - + const [emitter] = createMiniAppsEventEmitter(); emitter.on('viewport_changed', spy); dispatchWindowMessageEvent('viewport_changed', 'broken data'); diff --git a/packages/sdk/src/bridge/events/event-emitter/createMiniAppsEventEmitter.ts b/packages/sdk/src/bridge/events/event-emitter/createMiniAppsEventEmitter.ts new file mode 100644 index 000000000..29fa2ab6a --- /dev/null +++ b/packages/sdk/src/bridge/events/event-emitter/createMiniAppsEventEmitter.ts @@ -0,0 +1,159 @@ +import { logger } from '@/debug/debug.js'; +import { EventEmitter } from '@/events/event-emitter/EventEmitter.js'; +import { onWindow } from '@/events/onWindow.js'; +import { boolean } from '@/parsing/parsers/boolean.js'; +import { json } from '@/parsing/parsers/json.js'; +import { number } from '@/parsing/parsers/number.js'; +import { rgb } from '@/parsing/parsers/rgb.js'; +import { string } from '@/parsing/parsers/string.js'; +import { toRecord } from '@/parsing/toRecord.js'; +import type { RGB } from '@/colors/types.js'; + +import { type MiniAppsMessage, parseMessage } from '../../parseMessage.js'; +import { cleanupEventHandlers } from '../event-handlers/cleanupEventHandlers.js'; +import { defineEventHandlers } from '../event-handlers/defineEventHandlers.js'; +import type { MiniAppsEventEmitter, MiniAppsEventName, MiniAppsEventPayload } from '../types.js'; + +const popupClosedParser = json({ + button_id: (value) => ( + value === null || value === undefined + ? undefined + : string().parse(value) + ), +}); + +/** + * Parsers for each Mini Apps event. + * + * This map should be cleaned + */ +const parsers: { + [E in MiniAppsEventName]?: { + parse(value: unknown): MiniAppsEventPayload; + } +} = { + clipboard_text_received: json({ + req_id: string(), + data: (value) => (value === null ? value : string().optional().parse(value)), + }), + custom_method_invoked: json({ + req_id: string(), + result: (value) => value, + error: string().optional(), + }), + invoice_closed: json({ + slug: string(), + status: string(), + }), + phone_requested: json({ + status: string(), + }), + popup_closed: { + parse: (value) => popupClosedParser.parse(value ?? {}), + }, + qr_text_received: json({ + data: string().optional(), + }), + theme_changed: json({ + theme_params: (value) => { + const parser = rgb().optional(); + + return Object + .entries(toRecord(value)) + .reduce>>((acc, [k, v]) => { + acc[k] = parser.parse(v); + return acc; + }, {}); + }, + }), + viewport_changed: json({ + height: number(), + width: (value) => ( + value === null || value === undefined + ? window.innerWidth + : number().parse(value) + ), + is_state_stable: boolean(), + is_expanded: boolean(), + }), + write_access_requested: json({ + status: string(), + }), +}; + +/** + * Creates new event emitter, which handles events from the Telegram application. + */ +export function createMiniAppsEventEmitter(): [ + /** + * Created event emitter. + */ + emitter: MiniAppsEventEmitter, + /** + * Function to dispose created emitter. + */ + dispose: () => void, +] { + const emitter: MiniAppsEventEmitter = new EventEmitter(); + + // Define event handles, which will proxy native method calls to their web version. + defineEventHandlers(); + + // List of cleanup functions, which should be called on dispose. + let cleanupFunctions = [ + // Don't forget to remove created handlers. + cleanupEventHandlers, + // Add "resize" event listener to make sure, we always have fresh viewport information. + // Desktop version of Telegram is sometimes not sending the viewport_changed + // event. For example, when the MainButton is shown. That's why we should + // add our own listener to make sure, viewport information is always fresh. + // Issue: https://github.com/Telegram-Mini-Apps/tma.js/issues/10 + onWindow('resize', () => { + emitter.emit('viewport_changed', { + width: window.innerWidth, + height: window.innerHeight, + is_state_stable: true, + is_expanded: true, + }); + }), + // Add listener, which handles events sent from the Telegram web application and also events + // generated by the local emitEvent function. + onWindow('message', (event) => { + // Ignore non-parent window messages. + if (event.source !== window.parent) { + return; + } + + // Parse incoming event data. + let message: MiniAppsMessage; + try { + message = parseMessage(event.data); + } catch { + // We ignore incorrect messages as they could be generated by any other code. + return; + } + + const { eventType, eventData } = message; + const parser = parsers[eventType as keyof typeof parsers]; + + try { + const data = parser ? parser.parse(eventData) : eventData; + // eslint-disable-next-line prefer-spread + emitter.emit(...((data ? [eventType, data] : [eventType]) as [any, any])); + } catch (cause) { + logger.error( + `An error occurred processing the "${eventType}" event from the Telegram application. Please, file an issue here: https://github.com/Telegram-Mini-Apps/tma.js/issues/new/choose`, + message, + cause, + ); + } + }), + // Clear emitter bound events. + () => emitter.clear(), + ]; + + return [emitter, () => { + cleanupFunctions.forEach((l) => l()); + cleanupFunctions = []; + }]; +} diff --git a/packages/sdk/src/bridge/events/__tests__/singletonEmitter.ts b/packages/sdk/src/bridge/events/event-emitter/singleton.test.ts similarity index 54% rename from packages/sdk/src/bridge/events/__tests__/singletonEmitter.ts rename to packages/sdk/src/bridge/events/event-emitter/singleton.test.ts index 46da6d8c3..c4991c7c0 100644 --- a/packages/sdk/src/bridge/events/__tests__/singletonEmitter.ts +++ b/packages/sdk/src/bridge/events/event-emitter/singleton.test.ts @@ -1,8 +1,8 @@ +import { createWindow } from '@test-utils/createWindow.js'; import { afterEach, beforeEach, expect, it } from 'vitest'; +import type { WindowSpy } from '@test-utils/createWindow.js'; -import type { WindowSpy } from '../../../../test-utils/createWindow'; -import { createWindow } from '../../../../test-utils/createWindow'; -import { singletonEmitter } from '../singletonEmitter'; +import { miniAppsEventEmitter } from './singleton.js'; let windowSpy: WindowSpy; @@ -18,5 +18,5 @@ afterEach(() => { }); it('should return the same instance of emitter', () => { - expect(singletonEmitter()).toEqual(singletonEmitter()); + expect(miniAppsEventEmitter()).toEqual(miniAppsEventEmitter()); }); diff --git a/packages/sdk/src/bridge/events/event-emitter/singleton.ts b/packages/sdk/src/bridge/events/event-emitter/singleton.ts new file mode 100644 index 000000000..53a943c4b --- /dev/null +++ b/packages/sdk/src/bridge/events/event-emitter/singleton.ts @@ -0,0 +1,34 @@ +import { createSingleton } from '@/misc/createSingleton.js'; + +import { createMiniAppsEventEmitter } from './createMiniAppsEventEmitter.js'; +import type { MiniAppsEventEmitter } from '../types.js'; + +const [get, resetMiniAppsEventEmitter] = createSingleton( + (reset) => { + const [emitter, cleanup] = createMiniAppsEventEmitter(); + + // Rewire "off" method and make it reset singleton if no event listeners left. + const off = emitter.off.bind(emitter); + emitter.off = (event, listener) => { + const { count } = emitter; + off(event, listener); + + // If event emitter now has no listeners, we can perform a reset. + if (count && !emitter.count) { + reset(); + } + }; + + return [emitter, cleanup] as const; + }, + ([, cleanup]) => cleanup(), +); + +/** + * Returns Mini Apps event emitter singleton. + */ +export function miniAppsEventEmitter(): MiniAppsEventEmitter { + return get()[0]; +} + +export { resetMiniAppsEventEmitter }; diff --git a/packages/sdk/src/bridge/events/event-handlers/cleanupEventHandlers.test.ts b/packages/sdk/src/bridge/events/event-handlers/cleanupEventHandlers.test.ts new file mode 100644 index 000000000..717d9f0d8 --- /dev/null +++ b/packages/sdk/src/bridge/events/event-handlers/cleanupEventHandlers.test.ts @@ -0,0 +1,22 @@ +import { it, expect, vi, afterEach } from 'vitest'; + +import { cleanupEventHandlers } from './cleanupEventHandlers.js'; + +afterEach(() => { + vi.restoreAllMocks(); +}); + +it('should delete window properties: TelegramGameProxy_receiveEvent, TelegramGameProxy, Telegram', () => { + const wnd: Record = {}; + vi + .spyOn(window, 'window', 'get') + .mockImplementation(() => ({ + TelegramGameProxy_receiveEvent: {}, + TelegramGameProxy: { receiveEvent: {} }, + Telegram: { WebView: { receiveEvent: {} } }, + } as any)); + + cleanupEventHandlers(); + + expect(wnd).toStrictEqual({}); +}); \ No newline at end of file diff --git a/packages/sdk/src/bridge/events/event-handlers/cleanupEventHandlers.ts b/packages/sdk/src/bridge/events/event-handlers/cleanupEventHandlers.ts new file mode 100644 index 000000000..b7906f108 --- /dev/null +++ b/packages/sdk/src/bridge/events/event-handlers/cleanupEventHandlers.ts @@ -0,0 +1,8 @@ +/** + * Removes global event handlers, used by the package. + */ +export function cleanupEventHandlers(): void { + ['TelegramGameProxy_receiveEvent', 'TelegramGameProxy', 'Telegram'].forEach((prop) => { + delete window[prop as keyof Window]; + }); +} diff --git a/packages/sdk/src/bridge/events/event-handlers/defineEventHandlers.test.ts b/packages/sdk/src/bridge/events/event-handlers/defineEventHandlers.test.ts new file mode 100644 index 000000000..af8f0e35e --- /dev/null +++ b/packages/sdk/src/bridge/events/event-handlers/defineEventHandlers.test.ts @@ -0,0 +1,23 @@ +import { it, expect, vi, afterEach } from 'vitest'; +import { emitMiniAppsEvent } from '@/bridge/events/event-handlers/emitMiniAppsEvent.js'; + +import { defineEventHandlers } from './defineEventHandlers.js'; + +afterEach(() => { + vi.restoreAllMocks(); +}); + +it('should should specify emitMiniAppsEvent function by paths [window.TelegramGameProxy_receiveEvent, window.TelegramGameProxy.receiveEvent, window.Telegram.WebView.receiveEvent]', () => { + const wnd: Record = {}; + vi + .spyOn(window, 'window', 'get') + .mockImplementation(() => wnd as any); + + defineEventHandlers(); + + expect(wnd).toStrictEqual({ + TelegramGameProxy_receiveEvent: emitMiniAppsEvent, + TelegramGameProxy: { receiveEvent: emitMiniAppsEvent }, + Telegram: { WebView: { receiveEvent: emitMiniAppsEvent } }, + }); +}); \ No newline at end of file diff --git a/packages/sdk/src/bridge/events/event-handlers/defineEventHandlers.ts b/packages/sdk/src/bridge/events/event-handlers/defineEventHandlers.ts new file mode 100644 index 000000000..c003bb883 --- /dev/null +++ b/packages/sdk/src/bridge/events/event-handlers/defineEventHandlers.ts @@ -0,0 +1,33 @@ +import { emitMiniAppsEvent } from './emitMiniAppsEvent.js'; + +/** + * Defines special handlers by known paths, which are recognized by + * Telegram as ports to receive events. This function also sets special + * function in global window object to prevent duplicate declaration. + */ +export function defineEventHandlers() { + // Iterate over each path, where "receiveEvent" function should be + // defined. This function is called by external environment in case, + // it wants to emit some event. + [ + ['TelegramGameProxy_receiveEvent'], // Windows Phone. + ['TelegramGameProxy', 'receiveEvent'], // Desktop. + ['Telegram', 'WebView', 'receiveEvent'], // Android and iOS. + ].forEach((path) => { + // Path starts from the "window" object. + let pointer = window as any; + + path.forEach((item, idx, arr) => { + // We are on the last iteration, where function property name is passed. + if (idx === arr.length - 1) { + pointer[item] = emitMiniAppsEvent; + return; + } + + if (!(item in pointer)) { + pointer[item] = {}; + } + pointer = pointer[item]; + }); + }); +} diff --git a/packages/sdk/src/bridge/events/event-handlers/emitMiniAppsEvent.test.ts b/packages/sdk/src/bridge/events/event-handlers/emitMiniAppsEvent.test.ts new file mode 100644 index 000000000..6343e4887 --- /dev/null +++ b/packages/sdk/src/bridge/events/event-handlers/emitMiniAppsEvent.test.ts @@ -0,0 +1,17 @@ +import { expect, it, vi } from 'vitest'; + +import { emitMiniAppsEvent } from './emitMiniAppsEvent.js'; + +it('should call window.dispatchEvent with the Message event containing properties "data" property equal to { eventType, eventData } stringified and "source" property equal to window.parent', () => { + const dispatch = vi.spyOn(window, 'dispatchEvent').mockImplementationOnce(() => null as any); + vi.spyOn(window, 'parent', 'get').mockImplementationOnce(() => 'PARENT' as any); + emitMiniAppsEvent('test', 'some-data'); + expect(dispatch).toHaveBeenCalledOnce(); + + expect(dispatch.mock.calls[0][0]).toBeInstanceOf(MessageEvent); + expect(dispatch.mock.calls[0][0]).toMatchObject({ + type: 'message', + data: '{"eventType":"test","eventData":"some-data"}', + source: 'PARENT' as any, + }); +}); diff --git a/packages/sdk/src/bridge/events/event-handlers/emitMiniAppsEvent.ts b/packages/sdk/src/bridge/events/event-handlers/emitMiniAppsEvent.ts new file mode 100644 index 000000000..b570c379b --- /dev/null +++ b/packages/sdk/src/bridge/events/event-handlers/emitMiniAppsEvent.ts @@ -0,0 +1,15 @@ +/** + * Emits event sent from Telegram native application like it was sent in + * default web environment between 2 iframes. It dispatches new MessageEvent + * and expects it to be handled via `window.addEventListener('message', ...)` + * as developer would do it to handle messages sent from the parent iframe. + * @param eventType - event name. + * @param eventData - event payload. + */ +export function emitMiniAppsEvent(eventType: string, eventData: unknown): void { + window.dispatchEvent(new MessageEvent('message', { + data: JSON.stringify({ eventType, eventData }), + // We specify window.parent to imitate the case, the parent iframe sent us this event. + source: window.parent, + })); +} diff --git a/packages/sdk/src/bridge/events/events.ts b/packages/sdk/src/bridge/events/events.ts deleted file mode 100644 index 594ef1172..000000000 --- a/packages/sdk/src/bridge/events/events.ts +++ /dev/null @@ -1,164 +0,0 @@ -import type { ClipboardTextReceivedPayload } from './parsers/clipboardTextReceived.js'; -import type { CustomMethodInvokedPayload } from './parsers/customMethodInvoked.js'; -import type { InvoiceClosedPayload } from './parsers/invoiceClosed.js'; -import type { PhoneRequestedPayload } from './parsers/phoneRequested.js'; -import type { PopupClosedPayload } from './parsers/popupClosed.js'; -import type { QrTextReceivedPayload } from './parsers/qrTextReceived.js'; -import type { ThemeChangedPayload } from './parsers/theme-changed.js'; -import type { ViewportChangedPayload } from './parsers/viewportChanged.js'; -import type { WriteAccessRequestedPayload } from './parsers/writeAccessRequested.js'; -import type { EventEmitter } from '../../event-emitter/EventEmitter.js'; -import type { AnySubscribeListener, EventListener, EventParams } from '../../event-emitter/types.js'; -import type { Not } from '../../types/logical.js'; -import type { IsNever } from '../../types/utils.js'; - -/** - * Map where key is known event name, and value is its listener. - * @see https://docs.telegram-mini-apps.com/platform/events - */ -export interface MiniAppsEvents { - /** - * User clicked back button. - * @since v6.1 - * @see https://docs.telegram-mini-apps.com/platform/events#back-button-pressed - */ - back_button_pressed: () => void; - - /** - * Telegram application attempted to extract text from clipboard. - * @param payload - event payload. - * @since v6.4 - * @see https://docs.telegram-mini-apps.com/platform/events#clipboard-text-received - */ - clipboard_text_received: (payload: ClipboardTextReceivedPayload) => void; - - /** - * Custom method invocation completed. - * @param payload - event payload. - * @since v6.9 - * @see https://docs.telegram-mini-apps.com/platform/events#custom-method-invoked - */ - custom_method_invoked: (payload: CustomMethodInvokedPayload) => void; - - /** - * An invoice was closed. - * @param payload - invoice close information. - * @see https://docs.telegram-mini-apps.com/platform/events#invoice-closed - */ - invoice_closed: (payload: InvoiceClosedPayload) => void; - - /** - * User clicked the Main Button. - * @see https://docs.telegram-mini-apps.com/platform/events#main-button-pressed - */ - main_button_pressed: () => void; - - /** - * Application received phone access request status. - * @param payload - event payload. - * @since v6.9 - * @see https://docs.telegram-mini-apps.com/platform/events#phone-requested - */ - phone_requested: (payload: PhoneRequestedPayload) => void; - - /** - * Popup was closed. - * @param payload - event payload. - * @see https://docs.telegram-mini-apps.com/platform/events#popup-closed - */ - popup_closed: (payload: PopupClosedPayload) => void; - - /** - * Parent iframe requested current iframe reload. - * @see https://docs.telegram-mini-apps.com/platform/events#reload-iframe - */ - reload_iframe: () => void; - - /** - * The QR scanner scanned some QR and extracted its content. - * @param payload - event payload. - * @since v6.4 - * @see https://docs.telegram-mini-apps.com/platform/events#qr-text-received - */ - qr_text_received: (payload: QrTextReceivedPayload) => void; - - /** - * QR scanner was closed. - * @since v6.4 - * @see https://docs.telegram-mini-apps.com/platform/events#scan-qr-popup-closed - */ - scan_qr_popup_closed: () => void; - - /** - * The event which is usually sent by the Telegram web application. Its payload represents - * `