From 32a578ba79e22d65c6b60990bf16e8d116d39eb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 18 Jun 2024 09:50:59 +0400 Subject: [PATCH 01/75] feat: Intro to README. --- README.md | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1b8dea9..a3528e3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,92 @@ -# nextra-demo -A comprehensive demo of using nextra for a documentation site with Auth (private pages), Search and Analytics! +
+ +# Learn Nextra + +[![HitCount](https://hits.dwyl.com/dwyl/nextra-demo.svg?style=flat-square)](https://hits.dwyl.com/dwyl/nextra-demo) +[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat-square)](https://github.com/dwyl/nextra-demo/issues) + +A comprehensive demo +of using `Nextra` for documentation. +Learn how to create a site with +**authentication** +(private pages), +search and analytics! + +
+ + + +- [Learn Nextra](#learn-nextra) +- [Why?](#why) +- [What?](#what) +- [Who?](#who) +- [How?](#how) + + +# Why? + +If you work building software, +you must have come across technical documentation at some point in your career. +Either be it an API reference or internal manuals, +technical documentation +**is vital for the development process**. +Everyone expects it, +but without it, +knowledge of the application becomes siloed +within individuals which lead to inefficiencies +in the whole development process. + +To ensure long-term sustainability of your software projects, +having a clear and detailed record +of the `why`, `how` and `what` +helps maintain consistency +and increases the quality of your work! + +Whether it is meant as an internal reference +or you're creating documentation for public-facing clients +that are using your project, +having documentation benefits both the developers and users alike. + + +# What? + +[`Nextra`](https://nextra.site/) is a framework +that makes it easy for you to create a documentation static website +fully optimized and powered by [`Next.js`](https://nextjs.org/). + +It simpifies the process of creating and maintaining documentation +by offering a myriad of features, such as: +- themable design system. +- markdown support. +- full-text search out-of-the-box. +- automatic [`a11y`](https://www.a11yproject.com/). +- filesystem-based organization. + +Its integration with `Next.js` means that it's fully customizable, +making it ideal for your team to quickly generate a website +that is useful for both internal and external documentation. + + +# Who? + +This walkthrough is meant for beginners of the framework +but also seasoned software developers +that want to create internal and external documentation for their teams. + +This will **not be an introduction to technical writing**, +it will solely focus on the `Nextra` framework. +We recommend visiting https://developers.google.com/tech-writing/overview +if you are interested in learning more about technical writing. + +If you find it useful, give the repo a star! ⭐️ + +If you get stuck, have questions/suggestions +or just want to discuss this further, +[do open an issue](https://github.com/dwyl/nextra-demo/issues)! + + +# How? + From 988e1607df2e48b30a04ca744e635572e3723494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 18 Jun 2024 10:15:04 +0400 Subject: [PATCH 02/75] feat: Add set up project. --- README.md | 130 ++ next.config.js | 6 + package.json | 14 + pages/index.mdx | 3 + pnpm-lock.yaml | 3161 ++++++++++++++++++++++++++++++++++++++++++++++ theme.config.jsx | 6 + 6 files changed, 3320 insertions(+) create mode 100644 next.config.js create mode 100644 package.json create mode 100644 pages/index.mdx create mode 100644 pnpm-lock.yaml create mode 100644 theme.config.jsx diff --git a/README.md b/README.md index a3528e3..07077e3 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [What?](#what) - [Who?](#who) - [How?](#how) + - [0. Start a new project](#0-start-a-new-project) +- [1. Organizing your content](#1-organizing-your-content) # Why? @@ -90,3 +92,131 @@ or just want to discuss this further, # How? +Are we ready to start? Let's go! + +> [!TIP] +> +> Some of the information found in this document +> can also be found in the [`Nextra`'s offical docs](https://nextra.site/docs). +> We recommend going through their documentation +> (it's not long) to better have a feeling over the framework. + +When using `Nextra`, +you first have to make a choice: +- you either use a *default theme*. +- you customize your own. + +The vast majority of people will go for the former. +However, if you are looking to have a more customized look, +you may have to create your own theme. +[It's easier to start with a custom theme than using a default one and change it afterwards](https://github.com/shuding/nextra/issues/2926). + +In our case, +we'll start with the default theme and change it if needed. + + +## 0. Start a new project + +Let's create our project. +We first need to install some dependencies. +We're going to use [`pnpm`](https://pnpm.io/) +throughout the project to manage dependencies. + +```sh +pnpm add next react react-dom nextra nextra-theme-docs +``` + +This will create a `package.json` file +and install the dependencies under `node_modules`. + +Now, let's add some scripts to `package.json` +to be able to run our application. +Add the following: + +```json +"scripts": { + "dev": "next", + "build": "next build", + "start": "next start" +}, +``` + +Your `package.json` will look something like this. + +```json +{ + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "next": "^14.2.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "nextra": "^2.13.4", + "nextra-theme-docs": "^2.13.4" + } +} +``` + +Next, we need to add a `Nextra` config file. +Because we're starting a project from scratch, +it has no idea it's a `Next.js` project. +Create a file called `next.config.js` and add the following. + +```js +const withNextra = require('nextra')({ + theme: 'nextra-theme-docs', + themeConfig: './theme.config.jsx' +}) + +module.exports = withNextra() +``` + +Lastly, we need to create +a corresponding `theme.config.jsx` file in your project’s root directory. +It will be used to configure our `Nextra`'s site theme. +We'll just add the basic ones. + +> [!TIP] +> +> You can check the full theme configurations +> [in their documentation](https://nextra.site/docs/docs-theme/theme-configuration). + +Now we're ready to bounce! +Because `Nextra` is a **file-based system framework** +(much like `Next.js`), +you will have to create all the documentation +under the `pages` folder. +Let's start create our first one under `pages/index.mdx`! + +```mdx +# Welcome to our docs! + +Hello, world! +``` + +> [!NOTE] +> +> [`mdx`](https://mdxjs.com/) files are markdown files +> that allow you to write `JSX` content. +> You can import components and embed them within your markdown files. + +Let's see our handiwork. +Run `pnpm run dev` +and visit `http://localhost:3000`. +You should see your page! + +

+ +

+ +Congratulations! +You've just set up your documentation website! +Give yourself a pat on the back. 👏 + + +# 1. Organizing your content + + diff --git a/next.config.js b/next.config.js new file mode 100644 index 0000000..558bf1e --- /dev/null +++ b/next.config.js @@ -0,0 +1,6 @@ +const withNextra = require("nextra")({ + theme: "nextra-theme-docs", + themeConfig: "./theme.config.jsx", +}); + +module.exports = withNextra(); diff --git a/package.json b/package.json new file mode 100644 index 0000000..32a5641 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "next": "^14.2.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "nextra": "^2.13.4", + "nextra-theme-docs": "^2.13.4" + } +} diff --git a/pages/index.mdx b/pages/index.mdx new file mode 100644 index 0000000..561c2c8 --- /dev/null +++ b/pages/index.mdx @@ -0,0 +1,3 @@ +# Welcome to our docs! + +Hello, world! \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..a9f3e63 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,3161 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + next: + specifier: ^14.2.4 + version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + nextra: + specifier: ^2.13.4 + version: 2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + nextra-theme-docs: + specifier: ^2.13.4 + version: 2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: + specifier: ^18.3.1 + version: 18.3.1 + react-dom: + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) + +packages: + + '@babel/runtime@7.24.7': + resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==} + engines: {node: '>=6.9.0'} + + '@braintree/sanitize-url@6.0.4': + resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} + + '@headlessui/react@1.7.19': + resolution: {integrity: sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==} + engines: {node: '>=10'} + peerDependencies: + react: ^16 || ^17 || ^18 + react-dom: ^16 || ^17 || ^18 + + '@mdx-js/mdx@2.3.0': + resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} + + '@mdx-js/react@2.3.0': + resolution: {integrity: sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==} + peerDependencies: + react: '>=16' + + '@napi-rs/simple-git-android-arm-eabi@0.1.16': + resolution: {integrity: sha512-dbrCL0Pl5KZG7x7tXdtVsA5CO6At5ohDX3myf5xIYn9kN4jDFxsocl8bNt6Vb/hZQoJd8fI+k5VlJt+rFhbdVw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@napi-rs/simple-git-android-arm64@0.1.16': + resolution: {integrity: sha512-xYz+TW5J09iK8SuTAKK2D5MMIsBUXVSs8nYp7HcMi8q6FCRO7yJj96YfP9PvKsc/k64hOyqGmL5DhCzY9Cu1FQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@napi-rs/simple-git-darwin-arm64@0.1.16': + resolution: {integrity: sha512-XfgsYqxhUE022MJobeiX563TJqyQyX4FmYCnqrtJwAfivESVeAJiH6bQIum8dDEYMHXCsG7nL8Ok0Dp8k2m42g==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@napi-rs/simple-git-darwin-x64@0.1.16': + resolution: {integrity: sha512-tkEVBhD6vgRCbeWsaAQqM3bTfpIVGeitamPPRVSbsq8qgzJ5Dx6ZedH27R7KSsA/uao7mZ3dsrNLXbu1Wy5MzA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@napi-rs/simple-git-linux-arm-gnueabihf@0.1.16': + resolution: {integrity: sha512-R6VAyNnp/yRaT7DV1Ao3r67SqTWDa+fNq2LrNy0Z8gXk2wB9ZKlrxFtLPE1WSpWknWtyRDLpRlsorh7Evk7+7w==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@napi-rs/simple-git-linux-arm64-gnu@0.1.16': + resolution: {integrity: sha512-LAGI0opFKw/HBMCV2qIBK3uWSEW9h4xd2ireZKLJy8DBPymX6NrWIamuxYNyCuACnFdPRxR4LaRFy4J5ZwuMdw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@napi-rs/simple-git-linux-arm64-musl@0.1.16': + resolution: {integrity: sha512-I57Ph0F0Yn2KW93ep+V1EzKhACqX0x49vvSiapqIsdDA2PifdEWLc1LJarBolmK7NKoPqKmf6lAKKO9lhiZzkg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@napi-rs/simple-git-linux-x64-gnu@0.1.16': + resolution: {integrity: sha512-AZYYFY2V7hlcQASPEOWyOa3e1skzTct9QPzz0LiDM3f/hCFY/wBaU2M6NC5iG3d2Kr38heuyFS/+JqxLm5WaKA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@napi-rs/simple-git-linux-x64-musl@0.1.16': + resolution: {integrity: sha512-9TyMcYSBJwjT8jwjY9m24BZbu7ozyWTjsmYBYNtK3B0Um1Ov6jthSNneLVvouQ6x+k3Ow+00TiFh6bvmT00r8g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@napi-rs/simple-git-win32-arm64-msvc@0.1.16': + resolution: {integrity: sha512-uslJ1WuAHCYJWui6xjsyT47SjX6KOHDtClmNO8hqKz1pmDSNY7AjyUY8HxvD1lK9bDnWwc4JYhikS9cxCqHybw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/simple-git-win32-x64-msvc@0.1.16': + resolution: {integrity: sha512-SoEaVeCZCDF1MP+M9bMSXsZWgEjk4On9GWADO5JOulvzR1bKjk0s9PMHwe/YztR9F0sJzrCxwtvBZowhSJsQPg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@napi-rs/simple-git@0.1.16': + resolution: {integrity: sha512-C5wRPw9waqL2jk3jEDeJv+f7ScuO3N0a39HVdyFLkwKxHH4Sya4ZbzZsu2JLi6eEqe7RuHipHL6mC7B2OfYZZw==} + engines: {node: '>= 10'} + + '@next/env@14.2.4': + resolution: {integrity: sha512-3EtkY5VDkuV2+lNmKlbkibIJxcO4oIHEhBWne6PaAp+76J9KoSsGvNikp6ivzAT8dhhBMYrm6op2pS1ApG0Hzg==} + + '@next/swc-darwin-arm64@14.2.4': + resolution: {integrity: sha512-AH3mO4JlFUqsYcwFUHb1wAKlebHU/Hv2u2kb1pAuRanDZ7pD/A/KPD98RHZmwsJpdHQwfEc/06mgpSzwrJYnNg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@14.2.4': + resolution: {integrity: sha512-QVadW73sWIO6E2VroyUjuAxhWLZWEpiFqHdZdoQ/AMpN9YWGuHV8t2rChr0ahy+irKX5mlDU7OY68k3n4tAZTg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@14.2.4': + resolution: {integrity: sha512-KT6GUrb3oyCfcfJ+WliXuJnD6pCpZiosx2X3k66HLR+DMoilRb76LpWPGb4tZprawTtcnyrv75ElD6VncVamUQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-arm64-musl@14.2.4': + resolution: {integrity: sha512-Alv8/XGSs/ytwQcbCHwze1HmiIkIVhDHYLjczSVrf0Wi2MvKn/blt7+S6FJitj3yTlMwMxII1gIJ9WepI4aZ/A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + + '@next/swc-linux-x64-gnu@14.2.4': + resolution: {integrity: sha512-ze0ShQDBPCqxLImzw4sCdfnB3lRmN3qGMB2GWDRlq5Wqy4G36pxtNOo2usu/Nm9+V2Rh/QQnrRc2l94kYFXO6Q==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-linux-x64-musl@14.2.4': + resolution: {integrity: sha512-8dwC0UJoc6fC7PX70csdaznVMNr16hQrTDAMPvLPloazlcaWfdPogq+UpZX6Drqb1OBlwowz8iG7WR0Tzk/diQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + + '@next/swc-win32-arm64-msvc@14.2.4': + resolution: {integrity: sha512-jxyg67NbEWkDyvM+O8UDbPAyYRZqGLQDTPwvrBBeOSyVWW/jFQkQKQ70JDqDSYg1ZDdl+E3nkbFbq8xM8E9x8A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-ia32-msvc@14.2.4': + resolution: {integrity: sha512-twrmN753hjXRdcrZmZttb/m5xaCBFa48Dt3FbeEItpJArxriYDunWxJn+QFXdJ3hPkm4u7CKxncVvnmgQMY1ag==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@next/swc-win32-x64-msvc@14.2.4': + resolution: {integrity: sha512-tkLrjBzqFTP8DVrAAQmZelEahfR9OxWpFR++vAI9FBhCiIxtwHwBHC23SBHCTURBtwB4kc/x44imVOnkKGNVGg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/helpers@0.5.5': + resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} + + '@tanstack/react-virtual@3.5.1': + resolution: {integrity: sha512-jIsuhfgy8GqA67PdWqg73ZB2LFE+HD9hjWL1L6ifEIZVyZVAKpYmgUG4WsKQ005aEyImJmbuimPiEvc57IY0Aw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + + '@tanstack/virtual-core@3.5.1': + resolution: {integrity: sha512-046+AUSiDru/V9pajE1du8WayvBKeCvJ2NmKPy/mR8/SbKKrqmSbj7LJBfXE+nSq4f5TBXvnCzu0kcYebI9WdQ==} + + '@theguild/remark-mermaid@0.0.5': + resolution: {integrity: sha512-e+ZIyJkEv9jabI4m7q29wZtZv+2iwPGsXJ2d46Zi7e+QcFudiyuqhLhHG/3gX3ZEB+hxTch+fpItyMS8jwbIcw==} + peerDependencies: + react: ^18.2.0 + + '@theguild/remark-npm2yarn@0.2.1': + resolution: {integrity: sha512-jUTFWwDxtLEFtGZh/TW/w30ySaDJ8atKWH8dq2/IiQF61dPrGfETpl0WxD0VdBfuLOeU14/kop466oBSRO/5CA==} + + '@types/acorn@4.0.6': + resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + + '@types/d3-scale-chromatic@3.0.3': + resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==} + + '@types/d3-scale@4.0.8': + resolution: {integrity: sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==} + + '@types/d3-time@3.0.3': + resolution: {integrity: sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree-jsx@1.0.5': + resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/hast@2.3.10': + resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/js-yaml@4.0.9': + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + + '@types/katex@0.16.7': + resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} + + '@types/mdast@3.0.15': + resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + + '@types/ms@0.7.34': + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + + '@types/prop-types@15.7.12': + resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + + '@types/react@18.3.3': + resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + + '@types/unist@2.0.10': + resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} + + '@types/unist@3.0.2': + resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.12.0: + resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} + engines: {node: '>=0.4.0'} + hasBin: true + + ansi-sequence-parser@1.1.1: + resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + arch@2.2.0: + resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} + + arg@1.0.0: + resolution: {integrity: sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + astring@1.8.6: + resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} + hasBin: true + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + busboy@1.6.0: + resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} + engines: {node: '>=10.16.0'} + + caniuse-lite@1.0.30001636: + resolution: {integrity: sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chalk@2.3.0: + resolution: {integrity: sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==} + engines: {node: '>=4'} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + character-reference-invalid@2.0.1: + resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + clipboardy@1.2.2: + resolution: {integrity: sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==} + engines: {node: '>=4'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + compute-scroll-into-view@3.1.0: + resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} + + cose-base@1.0.3: + resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + + cross-spawn@5.1.0: + resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + cytoscape-cose-bilkent@4.1.0: + resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} + peerDependencies: + cytoscape: ^3.2.0 + + cytoscape@3.29.2: + resolution: {integrity: sha512-2G1ycU28Nh7OHT9rkXRLpCDP30MKH1dXJORZuBhtEhEW7pKwgPi77ImqlCWinouyE1PNepIOGZBOrE84DG7LyQ==} + engines: {node: '>=0.10'} + + d3-array@2.12.1: + resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@1.0.9: + resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-sankey@0.12.3: + resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@1.3.7: + resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + dagre-d3-es@7.0.10: + resolution: {integrity: sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==} + + dayjs@1.11.11: + resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==} + + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + + delaunator@5.0.1: + resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + + dompurify@3.1.5: + resolution: {integrity: sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==} + + elkjs@0.9.3: + resolution: {integrity: sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estree-util-attach-comments@2.1.1: + resolution: {integrity: sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==} + + estree-util-build-jsx@2.2.2: + resolution: {integrity: sha512-m56vOXcOBuaF+Igpb9OPAy7f9w9OIkb5yhjsZuaPm7HoGi4oTOQi0h2+yZ+AtKklYFZ+rPC4n0wYCJCEU1ONqg==} + + estree-util-is-identifier-name@2.1.0: + resolution: {integrity: sha512-bEN9VHRyXAUOjkKVQVvArFym08BTWB0aJPppZZr0UNyAqWsLaVfAqP7hbaTJjzHifmB5ebnR8Wm7r7yGN/HonQ==} + + estree-util-to-js@1.2.0: + resolution: {integrity: sha512-IzU74r1PK5IMMGZXUVZbmiu4A1uhiPgW5hm1GjcOfr4ZzHaMPpLNJjR7HjXiIOzi25nZDrgFTobHTkV5Q6ITjA==} + + estree-util-value-to-estree@1.3.0: + resolution: {integrity: sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw==} + engines: {node: '>=12.0.0'} + + estree-util-visit@1.2.1: + resolution: {integrity: sha512-xbgqcrkIVbIG+lI/gzbvd9SGTJL4zqJKBFttUl5pP27KhAjtMKbX/mQXJ7qgyXpMgVy/zvpm0xoQQaGL8OloOw==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + execa@0.8.0: + resolution: {integrity: sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==} + engines: {node: '>=4'} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + flexsearch@0.7.43: + resolution: {integrity: sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==} + + focus-visible@5.2.0: + resolution: {integrity: sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==} + + get-stream@3.0.0: + resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} + engines: {node: '>=4'} + + git-up@7.0.0: + resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} + + git-url-parse@13.1.1: + resolution: {integrity: sha512-PCFJyeSSdtnbfhSNRw9Wk96dDCNx+sogTe4YNXeXSJxt7xz5hvXekuRn9JX7m+Mf4OscCu8h+mtAl3+h5Fo8lQ==} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + + has-flag@2.0.0: + resolution: {integrity: sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==} + engines: {node: '>=0.10.0'} + + hash-obj@4.0.0: + resolution: {integrity: sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==} + engines: {node: '>=12'} + + hast-util-from-dom@5.0.0: + resolution: {integrity: sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==} + + hast-util-from-html-isomorphic@2.0.0: + resolution: {integrity: sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==} + + hast-util-from-html@2.0.1: + resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} + + hast-util-from-parse5@8.0.1: + resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + + hast-util-raw@9.0.4: + resolution: {integrity: sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==} + + hast-util-to-estree@2.3.3: + resolution: {integrity: sha512-ihhPIUPxN0v0w6M5+IiAZZrn0LH2uZomeWwhn7uP7avZC6TE7lIiEh2yBMPr5+zi1aUCXq6VoYRgs2Bw9xmycQ==} + + hast-util-to-parse5@8.0.0: + resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + + hast-util-to-text@4.0.2: + resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + + hast-util-whitespace@2.0.1: + resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==} + + hastscript@8.0.0: + resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + inline-style-parser@0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + + internmap@1.0.1: + resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + intersection-observer@0.12.2: + resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} + + is-alphabetical@2.0.1: + resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} + + is-alphanumerical@2.0.1: + resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + + is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + + is-decimal@2.0.1: + resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-hexadecimal@2.0.1: + resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + + is-obj@3.0.0: + resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==} + engines: {node: '>=12'} + + is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-reference@3.0.2: + resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} + + is-ssh@1.4.0: + resolution: {integrity: sha512-x7+VxdxOdlV3CYpjvRLBv5Lo9OJerlYanjwFrPR9fuGPjCiNiCzFgAWpiLAohSbsnH4ZAys3SBh+hq5rJosxUQ==} + + is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsonc-parser@3.2.1: + resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} + + katex@0.16.10: + resolution: {integrity: sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==} + hasBin: true + + khroma@2.1.0: + resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + layout-base@1.0.2: + resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + lru-cache@4.1.5: + resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + + markdown-extensions@1.1.1: + resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} + engines: {node: '>=0.10.0'} + + markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + + match-sorter@6.3.4: + resolution: {integrity: sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==} + + mdast-util-definitions@5.1.2: + resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==} + + mdast-util-find-and-replace@2.2.2: + resolution: {integrity: sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==} + + mdast-util-from-markdown@1.3.1: + resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==} + + mdast-util-gfm-autolink-literal@1.0.3: + resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==} + + mdast-util-gfm-footnote@1.0.2: + resolution: {integrity: sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==} + + mdast-util-gfm-strikethrough@1.0.3: + resolution: {integrity: sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==} + + mdast-util-gfm-table@1.0.7: + resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==} + + mdast-util-gfm-task-list-item@1.0.2: + resolution: {integrity: sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==} + + mdast-util-gfm@2.0.2: + resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==} + + mdast-util-math@2.0.2: + resolution: {integrity: sha512-8gmkKVp9v6+Tgjtq6SYx9kGPpTf6FVYRa53/DLh479aldR9AyP48qeVOgNZ5X7QUK7nOy4yw7vg6mbiGcs9jWQ==} + + mdast-util-mdx-expression@1.3.2: + resolution: {integrity: sha512-xIPmR5ReJDu/DHH1OoIT1HkuybIfRGYRywC+gJtI7qHjCJp/M9jrmBEJW22O8lskDWm562BX2W8TiAwRTb0rKA==} + + mdast-util-mdx-jsx@2.1.4: + resolution: {integrity: sha512-DtMn9CmVhVzZx3f+optVDF8yFgQVt7FghCRNdlIaS3X5Bnym3hZwPbg/XW86vdpKjlc1PVj26SpnLGeJBXD3JA==} + + mdast-util-mdx@2.0.1: + resolution: {integrity: sha512-38w5y+r8nyKlGvNjSEqWrhG0w5PmnRA+wnBvm+ulYCct7nsGYhFVb0lljS9bQav4psDAS1eGkP2LMVcZBi/aqw==} + + mdast-util-mdxjs-esm@1.3.1: + resolution: {integrity: sha512-SXqglS0HrEvSdUEfoXFtcg7DRl7S2cwOXc7jkuusG472Mmjag34DUDeOJUZtl+BVnyeO1frIgVpHlNRWc2gk/w==} + + mdast-util-phrasing@3.0.1: + resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==} + + mdast-util-to-hast@12.3.0: + resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==} + + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + + mdast-util-to-markdown@1.5.0: + resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==} + + mdast-util-to-string@3.2.0: + resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} + + mermaid@10.9.1: + resolution: {integrity: sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA==} + + micromark-core-commonmark@1.1.0: + resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==} + + micromark-extension-gfm-autolink-literal@1.0.5: + resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==} + + micromark-extension-gfm-footnote@1.1.2: + resolution: {integrity: sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==} + + micromark-extension-gfm-strikethrough@1.0.7: + resolution: {integrity: sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==} + + micromark-extension-gfm-table@1.0.7: + resolution: {integrity: sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==} + + micromark-extension-gfm-tagfilter@1.0.2: + resolution: {integrity: sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==} + + micromark-extension-gfm-task-list-item@1.0.5: + resolution: {integrity: sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==} + + micromark-extension-gfm@2.0.3: + resolution: {integrity: sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==} + + micromark-extension-math@2.1.2: + resolution: {integrity: sha512-es0CcOV89VNS9wFmyn+wyFTKweXGW4CEvdaAca6SWRWPyYCbBisnjaHLjWO4Nszuiud84jCpkHsqAJoa768Pvg==} + + micromark-extension-mdx-expression@1.0.8: + resolution: {integrity: sha512-zZpeQtc5wfWKdzDsHRBY003H2Smg+PUi2REhqgIhdzAa5xonhP03FcXxqFSerFiNUr5AWmHpaNPQTBVOS4lrXw==} + + micromark-extension-mdx-jsx@1.0.5: + resolution: {integrity: sha512-gPH+9ZdmDflbu19Xkb8+gheqEDqkSpdCEubQyxuz/Hn8DOXiXvrXeikOoBA71+e8Pfi0/UYmU3wW3H58kr7akA==} + + micromark-extension-mdx-md@1.0.1: + resolution: {integrity: sha512-7MSuj2S7xjOQXAjjkbjBsHkMtb+mDGVW6uI2dBL9snOBCbZmoNgDAeZ0nSn9j3T42UE/g2xVNMn18PJxZvkBEA==} + + micromark-extension-mdxjs-esm@1.0.5: + resolution: {integrity: sha512-xNRBw4aoURcyz/S69B19WnZAkWJMxHMT5hE36GtDAyhoyn/8TuAeqjFJQlwk+MKQsUD7b3l7kFX+vlfVWgcX1w==} + + micromark-extension-mdxjs@1.0.1: + resolution: {integrity: sha512-7YA7hF6i5eKOfFUzZ+0z6avRG52GpWR8DL+kN47y3f2KhxbBZMhmxe7auOeaTBrW2DenbbZTf1ea9tA2hDpC2Q==} + + micromark-factory-destination@1.1.0: + resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==} + + micromark-factory-label@1.1.0: + resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==} + + micromark-factory-mdx-expression@1.0.9: + resolution: {integrity: sha512-jGIWzSmNfdnkJq05c7b0+Wv0Kfz3NJ3N4cBjnbO4zjXIlxJr+f8lk+5ZmwFvqdAbUy2q6B5rCY//g0QAAaXDWA==} + + micromark-factory-space@1.1.0: + resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==} + + micromark-factory-title@1.1.0: + resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==} + + micromark-factory-whitespace@1.1.0: + resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==} + + micromark-util-character@1.2.0: + resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==} + + micromark-util-character@2.1.0: + resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + + micromark-util-chunked@1.1.0: + resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==} + + micromark-util-classify-character@1.1.0: + resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==} + + micromark-util-combine-extensions@1.1.0: + resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==} + + micromark-util-decode-numeric-character-reference@1.1.0: + resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==} + + micromark-util-decode-string@1.1.0: + resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==} + + micromark-util-encode@1.1.0: + resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==} + + micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + + micromark-util-events-to-acorn@1.2.3: + resolution: {integrity: sha512-ij4X7Wuc4fED6UoLWkmo0xJQhsktfNh1J0m8g4PbIMPlx+ek/4YdW5mvbye8z/aZvAPUoxgXHrwVlXAPKMRp1w==} + + micromark-util-html-tag-name@1.2.0: + resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==} + + micromark-util-normalize-identifier@1.1.0: + resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==} + + micromark-util-resolve-all@1.1.0: + resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==} + + micromark-util-sanitize-uri@1.2.0: + resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==} + + micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + + micromark-util-subtokenize@1.1.0: + resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==} + + micromark-util-symbol@1.1.0: + resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==} + + micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + + micromark-util-types@1.1.0: + resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==} + + micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + + micromark@3.2.0: + resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + next-mdx-remote@4.4.1: + resolution: {integrity: sha512-1BvyXaIou6xy3XoNF4yaMZUCb6vD2GTAa5ciOa6WoO+gAUTYsb1K4rI/HSC2ogAWLrb/7VSV52skz07vOzmqIQ==} + engines: {node: '>=14', npm: '>=7'} + peerDependencies: + react: '>=16.x <=18.x' + react-dom: '>=16.x <=18.x' + + next-seo@6.5.0: + resolution: {integrity: sha512-MfzUeWTN/x/rsKp/1n0213eojO97lIl0unxqbeCY+6pAucViHDA8GSLRRcXpgjsSmBxfCFdfpu7LXbt4ANQoNQ==} + peerDependencies: + next: ^8.1.1-canary.54 || >=9.0.0 + react: '>=16.0.0' + react-dom: '>=16.0.0' + + next-themes@0.2.1: + resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==} + peerDependencies: + next: '*' + react: '*' + react-dom: '*' + + next@14.2.4: + resolution: {integrity: sha512-R8/V7vugY+822rsQGQCjoLhMuC9oFj9SOi4Cl4b2wjDrseD0LRZ10W7R6Czo4w9ZznVSshKjuIomsRjvm9EKJQ==} + engines: {node: '>=18.17.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.41.2 + react: ^18.2.0 + react-dom: ^18.2.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + sass: + optional: true + + nextra-theme-docs@2.13.4: + resolution: {integrity: sha512-2XOoMfwBCTYBt8ds4ZHftt9Wyf2XsykiNo02eir/XEYB+sGeUoE77kzqfidjEOKCSzOHYbK9BDMcg2+B/2vYRw==} + peerDependencies: + next: '>=9.5.3' + nextra: 2.13.4 + react: '>=16.13.1' + react-dom: '>=16.13.1' + + nextra@2.13.4: + resolution: {integrity: sha512-7of2rSBxuUa3+lbMmZwG9cqgftcoNOVQLTT6Rxf3EhBR9t1EI7b43dted8YoqSNaigdE3j1CoyNkX8N/ZzlEpw==} + engines: {node: '>=16'} + peerDependencies: + next: '>=9.5.3' + react: '>=16.13.1' + react-dom: '>=16.13.1' + + non-layered-tidy-tree-layout@2.0.2: + resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} + + npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + + npm-to-yarn@2.2.1: + resolution: {integrity: sha512-O/j/ROyX0KGLG7O6Ieut/seQ0oiTpHF2tXAcFbpdTLQFiaNtkyTXXocM1fwpaa60dg1qpWj0nHlbNhx6qwuENQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + parse-entities@4.0.1: + resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + + parse-numeric-range@1.3.0: + resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} + + parse-path@7.0.0: + resolution: {integrity: sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==} + + parse-url@8.1.0: + resolution: {integrity: sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==} + + parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + + path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + + periscopic@3.1.0: + resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + + postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} + engines: {node: ^10 || ^12 || >=14} + + property-information@6.5.0: + resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + + protocols@2.0.1: + resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==} + + pseudomap@1.0.2: + resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + + reading-time@1.5.0: + resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + rehype-katex@7.0.0: + resolution: {integrity: sha512-h8FPkGE00r2XKU+/acgqwWUlyzve1IiOKwsEkg4pDL3k48PiE0Pt+/uLtVHDVkN1yA4iurZN6UES8ivHVEQV6Q==} + + rehype-pretty-code@0.9.11: + resolution: {integrity: sha512-Eq90eCYXQJISktfRZ8PPtwc5SUyH6fJcxS8XOMnHPUQZBtC6RYo67gGlley9X2nR8vlniPj0/7oCDEYHKQa/oA==} + engines: {node: '>=16'} + peerDependencies: + shiki: '*' + + rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + + remark-gfm@3.0.1: + resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} + + remark-math@5.1.1: + resolution: {integrity: sha512-cE5T2R/xLVtfFI4cCePtiRn+e6jKMtFDR3P8V3qpv8wpKjwvHoBA4eJzvX+nVrnlNy0911bdGmuspCSwetfYHw==} + + remark-mdx@2.3.0: + resolution: {integrity: sha512-g53hMkpM0I98MU266IzDFMrTD980gNF3BJnkyFcmN+dD873mQeD5rdMO3Y2X+x8umQfbSE0PcoEDl7ledSA+2g==} + + remark-parse@10.0.2: + resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==} + + remark-reading-time@2.0.1: + resolution: {integrity: sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw==} + + remark-rehype@10.1.0: + resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==} + + remove-accents@0.5.0: + resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} + + robust-predicates@3.0.2: + resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + + scroll-into-view-if-needed@3.1.0: + resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} + + section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + + shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + + shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + + shiki@0.14.7: + resolution: {integrity: sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + sort-keys@5.0.0: + resolution: {integrity: sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw==} + engines: {node: '>=12'} + + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + streamsearch@1.1.0: + resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} + engines: {node: '>=10.0.0'} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + + strip-eof@1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + + style-to-object@0.4.4: + resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} + + styled-jsx@5.1.1: + resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + stylis@4.3.2: + resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==} + + supports-color@4.5.0: + resolution: {integrity: sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==} + engines: {node: '>=4'} + + title@3.5.3: + resolution: {integrity: sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==} + hasBin: true + + titleize@1.0.0: + resolution: {integrity: sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw==} + engines: {node: '>=0.10.0'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + + type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + + unified@10.1.2: + resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} + + unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + + unist-util-generated@2.0.1: + resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==} + + unist-util-is@5.2.1: + resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-position-from-estree@1.1.2: + resolution: {integrity: sha512-poZa0eXpS+/XpoQwGwl79UUdea4ol2ZuCYguVaJS4qzIOMDzbqz8a3erUCOmubSZkaOuGamb3tX790iwOIROww==} + + unist-util-position@4.0.4: + resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove-position@4.0.2: + resolution: {integrity: sha512-TkBb0HABNmxzAcfLf4qsIbFbaPDvMO6wa3b3j4VcEzFVaw1LBKwnW4/sRJ/atSLSzoIg41JWEdnE7N6DIhGDGQ==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-remove@4.0.0: + resolution: {integrity: sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==} + + unist-util-stringify-position@3.0.3: + resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-parents@4.1.1: + resolution: {integrity: sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==} + + unist-util-visit-parents@5.1.3: + resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@3.1.0: + resolution: {integrity: sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==} + + unist-util-visit@4.1.2: + resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + + uvu@0.5.6: + resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==} + engines: {node: '>=8'} + hasBin: true + + vfile-location@5.0.2: + resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} + + vfile-matter@3.0.1: + resolution: {integrity: sha512-CAAIDwnh6ZdtrqAuxdElUqQRQDQgbbIrYtDYI8gCjXS1qQ+1XdLoK8FIZWxJwn0/I+BkSSZpar3SOgjemQz4fg==} + + vfile-message@3.1.4: + resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@5.3.7: + resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} + + vfile@6.0.1: + resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} + + vscode-oniguruma@1.7.0: + resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==} + + vscode-textmate@8.0.0: + resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + web-worker@1.3.0: + resolution: {integrity: sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@babel/runtime@7.24.7': + dependencies: + regenerator-runtime: 0.14.1 + + '@braintree/sanitize-url@6.0.4': {} + + '@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@tanstack/react-virtual': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + client-only: 0.0.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@mdx-js/mdx@2.3.0': + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/mdx': 2.0.13 + estree-util-build-jsx: 2.2.2 + estree-util-is-identifier-name: 2.1.0 + estree-util-to-js: 1.2.0 + estree-walker: 3.0.3 + hast-util-to-estree: 2.3.3 + markdown-extensions: 1.1.1 + periscopic: 3.1.0 + remark-mdx: 2.3.0 + remark-parse: 10.0.2 + remark-rehype: 10.1.0 + unified: 10.1.2 + unist-util-position-from-estree: 1.1.2 + unist-util-stringify-position: 3.0.3 + unist-util-visit: 4.1.2 + vfile: 5.3.7 + transitivePeerDependencies: + - supports-color + + '@mdx-js/react@2.3.0(react@18.3.1)': + dependencies: + '@types/mdx': 2.0.13 + '@types/react': 18.3.3 + react: 18.3.1 + + '@napi-rs/simple-git-android-arm-eabi@0.1.16': + optional: true + + '@napi-rs/simple-git-android-arm64@0.1.16': + optional: true + + '@napi-rs/simple-git-darwin-arm64@0.1.16': + optional: true + + '@napi-rs/simple-git-darwin-x64@0.1.16': + optional: true + + '@napi-rs/simple-git-linux-arm-gnueabihf@0.1.16': + optional: true + + '@napi-rs/simple-git-linux-arm64-gnu@0.1.16': + optional: true + + '@napi-rs/simple-git-linux-arm64-musl@0.1.16': + optional: true + + '@napi-rs/simple-git-linux-x64-gnu@0.1.16': + optional: true + + '@napi-rs/simple-git-linux-x64-musl@0.1.16': + optional: true + + '@napi-rs/simple-git-win32-arm64-msvc@0.1.16': + optional: true + + '@napi-rs/simple-git-win32-x64-msvc@0.1.16': + optional: true + + '@napi-rs/simple-git@0.1.16': + optionalDependencies: + '@napi-rs/simple-git-android-arm-eabi': 0.1.16 + '@napi-rs/simple-git-android-arm64': 0.1.16 + '@napi-rs/simple-git-darwin-arm64': 0.1.16 + '@napi-rs/simple-git-darwin-x64': 0.1.16 + '@napi-rs/simple-git-linux-arm-gnueabihf': 0.1.16 + '@napi-rs/simple-git-linux-arm64-gnu': 0.1.16 + '@napi-rs/simple-git-linux-arm64-musl': 0.1.16 + '@napi-rs/simple-git-linux-x64-gnu': 0.1.16 + '@napi-rs/simple-git-linux-x64-musl': 0.1.16 + '@napi-rs/simple-git-win32-arm64-msvc': 0.1.16 + '@napi-rs/simple-git-win32-x64-msvc': 0.1.16 + + '@next/env@14.2.4': {} + + '@next/swc-darwin-arm64@14.2.4': + optional: true + + '@next/swc-darwin-x64@14.2.4': + optional: true + + '@next/swc-linux-arm64-gnu@14.2.4': + optional: true + + '@next/swc-linux-arm64-musl@14.2.4': + optional: true + + '@next/swc-linux-x64-gnu@14.2.4': + optional: true + + '@next/swc-linux-x64-musl@14.2.4': + optional: true + + '@next/swc-win32-arm64-msvc@14.2.4': + optional: true + + '@next/swc-win32-ia32-msvc@14.2.4': + optional: true + + '@next/swc-win32-x64-msvc@14.2.4': + optional: true + + '@popperjs/core@2.11.8': {} + + '@swc/counter@0.1.3': {} + + '@swc/helpers@0.5.5': + dependencies: + '@swc/counter': 0.1.3 + tslib: 2.6.3 + + '@tanstack/react-virtual@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@tanstack/virtual-core': 3.5.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@tanstack/virtual-core@3.5.1': {} + + '@theguild/remark-mermaid@0.0.5(react@18.3.1)': + dependencies: + mermaid: 10.9.1 + react: 18.3.1 + unist-util-visit: 5.0.0 + transitivePeerDependencies: + - supports-color + + '@theguild/remark-npm2yarn@0.2.1': + dependencies: + npm-to-yarn: 2.2.1 + unist-util-visit: 5.0.0 + + '@types/acorn@4.0.6': + dependencies: + '@types/estree': 1.0.5 + + '@types/d3-scale-chromatic@3.0.3': {} + + '@types/d3-scale@4.0.8': + dependencies: + '@types/d3-time': 3.0.3 + + '@types/d3-time@3.0.3': {} + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 0.7.34 + + '@types/estree-jsx@1.0.5': + dependencies: + '@types/estree': 1.0.5 + + '@types/estree@1.0.5': {} + + '@types/hast@2.3.10': + dependencies: + '@types/unist': 2.0.10 + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.2 + + '@types/js-yaml@4.0.9': {} + + '@types/katex@0.16.7': {} + + '@types/mdast@3.0.15': + dependencies: + '@types/unist': 2.0.10 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.2 + + '@types/mdx@2.0.13': {} + + '@types/ms@0.7.34': {} + + '@types/prop-types@15.7.12': {} + + '@types/react@18.3.3': + dependencies: + '@types/prop-types': 15.7.12 + csstype: 3.1.3 + + '@types/unist@2.0.10': {} + + '@types/unist@3.0.2': {} + + '@ungap/structured-clone@1.2.0': {} + + acorn-jsx@5.3.2(acorn@8.12.0): + dependencies: + acorn: 8.12.0 + + acorn@8.12.0: {} + + ansi-sequence-parser@1.1.1: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + arch@2.2.0: {} + + arg@1.0.0: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + astring@1.8.6: {} + + bail@2.0.2: {} + + busboy@1.6.0: + dependencies: + streamsearch: 1.1.0 + + caniuse-lite@1.0.30001636: {} + + ccount@2.0.1: {} + + chalk@2.3.0: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 4.5.0 + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + character-entities@2.0.2: {} + + character-reference-invalid@2.0.1: {} + + client-only@0.0.1: {} + + clipboardy@1.2.2: + dependencies: + arch: 2.2.0 + execa: 0.8.0 + + clsx@2.1.1: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-name@1.1.3: {} + + comma-separated-tokens@2.0.3: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + compute-scroll-into-view@3.1.0: {} + + cose-base@1.0.3: + dependencies: + layout-base: 1.0.2 + + cross-spawn@5.1.0: + dependencies: + lru-cache: 4.1.5 + shebang-command: 1.2.0 + which: 1.3.1 + + csstype@3.1.3: {} + + cytoscape-cose-bilkent@4.1.0(cytoscape@3.29.2): + dependencies: + cose-base: 1.0.3 + cytoscape: 3.29.2 + + cytoscape@3.29.2: {} + + d3-array@2.12.1: + dependencies: + internmap: 1.0.1 + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.0.1 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.0: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@1.0.9: {} + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-sankey@0.12.3: + dependencies: + d3-array: 2.12.1 + d3-shape: 1.3.7 + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@1.3.7: + dependencies: + d3-path: 1.0.9 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.0 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + dagre-d3-es@7.0.10: + dependencies: + d3: 7.9.0 + lodash-es: 4.17.21 + + dayjs@1.11.11: {} + + debug@4.3.5: + dependencies: + ms: 2.1.2 + + decode-named-character-reference@1.0.2: + dependencies: + character-entities: 2.0.2 + + delaunator@5.0.1: + dependencies: + robust-predicates: 3.0.2 + + dequal@2.0.3: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + diff@5.2.0: {} + + dompurify@3.1.5: {} + + elkjs@0.9.3: {} + + entities@4.5.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@5.0.0: {} + + esprima@4.0.1: {} + + estree-util-attach-comments@2.1.1: + dependencies: + '@types/estree': 1.0.5 + + estree-util-build-jsx@2.2.2: + dependencies: + '@types/estree-jsx': 1.0.5 + estree-util-is-identifier-name: 2.1.0 + estree-walker: 3.0.3 + + estree-util-is-identifier-name@2.1.0: {} + + estree-util-to-js@1.2.0: + dependencies: + '@types/estree-jsx': 1.0.5 + astring: 1.8.6 + source-map: 0.7.4 + + estree-util-value-to-estree@1.3.0: + dependencies: + is-plain-obj: 3.0.0 + + estree-util-visit@1.2.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/unist': 2.0.10 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.5 + + execa@0.8.0: + dependencies: + cross-spawn: 5.1.0 + get-stream: 3.0.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + + extend@3.0.2: {} + + flexsearch@0.7.43: {} + + focus-visible@5.2.0: {} + + get-stream@3.0.0: {} + + git-up@7.0.0: + dependencies: + is-ssh: 1.4.0 + parse-url: 8.1.0 + + git-url-parse@13.1.1: + dependencies: + git-up: 7.0.0 + + github-slugger@2.0.0: {} + + graceful-fs@4.2.11: {} + + gray-matter@4.0.3: + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + + has-flag@2.0.0: {} + + hash-obj@4.0.0: + dependencies: + is-obj: 3.0.0 + sort-keys: 5.0.0 + type-fest: 1.4.0 + + hast-util-from-dom@5.0.0: + dependencies: + '@types/hast': 3.0.4 + hastscript: 8.0.0 + web-namespaces: 2.0.1 + + hast-util-from-html-isomorphic@2.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-from-dom: 5.0.0 + hast-util-from-html: 2.0.1 + unist-util-remove-position: 5.0.0 + + hast-util-from-html@2.0.1: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.1 + parse5: 7.1.2 + vfile: 6.0.1 + vfile-message: 4.0.2 + + hast-util-from-parse5@8.0.1: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + devlop: 1.1.0 + hastscript: 8.0.0 + property-information: 6.5.0 + vfile: 6.0.1 + vfile-location: 5.0.2 + web-namespaces: 2.0.1 + + hast-util-is-element@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-parse-selector@4.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-raw@9.0.4: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + '@ungap/structured-clone': 1.2.0 + hast-util-from-parse5: 8.0.1 + hast-util-to-parse5: 8.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + parse5: 7.1.2 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-estree@2.3.3: + dependencies: + '@types/estree': 1.0.5 + '@types/estree-jsx': 1.0.5 + '@types/hast': 2.3.10 + '@types/unist': 2.0.10 + comma-separated-tokens: 2.0.3 + estree-util-attach-comments: 2.1.1 + estree-util-is-identifier-name: 2.1.0 + hast-util-whitespace: 2.0.1 + mdast-util-mdx-expression: 1.3.2 + mdast-util-mdxjs-esm: 1.3.1 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + style-to-object: 0.4.4 + unist-util-position: 4.0.4 + zwitch: 2.0.4 + transitivePeerDependencies: + - supports-color + + hast-util-to-parse5@8.0.0: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-text@4.0.2: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 + + hast-util-whitespace@2.0.1: {} + + hastscript@8.0.0: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + + html-void-elements@3.0.0: {} + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + inline-style-parser@0.1.1: {} + + internmap@1.0.1: {} + + internmap@2.0.3: {} + + intersection-observer@0.12.2: {} + + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + + is-buffer@2.0.5: {} + + is-decimal@2.0.1: {} + + is-extendable@0.1.1: {} + + is-hexadecimal@2.0.1: {} + + is-obj@3.0.0: {} + + is-plain-obj@3.0.0: {} + + is-plain-obj@4.1.0: {} + + is-reference@3.0.2: + dependencies: + '@types/estree': 1.0.5 + + is-ssh@1.4.0: + dependencies: + protocols: 2.0.1 + + is-stream@1.1.0: {} + + isexe@2.0.0: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsonc-parser@3.2.1: {} + + katex@0.16.10: + dependencies: + commander: 8.3.0 + + khroma@2.1.0: {} + + kind-of@6.0.3: {} + + kleur@4.1.5: {} + + layout-base@1.0.2: {} + + lodash-es@4.17.21: {} + + lodash.get@4.4.2: {} + + longest-streak@3.1.0: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + lru-cache@4.1.5: + dependencies: + pseudomap: 1.0.2 + yallist: 2.1.2 + + markdown-extensions@1.1.1: {} + + markdown-table@3.0.3: {} + + match-sorter@6.3.4: + dependencies: + '@babel/runtime': 7.24.7 + remove-accents: 0.5.0 + + mdast-util-definitions@5.1.2: + dependencies: + '@types/mdast': 3.0.15 + '@types/unist': 2.0.10 + unist-util-visit: 4.1.2 + + mdast-util-find-and-replace@2.2.2: + dependencies: + '@types/mdast': 3.0.15 + escape-string-regexp: 5.0.0 + unist-util-is: 5.2.1 + unist-util-visit-parents: 5.1.3 + + mdast-util-from-markdown@1.3.1: + dependencies: + '@types/mdast': 3.0.15 + '@types/unist': 2.0.10 + decode-named-character-reference: 1.0.2 + mdast-util-to-string: 3.2.0 + micromark: 3.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-decode-string: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + unist-util-stringify-position: 3.0.3 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@1.0.3: + dependencies: + '@types/mdast': 3.0.15 + ccount: 2.0.1 + mdast-util-find-and-replace: 2.2.2 + micromark-util-character: 1.2.0 + + mdast-util-gfm-footnote@1.0.2: + dependencies: + '@types/mdast': 3.0.15 + mdast-util-to-markdown: 1.5.0 + micromark-util-normalize-identifier: 1.1.0 + + mdast-util-gfm-strikethrough@1.0.3: + dependencies: + '@types/mdast': 3.0.15 + mdast-util-to-markdown: 1.5.0 + + mdast-util-gfm-table@1.0.7: + dependencies: + '@types/mdast': 3.0.15 + markdown-table: 3.0.3 + mdast-util-from-markdown: 1.3.1 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@1.0.2: + dependencies: + '@types/mdast': 3.0.15 + mdast-util-to-markdown: 1.5.0 + + mdast-util-gfm@2.0.2: + dependencies: + mdast-util-from-markdown: 1.3.1 + mdast-util-gfm-autolink-literal: 1.0.3 + mdast-util-gfm-footnote: 1.0.2 + mdast-util-gfm-strikethrough: 1.0.3 + mdast-util-gfm-table: 1.0.7 + mdast-util-gfm-task-list-item: 1.0.2 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + + mdast-util-math@2.0.2: + dependencies: + '@types/mdast': 3.0.15 + longest-streak: 3.1.0 + mdast-util-to-markdown: 1.5.0 + + mdast-util-mdx-expression@1.3.2: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 2.3.10 + '@types/mdast': 3.0.15 + mdast-util-from-markdown: 1.3.1 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx-jsx@2.1.4: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 2.3.10 + '@types/mdast': 3.0.15 + '@types/unist': 2.0.10 + ccount: 2.0.1 + mdast-util-from-markdown: 1.3.1 + mdast-util-to-markdown: 1.5.0 + parse-entities: 4.0.1 + stringify-entities: 4.0.4 + unist-util-remove-position: 4.0.2 + unist-util-stringify-position: 3.0.3 + vfile-message: 3.1.4 + transitivePeerDependencies: + - supports-color + + mdast-util-mdx@2.0.1: + dependencies: + mdast-util-from-markdown: 1.3.1 + mdast-util-mdx-expression: 1.3.2 + mdast-util-mdx-jsx: 2.1.4 + mdast-util-mdxjs-esm: 1.3.1 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + + mdast-util-mdxjs-esm@1.3.1: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 2.3.10 + '@types/mdast': 3.0.15 + mdast-util-from-markdown: 1.3.1 + mdast-util-to-markdown: 1.5.0 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@3.0.1: + dependencies: + '@types/mdast': 3.0.15 + unist-util-is: 5.2.1 + + mdast-util-to-hast@12.3.0: + dependencies: + '@types/hast': 2.3.10 + '@types/mdast': 3.0.15 + mdast-util-definitions: 5.1.2 + micromark-util-sanitize-uri: 1.2.0 + trim-lines: 3.0.1 + unist-util-generated: 2.0.1 + unist-util-position: 4.0.4 + unist-util-visit: 4.1.2 + + mdast-util-to-hast@13.2.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + + mdast-util-to-markdown@1.5.0: + dependencies: + '@types/mdast': 3.0.15 + '@types/unist': 2.0.10 + longest-streak: 3.1.0 + mdast-util-phrasing: 3.0.1 + mdast-util-to-string: 3.2.0 + micromark-util-decode-string: 1.1.0 + unist-util-visit: 4.1.2 + zwitch: 2.0.4 + + mdast-util-to-string@3.2.0: + dependencies: + '@types/mdast': 3.0.15 + + mermaid@10.9.1: + dependencies: + '@braintree/sanitize-url': 6.0.4 + '@types/d3-scale': 4.0.8 + '@types/d3-scale-chromatic': 3.0.3 + cytoscape: 3.29.2 + cytoscape-cose-bilkent: 4.1.0(cytoscape@3.29.2) + d3: 7.9.0 + d3-sankey: 0.12.3 + dagre-d3-es: 7.0.10 + dayjs: 1.11.11 + dompurify: 3.1.5 + elkjs: 0.9.3 + katex: 0.16.10 + khroma: 2.1.0 + lodash-es: 4.17.21 + mdast-util-from-markdown: 1.3.1 + non-layered-tidy-tree-layout: 2.0.2 + stylis: 4.3.2 + ts-dedent: 2.2.0 + uuid: 9.0.1 + web-worker: 1.3.0 + transitivePeerDependencies: + - supports-color + + micromark-core-commonmark@1.1.0: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-factory-destination: 1.1.0 + micromark-factory-label: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-factory-title: 1.1.0 + micromark-factory-whitespace: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-classify-character: 1.1.0 + micromark-util-html-tag-name: 1.2.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-extension-gfm-autolink-literal@1.0.5: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-extension-gfm-footnote@1.1.2: + dependencies: + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-extension-gfm-strikethrough@1.0.7: + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-classify-character: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-extension-gfm-table@1.0.7: + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-extension-gfm-tagfilter@1.0.2: + dependencies: + micromark-util-types: 1.1.0 + + micromark-extension-gfm-task-list-item@1.0.5: + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-extension-gfm@2.0.3: + dependencies: + micromark-extension-gfm-autolink-literal: 1.0.5 + micromark-extension-gfm-footnote: 1.1.2 + micromark-extension-gfm-strikethrough: 1.0.7 + micromark-extension-gfm-table: 1.0.7 + micromark-extension-gfm-tagfilter: 1.0.2 + micromark-extension-gfm-task-list-item: 1.0.5 + micromark-util-combine-extensions: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-extension-math@2.1.2: + dependencies: + '@types/katex': 0.16.7 + katex: 0.16.10 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-extension-mdx-expression@1.0.8: + dependencies: + '@types/estree': 1.0.5 + micromark-factory-mdx-expression: 1.0.9 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-events-to-acorn: 1.2.3 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-extension-mdx-jsx@1.0.5: + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.5 + estree-util-is-identifier-name: 2.1.0 + micromark-factory-mdx-expression: 1.0.9 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + vfile-message: 3.1.4 + + micromark-extension-mdx-md@1.0.1: + dependencies: + micromark-util-types: 1.1.0 + + micromark-extension-mdxjs-esm@1.0.5: + dependencies: + '@types/estree': 1.0.5 + micromark-core-commonmark: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-events-to-acorn: 1.2.3 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + unist-util-position-from-estree: 1.1.2 + uvu: 0.5.6 + vfile-message: 3.1.4 + + micromark-extension-mdxjs@1.0.1: + dependencies: + acorn: 8.12.0 + acorn-jsx: 5.3.2(acorn@8.12.0) + micromark-extension-mdx-expression: 1.0.8 + micromark-extension-mdx-jsx: 1.0.5 + micromark-extension-mdx-md: 1.0.1 + micromark-extension-mdxjs-esm: 1.0.5 + micromark-util-combine-extensions: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-factory-destination@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-factory-label@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-factory-mdx-expression@1.0.9: + dependencies: + '@types/estree': 1.0.5 + micromark-util-character: 1.2.0 + micromark-util-events-to-acorn: 1.2.3 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + unist-util-position-from-estree: 1.1.2 + uvu: 0.5.6 + vfile-message: 3.1.4 + + micromark-factory-space@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-types: 1.1.0 + + micromark-factory-title@1.1.0: + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-factory-whitespace@1.1.0: + dependencies: + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-character@1.2.0: + dependencies: + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-character@2.1.0: + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + + micromark-util-chunked@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-classify-character@1.1.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-combine-extensions@1.1.0: + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-types: 1.1.0 + + micromark-util-decode-numeric-character-reference@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-decode-string@1.1.0: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 1.2.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-symbol: 1.1.0 + + micromark-util-encode@1.1.0: {} + + micromark-util-encode@2.0.0: {} + + micromark-util-events-to-acorn@1.2.3: + dependencies: + '@types/acorn': 4.0.6 + '@types/estree': 1.0.5 + '@types/unist': 2.0.10 + estree-util-visit: 1.2.1 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + vfile-message: 3.1.4 + + micromark-util-html-tag-name@1.2.0: {} + + micromark-util-normalize-identifier@1.1.0: + dependencies: + micromark-util-symbol: 1.1.0 + + micromark-util-resolve-all@1.1.0: + dependencies: + micromark-util-types: 1.1.0 + + micromark-util-sanitize-uri@1.2.0: + dependencies: + micromark-util-character: 1.2.0 + micromark-util-encode: 1.1.0 + micromark-util-symbol: 1.1.0 + + micromark-util-sanitize-uri@2.0.0: + dependencies: + micromark-util-character: 2.1.0 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + + micromark-util-subtokenize@1.1.0: + dependencies: + micromark-util-chunked: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + + micromark-util-symbol@1.1.0: {} + + micromark-util-symbol@2.0.0: {} + + micromark-util-types@1.1.0: {} + + micromark-util-types@2.0.0: {} + + micromark@3.2.0: + dependencies: + '@types/debug': 4.1.12 + debug: 4.3.5 + decode-named-character-reference: 1.0.2 + micromark-core-commonmark: 1.1.0 + micromark-factory-space: 1.1.0 + micromark-util-character: 1.2.0 + micromark-util-chunked: 1.1.0 + micromark-util-combine-extensions: 1.1.0 + micromark-util-decode-numeric-character-reference: 1.1.0 + micromark-util-encode: 1.1.0 + micromark-util-normalize-identifier: 1.1.0 + micromark-util-resolve-all: 1.1.0 + micromark-util-sanitize-uri: 1.2.0 + micromark-util-subtokenize: 1.1.0 + micromark-util-symbol: 1.1.0 + micromark-util-types: 1.1.0 + uvu: 0.5.6 + transitivePeerDependencies: + - supports-color + + mri@1.2.0: {} + + ms@2.1.2: {} + + nanoid@3.3.7: {} + + next-mdx-remote@4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@mdx-js/mdx': 2.3.0 + '@mdx-js/react': 2.3.0(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + vfile: 5.3.7 + vfile-matter: 3.0.1 + transitivePeerDependencies: + - supports-color + + next-seo@6.5.0(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + next-themes@0.2.1(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@next/env': 14.2.4 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 + caniuse-lite: 1.0.30001636 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.1(react@18.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 14.2.4 + '@next/swc-darwin-x64': 14.2.4 + '@next/swc-linux-arm64-gnu': 14.2.4 + '@next/swc-linux-arm64-musl': 14.2.4 + '@next/swc-linux-x64-gnu': 14.2.4 + '@next/swc-linux-x64-musl': 14.2.4 + '@next/swc-win32-arm64-msvc': 14.2.4 + '@next/swc-win32-ia32-msvc': 14.2.4 + '@next/swc-win32-x64-msvc': 14.2.4 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + + nextra-theme-docs@2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@popperjs/core': 2.11.8 + clsx: 2.1.1 + escape-string-regexp: 5.0.0 + flexsearch: 0.7.43 + focus-visible: 5.2.0 + git-url-parse: 13.1.1 + intersection-observer: 0.12.2 + match-sorter: 6.3.4 + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-seo: 6.5.0(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-themes: 0.2.1(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + nextra: 2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + scroll-into-view-if-needed: 3.1.0 + zod: 3.23.8 + + nextra@2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@mdx-js/mdx': 2.3.0 + '@mdx-js/react': 2.3.0(react@18.3.1) + '@napi-rs/simple-git': 0.1.16 + '@theguild/remark-mermaid': 0.0.5(react@18.3.1) + '@theguild/remark-npm2yarn': 0.2.1 + clsx: 2.1.1 + github-slugger: 2.0.0 + graceful-fs: 4.2.11 + gray-matter: 4.0.3 + katex: 0.16.10 + lodash.get: 4.4.2 + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-mdx-remote: 4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + p-limit: 3.1.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + rehype-katex: 7.0.0 + rehype-pretty-code: 0.9.11(shiki@0.14.7) + rehype-raw: 7.0.0 + remark-gfm: 3.0.1 + remark-math: 5.1.1 + remark-reading-time: 2.0.1 + shiki: 0.14.7 + slash: 3.0.0 + title: 3.5.3 + unist-util-remove: 4.0.0 + unist-util-visit: 5.0.0 + zod: 3.23.8 + transitivePeerDependencies: + - supports-color + + non-layered-tidy-tree-layout@2.0.2: {} + + npm-run-path@2.0.2: + dependencies: + path-key: 2.0.1 + + npm-to-yarn@2.2.1: {} + + p-finally@1.0.0: {} + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + parse-entities@4.0.1: + dependencies: + '@types/unist': 2.0.10 + character-entities: 2.0.2 + character-entities-legacy: 3.0.0 + character-reference-invalid: 2.0.1 + decode-named-character-reference: 1.0.2 + is-alphanumerical: 2.0.1 + is-decimal: 2.0.1 + is-hexadecimal: 2.0.1 + + parse-numeric-range@1.3.0: {} + + parse-path@7.0.0: + dependencies: + protocols: 2.0.1 + + parse-url@8.1.0: + dependencies: + parse-path: 7.0.0 + + parse5@7.1.2: + dependencies: + entities: 4.5.0 + + path-key@2.0.1: {} + + periscopic@3.1.0: + dependencies: + '@types/estree': 1.0.5 + estree-walker: 3.0.3 + is-reference: 3.0.2 + + picocolors@1.0.1: {} + + postcss@8.4.31: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.1 + source-map-js: 1.2.0 + + property-information@6.5.0: {} + + protocols@2.0.1: {} + + pseudomap@1.0.2: {} + + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + + reading-time@1.5.0: {} + + regenerator-runtime@0.14.1: {} + + rehype-katex@7.0.0: + dependencies: + '@types/hast': 3.0.4 + '@types/katex': 0.16.7 + hast-util-from-html-isomorphic: 2.0.0 + hast-util-to-text: 4.0.2 + katex: 0.16.10 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.1 + + rehype-pretty-code@0.9.11(shiki@0.14.7): + dependencies: + '@types/hast': 2.3.10 + hash-obj: 4.0.0 + parse-numeric-range: 1.3.0 + shiki: 0.14.7 + + rehype-raw@7.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-raw: 9.0.4 + vfile: 6.0.1 + + remark-gfm@3.0.1: + dependencies: + '@types/mdast': 3.0.15 + mdast-util-gfm: 2.0.2 + micromark-extension-gfm: 2.0.3 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + + remark-math@5.1.1: + dependencies: + '@types/mdast': 3.0.15 + mdast-util-math: 2.0.2 + micromark-extension-math: 2.1.2 + unified: 10.1.2 + + remark-mdx@2.3.0: + dependencies: + mdast-util-mdx: 2.0.1 + micromark-extension-mdxjs: 1.0.1 + transitivePeerDependencies: + - supports-color + + remark-parse@10.0.2: + dependencies: + '@types/mdast': 3.0.15 + mdast-util-from-markdown: 1.3.1 + unified: 10.1.2 + transitivePeerDependencies: + - supports-color + + remark-reading-time@2.0.1: + dependencies: + estree-util-is-identifier-name: 2.1.0 + estree-util-value-to-estree: 1.3.0 + reading-time: 1.5.0 + unist-util-visit: 3.1.0 + + remark-rehype@10.1.0: + dependencies: + '@types/hast': 2.3.10 + '@types/mdast': 3.0.15 + mdast-util-to-hast: 12.3.0 + unified: 10.1.2 + + remove-accents@0.5.0: {} + + robust-predicates@3.0.2: {} + + rw@1.3.3: {} + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safer-buffer@2.1.2: {} + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + scroll-into-view-if-needed@3.1.0: + dependencies: + compute-scroll-into-view: 3.1.0 + + section-matter@1.0.0: + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + + shebang-command@1.2.0: + dependencies: + shebang-regex: 1.0.0 + + shebang-regex@1.0.0: {} + + shiki@0.14.7: + dependencies: + ansi-sequence-parser: 1.1.1 + jsonc-parser: 3.2.1 + vscode-oniguruma: 1.7.0 + vscode-textmate: 8.0.0 + + signal-exit@3.0.7: {} + + slash@3.0.0: {} + + sort-keys@5.0.0: + dependencies: + is-plain-obj: 4.1.0 + + source-map-js@1.2.0: {} + + source-map@0.7.4: {} + + space-separated-tokens@2.0.2: {} + + sprintf-js@1.0.3: {} + + streamsearch@1.1.0: {} + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-bom-string@1.0.0: {} + + strip-eof@1.0.0: {} + + style-to-object@0.4.4: + dependencies: + inline-style-parser: 0.1.1 + + styled-jsx@5.1.1(react@18.3.1): + dependencies: + client-only: 0.0.1 + react: 18.3.1 + + stylis@4.3.2: {} + + supports-color@4.5.0: + dependencies: + has-flag: 2.0.0 + + title@3.5.3: + dependencies: + arg: 1.0.0 + chalk: 2.3.0 + clipboardy: 1.2.2 + titleize: 1.0.0 + + titleize@1.0.0: {} + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + ts-dedent@2.2.0: {} + + tslib@2.6.3: {} + + type-fest@1.4.0: {} + + unified@10.1.2: + dependencies: + '@types/unist': 2.0.10 + bail: 2.0.2 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 5.3.7 + + unist-util-find-after@5.0.0: + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + + unist-util-generated@2.0.1: {} + + unist-util-is@5.2.1: + dependencies: + '@types/unist': 2.0.10 + + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.2 + + unist-util-position-from-estree@1.1.2: + dependencies: + '@types/unist': 2.0.10 + + unist-util-position@4.0.4: + dependencies: + '@types/unist': 2.0.10 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.2 + + unist-util-remove-position@4.0.2: + dependencies: + '@types/unist': 2.0.10 + unist-util-visit: 4.1.2 + + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.2 + unist-util-visit: 5.0.0 + + unist-util-remove@4.0.0: + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + unist-util-stringify-position@3.0.3: + dependencies: + '@types/unist': 2.0.10 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.2 + + unist-util-visit-parents@4.1.1: + dependencies: + '@types/unist': 2.0.10 + unist-util-is: 5.2.1 + + unist-util-visit-parents@5.1.3: + dependencies: + '@types/unist': 2.0.10 + unist-util-is: 5.2.1 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + + unist-util-visit@3.1.0: + dependencies: + '@types/unist': 2.0.10 + unist-util-is: 5.2.1 + unist-util-visit-parents: 4.1.1 + + unist-util-visit@4.1.2: + dependencies: + '@types/unist': 2.0.10 + unist-util-is: 5.2.1 + unist-util-visit-parents: 5.1.3 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + uuid@9.0.1: {} + + uvu@0.5.6: + dependencies: + dequal: 2.0.3 + diff: 5.2.0 + kleur: 4.1.5 + sade: 1.8.1 + + vfile-location@5.0.2: + dependencies: + '@types/unist': 3.0.2 + vfile: 6.0.1 + + vfile-matter@3.0.1: + dependencies: + '@types/js-yaml': 4.0.9 + is-buffer: 2.0.5 + js-yaml: 4.1.0 + + vfile-message@3.1.4: + dependencies: + '@types/unist': 2.0.10 + unist-util-stringify-position: 3.0.3 + + vfile-message@4.0.2: + dependencies: + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 + + vfile@5.3.7: + dependencies: + '@types/unist': 2.0.10 + is-buffer: 2.0.5 + unist-util-stringify-position: 3.0.3 + vfile-message: 3.1.4 + + vfile@6.0.1: + dependencies: + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 + + vscode-oniguruma@1.7.0: {} + + vscode-textmate@8.0.0: {} + + web-namespaces@2.0.1: {} + + web-worker@1.3.0: {} + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + yallist@2.1.2: {} + + yocto-queue@0.1.0: {} + + zod@3.23.8: {} + + zwitch@2.0.4: {} diff --git a/theme.config.jsx b/theme.config.jsx new file mode 100644 index 0000000..60435f5 --- /dev/null +++ b/theme.config.jsx @@ -0,0 +1,6 @@ +export default { + logo: My Nextra Documentation, + project: { + link: 'https://github.com/shuding/nextra' + } + } \ No newline at end of file From 8ea05741dabaa4f240d87464f6db2a34eba7c493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 18 Jun 2024 10:51:57 +0400 Subject: [PATCH 03/75] feat: Adding organized pages. --- README.md | 104 ++++++++++++++++++++++++++++++++- next.config.js | 1 + pages/_meta.json | 6 ++ pages/about.mdx | 7 +++ pages/api_reference.mdx | 8 +++ pages/api_reference/_meta.json | 3 + pages/api_reference/about.mdx | 24 ++++++++ pages/contact.mdx | 17 ++++++ pages/index.mdx | 17 +++++- 9 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 pages/_meta.json create mode 100644 pages/about.mdx create mode 100644 pages/api_reference.mdx create mode 100644 pages/api_reference/_meta.json create mode 100644 pages/api_reference/about.mdx create mode 100644 pages/contact.mdx diff --git a/README.md b/README.md index 07077e3..5b11d14 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,8 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [Who?](#who) - [How?](#how) - [0. Start a new project](#0-start-a-new-project) -- [1. Organizing your content](#1-organizing-your-content) + - [1. Organizing your content](#1-organizing-your-content) + - [1.1 External links and hidden routes](#11-external--links-and-hidden-routes) # Why? @@ -168,12 +169,18 @@ Create a file called `next.config.js` and add the following. ```js const withNextra = require('nextra')({ theme: 'nextra-theme-docs', - themeConfig: './theme.config.jsx' + themeConfig: './theme.config.jsx', + defaultShowCopyCode: true }) module.exports = withNextra() ``` +Here we add global configurations to our project. +For example, we've added `defaultShowCopyCode: true`, +which will make it so code snippets +will have a copy button. + Lastly, we need to create a corresponding `theme.config.jsx` file in your project’s root directory. It will be used to configure our `Nextra`'s site theme. @@ -217,6 +224,97 @@ You've just set up your documentation website! Give yourself a pat on the back. 👏 -# 1. Organizing your content +## 1. Organizing your content + +Now let's write some content! +We are going to organize our documentation +so it's easier to navigate. + +In `Nextra`, +the site and page structure can be configured via +[`_meta.json`](https://nextra.site/docs/guide/organize-files) files. +These files will affect the layout of the theme, +especially the sidebar/navigation bar. + +For example, the title and order of a page shown in the sidebar +should be configured in the `_meta.json` file as key-value pairs. +Create the following structure in your project. + +``` +pages +|_ api_reference + |_ _meta.json + |_ about.mdx +|_ _meta.json +|_ about.mdx +|_ contact.mdx +|_ index.mdx +``` + +Define the pages in the top-level `_meta.json`, like so. + +```json +{ + "index": "My Homepage", + "contact": "Contact Us", + "api_reference": "API Reference", + "about": "About Us" +} +``` + +And in the nested `_meta.json` file, +inside `api_reference`. + +```json +{ + "about": "about" +} +``` + +As you can see, you can group pages together in directories +**to create _an hierarchy_** of pages, +thus organizing them neatly. + +If you want a folder to have their own page, +you can simply add a `.mdx` file +a level above, with the name of the folder. +Let's say we want `api_reference` to have an introductory page +when we click on it on the sidebar. +Simply create the file above the folder's level! + +``` +pages +|_ api_reference + |_ _meta.json + |_ about.mdx +|_ _meta.json +|_ about.mdx +|_ contact.mdx +|_ api_reference.mdx // added this +|_ index.mdx +``` + +Alternatively, you can create an `index.mdx` file inside `api_reference` +to achieve a similar effect. + + +Now fill each `.mdx` with any content you want. +Run `pnpm run dev` and see your pages organized! +

+ +

+ + +### 1.1 External links and hidden routes + +You can further customize the `_meta.json` +to show external links +and hide some routes. +In the top-level `_meta.json`, +change it to the following. + +```json + +``` diff --git a/next.config.js b/next.config.js index 558bf1e..bb00636 100644 --- a/next.config.js +++ b/next.config.js @@ -1,6 +1,7 @@ const withNextra = require("nextra")({ theme: "nextra-theme-docs", themeConfig: "./theme.config.jsx", + defaultShowCopyCode: true }); module.exports = withNextra(); diff --git a/pages/_meta.json b/pages/_meta.json new file mode 100644 index 0000000..6e34077 --- /dev/null +++ b/pages/_meta.json @@ -0,0 +1,6 @@ +{ + "index": "My Homepage", + "contact": "Contact Us", + "api_reference": "API Reference", + "about": "About Us" +} diff --git a/pages/about.mdx b/pages/about.mdx new file mode 100644 index 0000000..f7d8937 --- /dev/null +++ b/pages/about.mdx @@ -0,0 +1,7 @@ +# About Nextra + +Nextra is a powerful static site generator designed specifically for creating modern and highly customizable documentation websites. Built on top of Next.js, it leverages React's capabilities to deliver a seamless and efficient experience for developers. + +With Nextra, you can easily create documentation sites with automatic navigation, markdown support, and themable design options. Whether you are documenting an API, creating a knowledge base, or writing a user manual, Nextra provides the tools you need to get the job done. + +Learn more about the features and capabilities of Nextra as you explore this documentation. diff --git a/pages/api_reference.mdx b/pages/api_reference.mdx new file mode 100644 index 0000000..2f42947 --- /dev/null +++ b/pages/api_reference.mdx @@ -0,0 +1,8 @@ +# API Reference Overview + +The Nextra API Reference provides comprehensive information about the APIs available within the Nextra framework. This documentation is intended for developers who wish to integrate Nextra's features into their own applications or extend its functionality. + +Explore the various API endpoints and learn how to effectively use them in your projects. Each section includes detailed descriptions, usage examples, and response formats to help you get started quickly and efficiently. + +Check out the individual API sections for more details: +- [About API](api_reference/about) \ No newline at end of file diff --git a/pages/api_reference/_meta.json b/pages/api_reference/_meta.json new file mode 100644 index 0000000..36d16a0 --- /dev/null +++ b/pages/api_reference/_meta.json @@ -0,0 +1,3 @@ +{ + "about": "about" +} diff --git a/pages/api_reference/about.mdx b/pages/api_reference/about.mdx new file mode 100644 index 0000000..969b413 --- /dev/null +++ b/pages/api_reference/about.mdx @@ -0,0 +1,24 @@ +# About API + +The About API provides information about the Nextra framework, including its version, features, and capabilities. This endpoint is useful for retrieving metadata about your documentation site and can be utilized in various parts of your application. + +## GET `/api/about` + + +## Response + +The response includes the following fields: + +- `version`: The current version of Nextra. +- `features`: A list of features available in this version. +- `description`: A brief description of Nextra. + +## Example + +```json +{ + "version": "1.0.0", + "features": ["markdown support", "automatic navigation", "theme customization"], + "description": "Nextra is a static site generator for creating modern documentation websites." +} +``` \ No newline at end of file diff --git a/pages/contact.mdx b/pages/contact.mdx new file mode 100644 index 0000000..5fc0ef7 --- /dev/null +++ b/pages/contact.mdx @@ -0,0 +1,17 @@ +# Contact Us + +We'd love to hear from you! If you have any questions, feedback, or suggestions regarding Nextra, please feel free to reach out. + +## Email + +You can email us at [support@nextra.io](mailto:support@nextra.io). + +## Social Media + +Follow us on social media to stay updated with the latest news and updates: +- [Twitter](https://twitter.com/nextra) +- [GitHub](https://github.com/shuding/nextra) + +## Community + +Join our community on [Discord](https://discord.gg/nextra) to connect with other users and developers, ask questions, and share your experiences. diff --git a/pages/index.mdx b/pages/index.mdx index 561c2c8..f527fba 100644 --- a/pages/index.mdx +++ b/pages/index.mdx @@ -1,3 +1,14 @@ -# Welcome to our docs! - -Hello, world! \ No newline at end of file +# Welcome to Nextra Documentation + +Welcome to the Nextra documentation site! Nextra is a modern static site generator optimized for creating high-quality documentation websites with ease. This documentation will guide you through the setup, features, and best practices for using Nextra. + +## Getting Started + +To get started with Nextra, check out the [About](about) page to learn more about its capabilities and features. If you need any assistance, visit our [Contact](contact) page to find out how to reach us. + +Explore the sections below to dive deeper into specific topics: +- [About Nextra](about) +- [API Reference](api_reference) +- [Contact Us](contact) + +We hope you find Nextra useful for your documentation needs! From e709a4ff9c34691bf76ed493ce85c9ef39422bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 18 Jun 2024 11:38:26 +0400 Subject: [PATCH 04/75] feat: Finishing up organization. --- README.md | 111 ++++++++++++++++++++++++++ pages/_meta.json | 26 +++++- pages/api_reference/_meta.json | 6 +- pages/api_reference/users.mdx | 142 +++++++++++++++++++++++++++++++++ 4 files changed, 280 insertions(+), 5 deletions(-) create mode 100644 pages/api_reference/users.mdx diff --git a/README.md b/README.md index 5b11d14..4c30de7 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [0. Start a new project](#0-start-a-new-project) - [1. Organizing your content](#1-organizing-your-content) - [1.1 External links and hidden routes](#11-external--links-and-hidden-routes) + - [1.2 Adding items to the navbar](#12-adding-items-to-the-navbar) + - [2. Organizing your content](#2-organizing-your-content) # Why? @@ -316,5 +318,114 @@ In the top-level `_meta.json`, change it to the following. ```json +{ + "index": "My Homepage", + "contact": "Contact Us", + "api_reference": "API Reference", + "about": "About Us", + "github_link": { + "title": "Github", + "href": "https://github.com/shuding/nextra", + "newWindow": true + } +} +``` + +This will add a new link to the sidebar that, +once clicked, +will redirect the person to the `Github` page. + +You can also hide it. +Simply add the `display` property and set it to `hidden`, +just like in `CSS`! +```json +{ + "index": "My Homepage", + "contact": "Contact Us", + "api_reference": "API Reference", + "about": "About Us", + "github_link": { + "title": "Github", + "href": "https://github.com/shuding/nextra", + "newWindow": true, + "display": "hidden" + } +} ``` + +### 1.2 Adding items to the navbar + +The navbar is a great way to further organize your content. +You can show special pages on the navigation bar +instead of the sidebar. +To do this, you need to use the `"type": "page"` property +in the `_meta.json` file at top level. + +Let's add the `API Reference` to the navbar. +To do this, edit the top-level `_meta.json` to look like so: + +```json +{ + "index": { + "title": "Hello!", + "type": "page" + }, + "api_reference": { + "title": "API Reference", + "type": "page" + }, + "about": { + "title": "About Us", + "type": "page" + }, + "contact": { + "title": "Contact Us", + "type": "page" + }, + "github_link": { + "title": "Github", + "href": "https://github.com/shuding/nextra", + "newWindow": true, + "display": "hidden" + } +} +``` + +This will make every single top-level file +a page on the navbar. +Inside `api_reference`, +create a new file called `users.mdx` +and write whatever you want in it. +Let's change the `_meta.json` file inside this directory +to the following. + +```json +{ + "about": "about", + "---": { + "type": "separator" + }, + "users": "users" +} +``` + +Notice that we've added `"---"`. +This will add a separator between the two sidebar items. + +If you run `pnpm run dev`, +you will see that your site is organized differently. +The top-level pages are in the navbar, +and you can check the sidebar inside the `api_reference` folder contents. + +

+ +

+ +Awesome! 🎉 + +There are the basics on how to organize your content +inside your website! + + +## 2. Organizing your content diff --git a/pages/_meta.json b/pages/_meta.json index 6e34077..4f4bef3 100644 --- a/pages/_meta.json +++ b/pages/_meta.json @@ -1,6 +1,24 @@ { - "index": "My Homepage", - "contact": "Contact Us", - "api_reference": "API Reference", - "about": "About Us" + "index": { + "title": "Hello!", + "type": "page" + }, + "api_reference": { + "title": "API Reference", + "type": "page" + }, + "about": { + "title": "About Us", + "type": "page" + }, + "contact": { + "title": "Contact Us", + "type": "page" + }, + "github_link": { + "title": "Github", + "href": "https://github.com/shuding/nextra", + "newWindow": true, + "display": "hidden" + } } diff --git a/pages/api_reference/_meta.json b/pages/api_reference/_meta.json index 36d16a0..fa05495 100644 --- a/pages/api_reference/_meta.json +++ b/pages/api_reference/_meta.json @@ -1,3 +1,7 @@ { - "about": "about" + "about": "about", + "---": { + "type": "separator" + }, + "users": "users" } diff --git a/pages/api_reference/users.mdx b/pages/api_reference/users.mdx new file mode 100644 index 0000000..0733dde --- /dev/null +++ b/pages/api_reference/users.mdx @@ -0,0 +1,142 @@ +# Users API + +The Users API allows you to manage user data within your Nextra-powered documentation site. This endpoint provides functionalities to create, retrieve, update, and delete user information, making it a crucial component for any user-centric applications. + +## Endpoints + +### Get Users + +Retrieve a list of all users. + +**Endpoint:** +``` +GET /api/users +``` + +**Response:** + +The response includes a list of user objects, each containing the following fields: +- `id`: The unique identifier for the user. +- `name`: The name of the user. +- `email`: The email address of the user. +- `role`: The role of the user within the system. + +**Example:** + +```json +[ + { + "id": "1", + "name": "John Doe", + "email": "john.doe@example.com", + "role": "admin" + }, + { + "id": "2", + "name": "Jane Smith", + "email": "jane.smith@example.com", + "role": "editor" + } +] +``` + +### Create User + +Add a new user to the system. + +**Endpoint:** +``` +POST /api/users +``` + +**Request Body:** + +The request body should include the following fields: +- `name` (required): The name of the user. +- `email` (required): The email address of the user. +- `role` (optional): The role of the user. Default is `viewer`. + +**Example:** + +```json +{ + "name": "Alice Johnson", + "email": "alice.johnson@example.com", + "role": "editor" +} +``` + +**Response:** + +The response includes the created user object. + +```json +{ + "id": "3", + "name": "Alice Johnson", + "email": "alice.johnson@example.com", + "role": "editor" +} +``` + +### Update User + +Modify an existing user's information. + +**Endpoint:** +``` +PUT /api/users/:id +``` + +**Request Body:** + +The request body can include any of the following fields to update: +- `name` (optional): The name of the user. +- `email` (optional): The email address of the user. +- `role` (optional): The role of the user. + +**Example:** + +```json +{ + "name": "Alice Johnson", + "email": "alice.johnson@newdomain.com", + "role": "admin" +} +``` + +**Response:** + +The response includes the updated user object. + +```json +{ + "id": "3", + "name": "Alice Johnson", + "email": "alice.johnson@newdomain.com", + "role": "admin" +} +``` + +### Delete User + +Remove a user from the system. + +**Endpoint:** +``` +DELETE /api/users/:id +``` + +**Response:** + +The response includes a confirmation message. + +```json +{ + "message": "User deleted successfully." +} +``` + +## Summary + +The Users API provides essential operations for managing users within your Nextra documentation site. Whether you need to add new users, update existing ones, or remove users, these endpoints offer the flexibility to handle all user-related tasks efficiently. For more information on other available APIs, refer back to the [API Reference](index). From 427cc4911b1db40a6c9c1f5457c27494610041bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 18 Jun 2024 11:40:01 +0400 Subject: [PATCH 05/75] chore: Adding intro to the authentication. --- README.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c30de7..bb2df17 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [1. Organizing your content](#1-organizing-your-content) - [1.1 External links and hidden routes](#11-external--links-and-hidden-routes) - [1.2 Adding items to the navbar](#12-adding-items-to-the-navbar) - - [2. Organizing your content](#2-organizing-your-content) + - [2. Adding authentication](#2-adding-authentication) # Why? @@ -428,4 +428,21 @@ There are the basics on how to organize your content inside your website! -## 2. Organizing your content +## 2. Adding authentication + +Now that our website is in working order, +let's work in adding authentication to it! +This is important because +you may want to use this website +*for internal purposes*, +meaning that **it can't be public-facing**. + +To address this issue, +we are going to make the users have to sign in +through a given provider +to be able to visit private pages +that we will define ourselves. + +Let's rock! 🎸 + + From 7556c8b9c6556d43eda2dc40beb3a0938aa71fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 18 Jun 2024 12:33:27 +0400 Subject: [PATCH 06/75] feat: Intro to auth. --- .vscode/settings.json | 3 + README.md | 145 ++++++++++++++++++++++++++++ app/api/auth/[...nextauth]/route.ts | 2 + auth.ts | 5 + middleware.ts | 1 + next-env.d.ts | 6 ++ package.json | 11 ++- pnpm-lock.yaml | 121 +++++++++++++++++++++++ tsconfig.json | 34 +++++++ 9 files changed, 325 insertions(+), 3 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 app/api/auth/[...nextauth]/route.ts create mode 100644 auth.ts create mode 100644 middleware.ts create mode 100644 next-env.d.ts create mode 100644 tsconfig.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..55712c1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/README.md b/README.md index bb2df17..6732097 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [1.1 External links and hidden routes](#11-external--links-and-hidden-routes) - [1.2 Adding items to the navbar](#12-adding-items-to-the-navbar) - [2. Adding authentication](#2-adding-authentication) + - [2.1 Adding Github provider](#21-adding-github-provider) # Why? @@ -445,4 +446,148 @@ that we will define ourselves. Let's rock! 🎸 +We are going to be using +[`Auth.js`](https://authjs.dev/) to streamline our authentication process. +This framework was previously working solely on `Next.js` projects, +but this new `v5` release extends their compatibility to other frameworks. + +Let's add it to our project! + +> [!NOTE] +> +> At the time of writing, +> only the `beta` version of `auth.js` is working. +> We'll update this doc when a full stable release is announced. + +```sh +pnpm add next-auth@beta +``` + +Great! +Now let's create our secret. +We are going to be using this secret as an [environment variable](https://github.com/dwyl/learn-environment-variables), +which is used by the library to encrypt token and e-mail verification hashes. +Simply run: + +```sh +npx auth secret +``` + +Your terminal will show this: + +``` +Need to install the following packages: +auth@1.0.2 +Ok to proceed? (y) y + +Secret generated. Copy it to your .env/.env.local file (depending on your framework): + +AUTH_SECRET= +``` + +Copy the secret and create a file called `.env.local`. + +```sh +AUTH_SECRET=secret +``` + +Great! +Now let's create the configuration files needed for `Auth.js` to work! +Start by creating a file called `auth.ts` at the root. + +```ts +import NextAuth from "next-auth"; + +export const { handlers, signIn, signOut, auth } = NextAuth({ + providers: [], +}); +``` + +Then, create the following folders from the root of the project - +`/app/api/auth/[...nextauth]/`. +`Nextra` only works in the [Pages Router](https://nextjs.org/docs/pages). +Authentication with `Auth.js` needs the +[App Router](https://nextjs.org/docs/app) to work. +For this, we need to create the folder hierarchy we've just mentioned. + +After creating the folders, +create a file called `route.ts` inside `[...nextauth]. + +```ts +import { handlers } from "@/auth" // Referring to the auth.ts we just created +export const { GET, POST } = handlers +``` + +And add a file called `middleware.ts` at the root of the project. +This is to keep the session alive, +this will update the session expiry every time its called. + +```ts +export { auth as middleware } from "@/auth" +``` + +> [!NOTE] +> +> Your imports may be complaining about not being able to find the `@auth` module. +> To fix this, create a `tsconfig.json` file at the root of the project +> with the following code. +> +> ```json +> { +> "compilerOptions": { +> "target": "es5", +> "lib": ["dom", "dom.iterable", "esnext"], +> "allowJs": true, +> "skipLibCheck": true, +> "strict": true, +> "noEmit": true, +> "esModuleInterop": true, +> "module": "esnext", +> "moduleResolution": "bundler", +> "resolveJsonModule": true, +> "isolatedModules": true, +> "jsx": "preserve", +> "incremental": true, +> "plugins": [ +> { +> "name": "next" +> } +> ], +> "paths": { +> "@/*": ["./*"] +> } +> }, +> "include": [ +> "next-env.d.ts", +> "**/*.ts", +> "**/*.tsx", +> ".next/types/**/*.ts", +> "app/lib/placeholder-data.js", +> "scripts/seed.js" +> ], +> "exclude": ["node_modules"] +> } + +And that's it! +We're all ready to go! + + +### 2.1 Adding Github provider + +You can now decide how you are going to authenticate the users into your application. +You can either: +- choose an [`OAuth`](https://oauth.net/2/), +a delegated authentication where you delegate through a third party. +- or you can set up your own [identity provider](https://www.cloudflare.com/en-gb/learning/access-management/what-is-an-identity-provider/) +and take care of it yourself. + +We're going to choose the former, because it's easier. +[`Auth.js` docs](https://authjs.dev/getting-started/authentication) explain it succinctly. + +> OAuth services spend significant amounts of money, time, and engineering effort to build abuse detection (bot-protection, rate-limiting), +> password management (password reset, credential stuffing, rotation), +> data security (encryption/salting, strength validation), and much more. +> It is likely that your application would benefit from leveraging these battle-tested solutions rather than try to rebuild them from scratch. + +Let's authenticate our users through a GitHub provider! diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 0000000..0cf1408 --- /dev/null +++ b/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,2 @@ +import { handlers } from "@/auth" // Referring to the auth.ts we just created +export const { GET, POST } = handlers \ No newline at end of file diff --git a/auth.ts b/auth.ts new file mode 100644 index 0000000..3be7be6 --- /dev/null +++ b/auth.ts @@ -0,0 +1,5 @@ +import NextAuth from "next-auth"; + +export const { handlers, signIn, signOut, auth } = NextAuth({ + providers: [], +}); diff --git a/middleware.ts b/middleware.ts new file mode 100644 index 0000000..2df914b --- /dev/null +++ b/middleware.ts @@ -0,0 +1 @@ +export { auth as middleware } from "@/auth" \ No newline at end of file diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..fd36f94 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/package.json b/package.json index 32a5641..0e8cd5f 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,14 @@ }, "dependencies": { "next": "^14.2.4", - "react": "^18.3.1", - "react-dom": "^18.3.1", + "next-auth": "5.0.0-beta.19", "nextra": "^2.13.4", - "nextra-theme-docs": "^2.13.4" + "nextra-theme-docs": "^2.13.4", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/node": "20.14.5", + "typescript": "5.4.5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a9f3e63..8b230ce 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,9 @@ importers: next: specifier: ^14.2.4 version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-auth: + specifier: 5.0.0-beta.19 + version: 5.0.0-beta.19(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) nextra: specifier: ^2.13.4 version: 2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -23,9 +26,30 @@ importers: react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) + devDependencies: + '@types/node': + specifier: 20.14.5 + version: 20.14.5 + typescript: + specifier: 5.4.5 + version: 5.4.5 packages: + '@auth/core@0.32.0': + resolution: {integrity: sha512-3+ssTScBd+1fd0/fscAyQN1tSygXzuhysuVVzB942ggU4mdfiTbv36P0ccVnExKWYJKvu3E2r3/zxXCCAmTOrg==} + peerDependencies: + '@simplewebauthn/browser': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 + nodemailer: ^6.8.0 + peerDependenciesMeta: + '@simplewebauthn/browser': + optional: true + '@simplewebauthn/server': + optional: true + nodemailer: + optional: true + '@babel/runtime@7.24.7': resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==} engines: {node: '>=6.9.0'} @@ -175,6 +199,9 @@ packages: cpu: [x64] os: [win32] + '@panva/hkdf@1.1.1': + resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} + '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} @@ -204,6 +231,9 @@ packages: '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/d3-scale-chromatic@3.0.3': resolution: {integrity: sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==} @@ -246,6 +276,9 @@ packages: '@types/ms@0.7.34': resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + '@types/node@20.14.5': + resolution: {integrity: sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==} + '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -354,6 +387,10 @@ packages: compute-scroll-into-view@3.1.0: resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} @@ -734,6 +771,9 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + jose@5.4.0: + resolution: {integrity: sha512-6rpxTHPAQyWMb9A35BroFl1Sp0ST3DpPcm5EVIxZxdH+e0Hv9fwhyB3XLKFUcHNpdSDnETmBfuPPTTlYz5+USw==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -987,6 +1027,22 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + next-auth@5.0.0-beta.19: + resolution: {integrity: sha512-YHu1igcAxZPh8ZB7GIM93dqgY6gcAzq66FOhQFheAdOx1raxNcApt05nNyNCSB6NegSiyJ4XOPsaNow4pfDmsg==} + peerDependencies: + '@simplewebauthn/browser': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 + next: ^14 || ^15.0.0-0 + nodemailer: ^6.6.5 + react: ^18.2.0 || ^19.0.0-0 + peerDependenciesMeta: + '@simplewebauthn/browser': + optional: true + '@simplewebauthn/server': + optional: true + nodemailer: + optional: true + next-mdx-remote@4.4.1: resolution: {integrity: sha512-1BvyXaIou6xy3XoNF4yaMZUCb6vD2GTAa5ciOa6WoO+gAUTYsb1K4rI/HSC2ogAWLrb/7VSV52skz07vOzmqIQ==} engines: {node: '>=14', npm: '>=7'} @@ -1053,6 +1109,9 @@ packages: resolution: {integrity: sha512-O/j/ROyX0KGLG7O6Ieut/seQ0oiTpHF2tXAcFbpdTLQFiaNtkyTXXocM1fwpaa60dg1qpWj0nHlbNhx6qwuENQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + oauth4webapi@2.10.4: + resolution: {integrity: sha512-DSoj8QoChzOCQlJkRmYxAJCIpnXFW32R0Uq7avyghIeB6iJq0XAblOD7pcq3mx4WEBDwMuKr0Y1qveCBleG2Xw==} + p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} @@ -1090,6 +1149,17 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} + preact-render-to-string@5.2.3: + resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} + peerDependencies: + preact: '>=10' + + preact@10.11.3: + resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} + + pretty-format@3.8.0: + resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} + property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} @@ -1269,6 +1339,14 @@ packages: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} engines: {node: '>=10'} + typescript@5.4.5: + resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + unified@10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} @@ -1384,6 +1462,16 @@ packages: snapshots: + '@auth/core@0.32.0': + dependencies: + '@panva/hkdf': 1.1.1 + '@types/cookie': 0.6.0 + cookie: 0.6.0 + jose: 5.4.0 + oauth4webapi: 2.10.4 + preact: 10.11.3 + preact-render-to-string: 5.2.3(preact@10.11.3) + '@babel/runtime@7.24.7': dependencies: regenerator-runtime: 0.14.1 @@ -1501,6 +1589,8 @@ snapshots: '@next/swc-win32-x64-msvc@14.2.4': optional: true + '@panva/hkdf@1.1.1': {} + '@popperjs/core@2.11.8': {} '@swc/counter@0.1.3': {} @@ -1535,6 +1625,8 @@ snapshots: dependencies: '@types/estree': 1.0.5 + '@types/cookie@0.6.0': {} + '@types/d3-scale-chromatic@3.0.3': {} '@types/d3-scale@4.0.8': @@ -1577,6 +1669,10 @@ snapshots: '@types/ms@0.7.34': {} + '@types/node@20.14.5': + dependencies: + undici-types: 5.26.5 + '@types/prop-types@15.7.12': {} '@types/react@18.3.3': @@ -1661,6 +1757,8 @@ snapshots: compute-scroll-into-view@3.1.0: {} + cookie@0.6.0: {} + cose-base@1.0.3: dependencies: layout-base: 1.0.2 @@ -2118,6 +2216,8 @@ snapshots: isexe@2.0.0: {} + jose@5.4.0: {} + js-tokens@4.0.0: {} js-yaml@3.14.1: @@ -2659,6 +2759,12 @@ snapshots: nanoid@3.3.7: {} + next-auth@5.0.0-beta.19(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + dependencies: + '@auth/core': 0.32.0 + next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + next-mdx-remote@4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@mdx-js/mdx': 2.3.0 @@ -2769,6 +2875,8 @@ snapshots: npm-to-yarn@2.2.1: {} + oauth4webapi@2.10.4: {} + p-finally@1.0.0: {} p-limit@3.1.0: @@ -2816,6 +2924,15 @@ snapshots: picocolors: 1.0.1 source-map-js: 1.2.0 + preact-render-to-string@5.2.3(preact@10.11.3): + dependencies: + preact: 10.11.3 + pretty-format: 3.8.0 + + preact@10.11.3: {} + + pretty-format@3.8.0: {} + property-information@6.5.0: {} protocols@2.0.1: {} @@ -3003,6 +3120,10 @@ snapshots: type-fest@1.4.0: {} + typescript@5.4.5: {} + + undici-types@5.26.5: {} + unified@10.1.2: dependencies: '@types/unist': 2.0.10 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8ec8567 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + "app/lib/placeholder-data.js", + "scripts/seed.js" + ], + "exclude": ["node_modules"] +} \ No newline at end of file From c319097c4ea20118882614d1de4079640173f4d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 18 Jun 2024 13:02:51 +0400 Subject: [PATCH 07/75] feat: Adding auth configuration. --- .env.local-example | 4 +++ README.md | 70 +++++++++++++++++++++++++++++++++++++++++++++- auth.ts | 3 +- 3 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 .env.local-example diff --git a/.env.local-example b/.env.local-example new file mode 100644 index 0000000..90d0fe8 --- /dev/null +++ b/.env.local-example @@ -0,0 +1,4 @@ +AUTH_SECRET= + +AUTH_GITHUB_ID= +AUTH_GITHUB_SECRET= \ No newline at end of file diff --git a/README.md b/README.md index 6732097..34af083 100644 --- a/README.md +++ b/README.md @@ -420,7 +420,7 @@ The top-level pages are in the navbar, and you can check the sidebar inside the `api_reference` folder contents.

- +

Awesome! 🎉 @@ -591,3 +591,71 @@ We're going to choose the former, because it's easier. Let's authenticate our users through a GitHub provider! +Let's add it to our `providers` array inside `auth.ts` + +```ts +import NextAuth from "next-auth"; +import GitHub from "next-auth/providers/github" + +export const { handlers, signIn, signOut, auth } = NextAuth({ + providers: [GitHub], +}); + +``` + +Next, create an **`OAuth` app** inside our GitHub account. +Navigate to `https://github.com/settings/developers` +and click on `OAuth Apps` +and click on `New OAuth App`. + +

+ +

+ +Fill out the information. +The default callback URL will be of the form of +`[origin]/api/auth/callback/[provider]`. +While developing, you may use `localhost` as the `origin`. +However, you'll have to chance this to your product's domain in production. + +```sh +// Local +http://localhost:3000/api/auth/callback/github + +// Prod +https://app.company.com/api/auth/callback/github +``` + +

+ +

+ +After completing the form, +you will be redirected to the page of your newly created `OAuth` app. +Click on `Generate a new client secret`. + +

+ +

+ +You will be shown the secret of the new app. +Do not close the page, you will need to copy this `secret` and the shown `client ID.` + +

+ +

+ +In your `.env.local` file, +add these two copied strings, like so. + +```sh +AUTH_SECRET= + +AUTH_GITHUB_ID= +AUTH_GITHUB_SECRET= +``` + +And that's all the configuration we need! +Now it's time to authenticate people into our app! + + diff --git a/auth.ts b/auth.ts index 3be7be6..b4c6e16 100644 --- a/auth.ts +++ b/auth.ts @@ -1,5 +1,6 @@ import NextAuth from "next-auth"; +import GitHub from "next-auth/providers/github" export const { handlers, signIn, signOut, auth } = NextAuth({ - providers: [], + providers: [GitHub], }); From 989c4631089a823fa2223ffcec9c1f4d910881a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Wed, 19 Jun 2024 13:45:34 +0400 Subject: [PATCH 08/75] feat: Adding script that generates private routes based on `_meta.json` to be used in `middleware.ts`. --- generateMiddleware.ts | 85 +++++++++++ package.json | 7 +- pnpm-lock.yaml | 317 ++++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 10 +- 4 files changed, 417 insertions(+), 2 deletions(-) create mode 100644 generateMiddleware.ts diff --git a/generateMiddleware.ts b/generateMiddleware.ts new file mode 100644 index 0000000..1a8df57 --- /dev/null +++ b/generateMiddleware.ts @@ -0,0 +1,85 @@ +import { Project } from "ts-morph"; +import path from "path"; +import fs from "fs"; +import { globSync } from "fast-glob"; + +// Types for the `_meta.json` structure +type PrivateInfo = { + private: boolean; + roles?: string[]; +}; + +type MetaJson = { + [key: string]: string | any | PrivateInfo; +}; + +type PrivateRoutes = { + [key: string]: string[] +} + +/** + * This function looks at the file system under a path and goes through each `_meta.json` looking for private roots recursively. + * It is expecting the `_meta.json` values of keys to have a property called "private" to consider the route as private for specific roles. + * @param pagesDir path to recursively look for. + * @returns map of private routes as key and array of roles that are permitted to access the route. + */ +function getPrivateRoutes(pagesDir: string): PrivateRoutes { + let privateRoutes: PrivateRoutes = {}; + + // Find all _meta.json files recursively + const metaFiles = globSync(path.join(pagesDir, "**/_meta.json")); + + // Iterate over the found meta files + for (const file of metaFiles) { + + // Get the path of file and read it + const dir = path.dirname(file); + const metaJson: MetaJson = JSON.parse(fs.readFileSync(file, "utf-8")); + + // Iterate over the key/value pairs + for (const [key, meta] of Object.entries(metaJson)) { + // Check if the current meta has a private property + if (meta.private !== undefined) { + if (typeof meta.private === "boolean") { + // If private is a boolean, directly use it + if (meta.private) { + const route = path.join(dir, key).replace(pagesDir, "").replace(/\\/g, "/"); + privateRoutes[route] = []; + } + } + // If private is an object with private true and roles array (which can be omitted) + else if (meta.private.private) { + const route = path.join(dir, key).replace(pagesDir, "").replace(/\\/g, "/"); + privateRoutes[route] = meta.private.roles || []; + } + // Do nothing if private is an object with private false or without roles array + } + } + } + + return privateRoutes; +}; + +// - - - - - - - - - - - - - - - - - - - - - - - +// `middleware.ts` is changed by executing the code below. + + +const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated +const DIRECTORY = "pages" // Directory to look for the routes (should be `pages`, according to Nextra's file system) + +// Get private routes +const pagesDir = path.join(__dirname, DIRECTORY); +const privateRoutes = getPrivateRoutes(pagesDir); + +// Initialize the project and source file +const project = new Project(); +const sourceFile = project.addSourceFileAtPath(path.resolve(__dirname, "middleware.ts")); + +// Find the variable to replace and change it's declaration +const variable = sourceFile.getVariableDeclaration(CONST_VARIABLE_NAME); +if (variable) { + variable.setInitializer(JSON.stringify(privateRoutes)); + sourceFile.saveSync(); +} else { + console.error("Variable not found in `middleware.ts`. File wasn't changed."); +} diff --git a/package.json b/package.json index 0e8cd5f..5084c49 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,8 @@ { "scripts": { - "dev": "next", + "dev": "npm run private-route-gen && next", + "private-route-gen": "ts-node generateMiddleware.ts", + "prebuild": "npm run private-route-gen", "build": "next build", "start": "next start" }, @@ -14,6 +16,9 @@ }, "devDependencies": { "@types/node": "20.14.5", + "fast-glob": "^3.3.2", + "ts-morph": "^22.0.0", + "ts-node": "^10.9.2", "typescript": "5.4.5" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8b230ce..171b948 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,6 +30,15 @@ importers: '@types/node': specifier: 20.14.5 version: 20.14.5 + fast-glob: + specifier: ^3.3.2 + version: 3.3.2 + ts-morph: + specifier: ^22.0.0 + version: 22.0.0 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.14.5)(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -57,6 +66,10 @@ packages: '@braintree/sanitize-url@6.0.4': resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + '@headlessui/react@1.7.19': resolution: {integrity: sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==} engines: {node: '>=10'} @@ -64,6 +77,16 @@ packages: react: ^16 || ^17 || ^18 react-dom: ^16 || ^17 || ^18 + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@mdx-js/mdx@2.3.0': resolution: {integrity: sha512-jLuwRlz8DQfQNiUCJR50Y09CGPq3fLtmtUQfVrj79E0JWu3dvsVcxVIcfhR5h0iXu+/z++zDrYeiJqifRynJkA==} @@ -199,6 +222,18 @@ packages: cpu: [x64] os: [win32] + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + '@panva/hkdf@1.1.1': resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} @@ -228,6 +263,21 @@ packages: '@theguild/remark-npm2yarn@0.2.1': resolution: {integrity: sha512-jUTFWwDxtLEFtGZh/TW/w30ySaDJ8atKWH8dq2/IiQF61dPrGfETpl0WxD0VdBfuLOeU14/kop466oBSRO/5CA==} + '@ts-morph/common@0.23.0': + resolution: {integrity: sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} @@ -299,6 +349,10 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.3: + resolution: {integrity: sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==} + engines: {node: '>=0.4.0'} + acorn@8.12.0: resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} engines: {node: '>=0.4.0'} @@ -317,6 +371,9 @@ packages: arg@1.0.0: resolution: {integrity: sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw==} + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -330,6 +387,16 @@ packages: bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} @@ -367,6 +434,9 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + code-block-writer@13.0.1: + resolution: {integrity: sha512-c5or4P6erEA69TxaxTNcHUNcIn+oyxSRTOWV+pSYF+z4epXqNvwvJ70XPGjPNgue83oAFAPBRQYwpAJ/Hpe/Sg==} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -394,6 +464,9 @@ packages: cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} @@ -576,6 +649,10 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + diff@5.2.0: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} @@ -636,6 +713,17 @@ packages: extend@3.0.2: resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + flexsearch@0.7.43: resolution: {integrity: sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==} @@ -655,6 +743,10 @@ packages: github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -743,9 +835,21 @@ packages: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + is-obj@3.0.0: resolution: {integrity: sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ==} engines: {node: '>=12'} @@ -822,6 +926,9 @@ packages: lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + markdown-extensions@1.1.1: resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} engines: {node: '>=0.10.0'} @@ -889,6 +996,10 @@ packages: mdast-util-to-string@3.2.0: resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + mermaid@10.9.1: resolution: {integrity: sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA==} @@ -1015,6 +1126,19 @@ packages: micromark@3.2.0: resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + mkdirp@3.0.1: + resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} + engines: {node: '>=10'} + hasBin: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1135,6 +1259,9 @@ packages: parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-key@2.0.1: resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} engines: {node: '>=4'} @@ -1145,6 +1272,10 @@ packages: picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} @@ -1169,6 +1300,9 @@ packages: pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -1217,9 +1351,16 @@ packages: remove-accents@0.5.0: resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} @@ -1322,6 +1463,10 @@ packages: resolution: {integrity: sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw==} engines: {node: '>=0.10.0'} + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -1332,6 +1477,23 @@ packages: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'} + ts-morph@22.0.0: + resolution: {integrity: sha512-M9MqFGZREyeb5fTl6gNHKZLqBQA0TjA1lea+CR48R8EBTDuWrNqW6ccC5QvjNR4s6wDumD3LTCjOFSp9iwlzaw==} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} @@ -1413,6 +1575,9 @@ packages: engines: {node: '>=8'} hasBin: true + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + vfile-location@5.0.2: resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} @@ -1450,6 +1615,10 @@ packages: yallist@2.1.2: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -1478,6 +1647,10 @@ snapshots: '@braintree/sanitize-url@6.0.4': {} + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + '@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@tanstack/react-virtual': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -1485,6 +1658,15 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.4.15': {} + + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@mdx-js/mdx@2.3.0': dependencies: '@types/estree-jsx': 1.0.5 @@ -1589,6 +1771,18 @@ snapshots: '@next/swc-win32-x64-msvc@14.2.4': optional: true + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + '@panva/hkdf@1.1.1': {} '@popperjs/core@2.11.8': {} @@ -1621,6 +1815,21 @@ snapshots: npm-to-yarn: 2.2.1 unist-util-visit: 5.0.0 + '@ts-morph/common@0.23.0': + dependencies: + fast-glob: 3.3.2 + minimatch: 9.0.4 + mkdirp: 3.0.1 + path-browserify: 1.0.1 + + '@tsconfig/node10@1.0.11': {} + + '@tsconfig/node12@1.0.11': {} + + '@tsconfig/node14@1.0.3': {} + + '@tsconfig/node16@1.0.4': {} + '@types/acorn@4.0.6': dependencies: '@types/estree': 1.0.5 @@ -1690,6 +1899,10 @@ snapshots: dependencies: acorn: 8.12.0 + acorn-walk@8.3.3: + dependencies: + acorn: 8.12.0 + acorn@8.12.0: {} ansi-sequence-parser@1.1.1: {} @@ -1702,6 +1915,8 @@ snapshots: arg@1.0.0: {} + arg@4.1.3: {} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -1712,6 +1927,16 @@ snapshots: bail@2.0.2: {} + balanced-match@1.0.2: {} + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + busboy@1.6.0: dependencies: streamsearch: 1.1.0 @@ -1743,6 +1968,8 @@ snapshots: clsx@2.1.1: {} + code-block-writer@13.0.1: {} + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -1763,6 +1990,8 @@ snapshots: dependencies: layout-base: 1.0.2 + create-require@1.1.1: {} + cross-spawn@5.1.0: dependencies: lru-cache: 4.1.5 @@ -1970,6 +2199,8 @@ snapshots: dependencies: dequal: 2.0.3 + diff@4.0.2: {} + diff@5.2.0: {} dompurify@3.1.5: {} @@ -2031,6 +2262,22 @@ snapshots: extend@3.0.2: {} + fast-glob@3.3.2: + 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.7 + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + flexsearch@0.7.43: {} focus-visible@5.2.0: {} @@ -2048,6 +2295,10 @@ snapshots: github-slugger@2.0.0: {} + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + graceful-fs@4.2.11: {} gray-matter@4.0.3: @@ -2196,8 +2447,16 @@ snapshots: is-extendable@0.1.1: {} + is-extglob@2.1.1: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + is-hexadecimal@2.0.1: {} + is-number@7.0.0: {} + is-obj@3.0.0: {} is-plain-obj@3.0.0: {} @@ -2258,6 +2517,8 @@ snapshots: pseudomap: 1.0.2 yallist: 2.1.2 + make-error@1.3.6: {} + markdown-extensions@1.1.1: {} markdown-table@3.0.3: {} @@ -2437,6 +2698,8 @@ snapshots: dependencies: '@types/mdast': 3.0.15 + merge2@1.4.1: {} + mermaid@10.9.1: dependencies: '@braintree/sanitize-url': 6.0.4 @@ -2753,6 +3016,17 @@ snapshots: transitivePeerDependencies: - supports-color + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + minimatch@9.0.4: + dependencies: + brace-expansion: 2.0.1 + + mkdirp@3.0.1: {} + mri@1.2.0: {} ms@2.1.2: {} @@ -2908,6 +3182,8 @@ snapshots: dependencies: entities: 4.5.0 + path-browserify@1.0.1: {} + path-key@2.0.1: {} periscopic@3.1.0: @@ -2918,6 +3194,8 @@ snapshots: picocolors@1.0.1: {} + picomatch@2.3.1: {} + postcss@8.4.31: dependencies: nanoid: 3.3.7 @@ -2939,6 +3217,8 @@ snapshots: pseudomap@1.0.2: {} + queue-microtask@1.2.3: {} + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 @@ -3023,8 +3303,14 @@ snapshots: remove-accents@0.5.0: {} + reusify@1.0.4: {} + robust-predicates@3.0.2: {} + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + rw@1.3.3: {} sade@1.8.1: @@ -3110,12 +3396,39 @@ snapshots: titleize@1.0.0: {} + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + trim-lines@3.0.1: {} trough@2.2.0: {} ts-dedent@2.2.0: {} + ts-morph@22.0.0: + dependencies: + '@ts-morph/common': 0.23.0 + code-block-writer: 13.0.1 + + ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.14.5 + acorn: 8.12.0 + acorn-walk: 8.3.3 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.4.5 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + tslib@2.6.3: {} type-fest@1.4.0: {} @@ -3227,6 +3540,8 @@ snapshots: kleur: 4.1.5 sade: 1.8.1 + v8-compile-cache-lib@3.0.1: {} + vfile-location@5.0.2: dependencies: '@types/unist': 3.0.2 @@ -3275,6 +3590,8 @@ snapshots: yallist@2.1.2: {} + yn@3.1.1: {} + yocto-queue@0.1.0: {} zod@3.23.8: {} diff --git a/tsconfig.json b/tsconfig.json index 8ec8567..1175064 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -30,5 +30,13 @@ "app/lib/placeholder-data.js", "scripts/seed.js" ], - "exclude": ["node_modules"] + "exclude": ["node_modules"], + + // These are only used by `ts-node` to run the script that generates the private routes. + // These options are overrides used only by ts-node, same as the --compilerOptions flag and the TS_NODE_COMPILER_OPTIONS environment variable + "ts-node": { + "compilerOptions": { + "module": "commonjs" + } + }, } \ No newline at end of file From 088f5e985e149461db44d39af6d6153891200d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Wed, 19 Jun 2024 13:46:06 +0400 Subject: [PATCH 09/75] refactor: Formatting script. --- generateMiddleware.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/generateMiddleware.ts b/generateMiddleware.ts index 1a8df57..7544073 100644 --- a/generateMiddleware.ts +++ b/generateMiddleware.ts @@ -14,8 +14,8 @@ type MetaJson = { }; type PrivateRoutes = { - [key: string]: string[] -} + [key: string]: string[]; +}; /** * This function looks at the file system under a path and goes through each `_meta.json` looking for private roots recursively. @@ -31,7 +31,6 @@ function getPrivateRoutes(pagesDir: string): PrivateRoutes { // Iterate over the found meta files for (const file of metaFiles) { - // Get the path of file and read it const dir = path.dirname(file); const metaJson: MetaJson = JSON.parse(fs.readFileSync(file, "utf-8")); @@ -58,14 +57,13 @@ function getPrivateRoutes(pagesDir: string): PrivateRoutes { } return privateRoutes; -}; +} // - - - - - - - - - - - - - - - - - - - - - - - // `middleware.ts` is changed by executing the code below. - const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated -const DIRECTORY = "pages" // Directory to look for the routes (should be `pages`, according to Nextra's file system) +const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) // Get private routes const pagesDir = path.join(__dirname, DIRECTORY); From 4ef1fcb70892fb4c9b8cf621d7769024acc74089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Wed, 19 Jun 2024 18:01:40 +0400 Subject: [PATCH 10/75] feat: Adding sign in and sign out. --- README.md | 11 +++++-- components/LoginOrUserInfo/index.tsx | 19 ++++++++++++ package.json | 2 +- pages/_meta.json | 11 +++++-- pages/api_reference/_meta.json | 6 +++- pages/api_reference/mega_private/_meta.json | 4 +++ pages/api_reference/mega_private/hello.mdx | 3 ++ pages/index.mdx | 34 +++++++++++++++++++++ tsconfig.json | 1 + 9 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 components/LoginOrUserInfo/index.tsx create mode 100644 pages/api_reference/mega_private/_meta.json create mode 100644 pages/api_reference/mega_private/hello.mdx diff --git a/README.md b/README.md index 34af083..e95b5cb 100644 --- a/README.md +++ b/README.md @@ -369,8 +369,9 @@ To do this, edit the top-level `_meta.json` to look like so: ```json { "index": { - "title": "Hello!", - "type": "page" + "title": "Homepage", + "type": "page", + "display": "hidden" }, "api_reference": { "title": "API Reference", @@ -395,6 +396,9 @@ To do this, edit the top-level `_meta.json` to look like so: This will make every single top-level file a page on the navbar. +We've hidden the `index.mdx`, +because it's rendered by default when we enter the site +and we can return to it if we click on the website's logo. Inside `api_reference`, create a new file called `users.mdx` and write whatever you want in it. @@ -659,3 +663,6 @@ And that's all the configuration we need! Now it's time to authenticate people into our app! + + + diff --git a/components/LoginOrUserInfo/index.tsx b/components/LoginOrUserInfo/index.tsx new file mode 100644 index 0000000..b291398 --- /dev/null +++ b/components/LoginOrUserInfo/index.tsx @@ -0,0 +1,19 @@ +import Link from "next/link"; +import { signOut } from "next-auth/react"; +import { Session } from "next-auth"; + +export function LoginOrUserInfo({ session } : Readonly<{session: Session}>) { + if (session?.user) { + return ( +
+ + Welcome {session.user.name} + {" "} +
+ +
+ ); + } else { + return LOGIN; + } +} diff --git a/package.json b/package.json index 5084c49..77f5828 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "scripts": { - "dev": "npm run private-route-gen && next", "private-route-gen": "ts-node generateMiddleware.ts", + "dev": "npm run private-route-gen && next", "prebuild": "npm run private-route-gen", "build": "next build", "start": "next start" diff --git a/pages/_meta.json b/pages/_meta.json index 4f4bef3..60a29eb 100644 --- a/pages/_meta.json +++ b/pages/_meta.json @@ -1,11 +1,16 @@ { "index": { - "title": "Hello!", - "type": "page" + "title": "Homepage", + "type": "page", + "display": "hidden" }, "api_reference": { "title": "API Reference", - "type": "page" + "type": "page", + "private": { + "private": true, + "roles": ["role1", "role2"] + } }, "about": { "title": "About Us", diff --git a/pages/api_reference/_meta.json b/pages/api_reference/_meta.json index fa05495..5db147b 100644 --- a/pages/api_reference/_meta.json +++ b/pages/api_reference/_meta.json @@ -3,5 +3,9 @@ "---": { "type": "separator" }, - "users": "users" + "users": "users", + "mega_private": { + "title": "Mega Private Section", + "private": true + } } diff --git a/pages/api_reference/mega_private/_meta.json b/pages/api_reference/mega_private/_meta.json new file mode 100644 index 0000000..33da045 --- /dev/null +++ b/pages/api_reference/mega_private/_meta.json @@ -0,0 +1,4 @@ +{ + "hello": "Hello page" +} + \ No newline at end of file diff --git a/pages/api_reference/mega_private/hello.mdx b/pages/api_reference/mega_private/hello.mdx new file mode 100644 index 0000000..ecf33bc --- /dev/null +++ b/pages/api_reference/mega_private/hello.mdx @@ -0,0 +1,3 @@ +# Hey there! + +This is super private, so you can't read it! \ No newline at end of file diff --git a/pages/index.mdx b/pages/index.mdx index f527fba..aa19993 100644 --- a/pages/index.mdx +++ b/pages/index.mdx @@ -1,7 +1,39 @@ +import { auth } from "@/auth.ts" +import { useData } from 'nextra/data' +import Link from 'next/link' +import { signOut } from "next-auth/react" +import { LoginOrUserInfo } from "@/components/LoginOrUserInfo" + +export async function getServerSideProps(ctx) { + const session = await auth(ctx) + +return { + props: { + // We add an `ssg` field to the page props, + // which will be provided to the Nextra `useData` hook. + ssg: { + session + } + } + } +} + +export const Info = () => { + // Get the data from SSG, and render it as a component. + const { session } = useData() + return +} + # Welcome to Nextra Documentation Welcome to the Nextra documentation site! Nextra is a modern static site generator optimized for creating high-quality documentation websites with ease. This documentation will guide you through the setup, features, and best practices for using Nextra. +--- + + + +--- + ## Getting Started To get started with Nextra, check out the [About](about) page to learn more about its capabilities and features. If you need any assistance, visit our [Contact](contact) page to find out how to reach us. @@ -12,3 +44,5 @@ Explore the sections below to dive deeper into specific topics: - [Contact Us](contact) We hope you find Nextra useful for your documentation needs! + + diff --git a/tsconfig.json b/tsconfig.json index 1175064..aff8218 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,6 +24,7 @@ }, "include": [ "next-env.d.ts", + "*/**/*.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", From 1e1c157e507cb3a1f0b801a0f0da907584a94192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 20 Jun 2024 15:20:43 +0400 Subject: [PATCH 11/75] feat: Adding documentation of authentication (missing `generateMiddleware` still). --- .vscode/launch.json | 28 ++ README.md | 496 +++++++++++++++++++++++++++ auth.ts | 78 ++++- components/LoginOrUserInfo/index.tsx | 7 +- middleware.ts | 51 ++- 5 files changed, 652 insertions(+), 8 deletions(-) create mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..4bf1534 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Next.js: debug server-side", + "type": "node-terminal", + "request": "launch", + "command": "pnpm run dev" + }, + { + "name": "Next.js: debug client-side", + "type": "chrome", + "request": "launch", + "url": "http://localhost:3000" + }, + { + "name": "Next.js: debug full stack", + "type": "node-terminal", + "request": "launch", + "command": "pnpm run dev", + "serverReadyAction": { + "pattern": "- Local:.+(https?://.+)", + "uriFormat": "%s", + "action": "debugWithChrome" + } + } + ] + } \ No newline at end of file diff --git a/README.md b/README.md index e95b5cb..72d5a58 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,14 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [1.2 Adding items to the navbar](#12-adding-items-to-the-navbar) - [2. Adding authentication](#2-adding-authentication) - [2.1 Adding Github provider](#21-adding-github-provider) + - [2.2 Letting people `Sign In` and `Sign Out`](#22-letting-people-sign-in-and-sign-out) + - [3. Protecting routes](#3-protecting-routes) + - [3.1 A word about `middleware.ts`](#31-a-word-about-middlewarets) + - [3.2 Adding `middleware.ts` logic](#32-adding-middlewarets-logic) + - [3.3 Configuring `auth.ts`](#33-configuring-authts) + - [4. Generating private routes](#4-generating-private-routes) +- [Change theme](#change-theme) +- [zones](#zones) # Why? @@ -663,6 +671,494 @@ And that's all the configuration we need! Now it's time to authenticate people into our app! +### 2.2 Letting people `Sign In` and `Sign Out` +With all the configuration out of the way, +it's time to a way for people to **sign in** and **sign out** of our Nextra website. +Before continuing, +let's change our site's structure a little bit. +Make it like so. +``` +pages +|_ reference_api // yes, change from 'api_reference' to 'reference_api' + |_ mega_private // add this new folder + |_ _meta.json + |_ hello.mdx + |_ _meta.json + |_ about.mdx + |_ users.mdx +|_ _meta.json +|_ about.mdx +|_ api_reference.mdx +|_ contact.mdx +|_ index.mdx +``` + +> [!IMPORTANT] +> +> Change the root `_meta.json` file pertaining to `"api_reference"` +> to `"reference_api"`, and the folder as well. +> +> This is important because we are going to have a middleware +> that is going to match routes to perform authorization checks. +> `Next.js` projects usually have APIs under `/api`, +> which means the middleware was not going to perform verifications on anything +> under `api`. + +Create a new folder `mega_private` inside `api_reference`. +We'll use this later. +You can write whatever you want in it. +Keep the `_meta.json` inside `mega_private` simple, like so. + +```json +{ + "hello": "Hello page" +} +``` + +Great! + +`next-auth` provides a set of built-in pages +for people to go through their authentication journey +(sign in, sign up, sign out, error, etc...). +[Although you can customize your own pages](https://authjs.dev/guides/pages/signin), +we are going to leverage these built-in pages +to keep the tutorial simple. + +To allow people to sign in, +let's create a component to be shown in `pages/index.mdx`, +the root page of the site. + +For this, create a folder called `components` on the root of the project. +Inside of `components`, create `LoginOrUserInfo`, +and inside this one create a file called `index.ts` (`components/LoginOrUserInfo/index.tsx`). + +```ts +import { signOut, signIn } from "next-auth/react"; +import { Session } from "next-auth"; + +export function LoginOrUserInfo({ session } : Readonly<{session: Session}>) { + if (session?.user) { + return ( +
+ + Welcome {session.user.name} + {" "} +
+ +
+ ); + } else { + return ; + } +} +``` + +We are exporting a function `LoginOrUserInfo` +that receives `Session` object (from `next-auth`). +Inside this component, what we do is really simple: +show his name and a `SignOut` button if they are logged in; +otherwise, show a button to `SignIn`. + +We are leveraging both `signIn` and `signOut` functions from `next-auth`. + +> [!WARNING] +> +> By creating these nested folders, +> we have to update the `tsconfig.json` file to encompass +> files that are nested on more than two levels. +> +> ```json +> "include": [ +> "next-env.d.ts", +> "*/**/*.ts", // add this line +> "**/*.ts", +> "**/*.tsx", +> ".next/types/**/*.ts", +> "app/lib/placeholder-data.js", +> "scripts/seed.js" +> ], +> ``` + +Now let's use our newly created component. +Go to `pages/index.mdx` and add the following code to the top. + +```mdx +import { auth } from "@/auth.ts" +import { useData } from 'nextra/data' +import Link from 'next/link' +import { signOut } from "next-auth/react" +import { LoginOrUserInfo } from "@/components/LoginOrUserInfo" + +export async function getServerSideProps(ctx) { + const session = await auth(ctx) + +return { + props: { + // We add an `ssg` field to the page props, + // which will be provided to the Nextra `useData` hook. + ssg: { + session + } + } + } +} + +export const Info = () => { + // Get the data from SSG, and render it as a component. + const { session } = useData() + return +``` + +We are using [`getServerSideProps` ](https://nextjs.org/docs/pages/building-your-application/data-fetching/get-server-side-props) +to fetch the session from the `auth` function from `next-auth`. +For more information about this inside `Nextra`, +visit https://nextra.site/docs/guide/ssg. + +We need to return the session inside an object `props` +and adding a named property called `ssg` +with the data we want to send over the components we want to display. +`Nextra` retrieves this data using the `useData()` hook. + +In the `Info` component, we fetch the `session` object +from the `auth` and pass it to the component +we've created ``. + +All that's left is using this component in our `.mdx` file. +Simply add `` (the component we've created inside `.mdx`) +wherever you want in the page1 + +If you run the application, you should be able to sign in and sign out! + +

+ + + +

+ +We now have access to [`JWT` tokens](https://jwt.io/introduction) in our application, +where `GitHub`'s `OAuth` provider is providing them for us. + +Now let's start using it to start protecting routes! + + +## 3. Protecting routes + +We now have a basic authentication flow in our site, +with `GitHub` providing and managing the tokens for our application for us. +It's in our interest to restrict certain routes to specific users +with specific roles if we ever want to make our awesome documentation site +*available to different clients*. + + +### 3.1 A word about `middleware.ts` + +Normally, when developing applications that follow the normal +`Frontend -> Backend -> Database` convention, +you usually want to have security measures +**as close to the data as possible**. + +[With `React Server Components` being introduced in `Next.js`](https://nextjs.org/docs/app/building-your-application/rendering/server-components), +the line between server and client gets blurred. +Data handling is paramount in understanding where information is processed +and subsequently made available. +So we always have to be careful to know +how authentication and how protecting routes is implemented +and *where* it is processed, +so it's not subject to malicious actors. + + +> [!NOTE] +> +> To learn more about Data Access Layers, +> please visit https://x.com/delba_oliveira/status/1800921612105011284 +> and https://nextjs.org/blog/security-nextjs-server-components-actions. +> These links provide great insights on how to implement a Data Access Layer +> to better encapsulate your data and minimize security pitfalls. + +For this purpose, +because `Nextra` statically generates pages, +we are going to be using [**`middleware`**](https://nextjs.org/docs/pages/building-your-application/routing/middleware) +to protect the routes. +[`next-auth`](https://authjs.dev/getting-started/session-management/protecting?framework=express#api-routes) +warns people to +**on middleware exclusively for authorization and to always ensure that the session is verified as close to your data fetching as possible.** +While that is true +(and a reiteration of what was aforementioned), +protecting the routes in our application +through `middleware` +is optimistically secure enough +(as it runs on the server-side), +as it runs on every request, +including prefetched routes. +Additionally, [`Next.js` recommends doing so](https://nextjs.org/docs/pages/building-your-application/authentication#protecting-routes-with-middleware). + +> "This is important for keeping areas like the user dashboard protected while having other pages like marketing pages be public. +> It's recommended to apply Middleware across all routes and specify exclusions for public access. + + +### 3.2 Adding `middleware.ts` logic + +As per `Next.js`'s convention, +to add this middleware, +we need to create a `middleware.ts` file at the root of the project. + +Create it and add the following code to it: + +```ts +// middleware.ts + +"server only"; + +import { auth } from "@/auth"; +import { NextResponse } from "next/server"; + +// !!!! DO NOT CHANGE THE NAME OF THE VARIABLE !!!! +const privateRoutesMap: any = {}; + +export default auth(async (req, ctx) => { + const currentPath = req.nextUrl.pathname; + const basePath = req.nextUrl.basePath; + const isProtectedRoute = currentPath in privateRoutesMap + + if(isProtectedRoute) { + // Check for valid session + const session = req.auth + + // Redirect unauthed users + if(!session?.user || !session.user.role) { + return NextResponse.redirect(new URL('/api/auth/signin', req.nextUrl)) + } + + // Redirect users that don't have the necessary roles + const neededRolesForPath = privateRoutesMap[currentPath] + if(!(session.user.role && session.user.role in neededRolesForPath)) { + return NextResponse.redirect(new URL('/api/auth/signin', req.nextUrl)) + } + } + + return NextResponse.next() +}); + +export const config = { + matcher: [ + /* + * Match all request paths except for the ones starting with: + * - api (API routes) + * - _next/static (static files) + * - _next/image (image optimization files) + * - favicon.ico (favicon file) + */ + '/((?!api|_next/static|_next/image|favicon.ico).*)', + ], +} + +``` + +Let's break down what we just wrote: + +- **`privateRoutesMap`** is an object/map that will have the **path** as `key` +and the **array of roles needed to access the path** as `value`. +This variable will be changed on build-time, +so do not change its name! +- we export **`auth`** as default from `middleware.ts`. +This function is called before every route server-side. +Inside it, we check the path and the session cookie. +With these, we can know *if the route is protected* or not. +If it is, we check if the person can access it with the given role. +If any of these conditions fail, +the person is redirected to the Sign In page. +- we also export a **`config`** object, +with a `matcher` property. +We use [`RegEx`](https://regexr.com/) to configure which paths we want the middleware to run on. + +> [!NOTE] +> +> Your `Typescript` compiler may be complaining +> because `role` is not a property inside `user`. +> Don't worry, we'll fix this now. + + +### 3.3 Configuring `auth.ts` + +`middleware.ts` assumes the `JWT` token to have a role +in order to do role-based authorization. +For it to have access to it +(and throughout the whole application), +we ought to head over to `auth.ts` +and do additional configuration. + +Open `auth.ts` and change it the following. + +```ts +// auth.ts + +export const { handlers, signIn, signOut, auth } = NextAuth({ + providers: [ + GitHub({ + profile(profile) { + // GitHub's OAuth apps don't allow you to define roles. + // So `profile` here doesn't have a `role` property. + // But on other providers, you'd add the role here through it. + return { + id: profile.id.toString(), + name: profile.name ?? profile.login, + email: profile.email, + image: profile.avatar_url, + role: "user", + }; + }, + }), + ], + callbacks: { + jwt({ token, user, account, profile }) { + // Normally, it would be like this + // if(user) return {...token, role: token.role} + + // But because Github's provider is not passing the role + // (it should, according to https://authjs.dev/guides/role-based-access-control#with-jwt - + // maybe it's because v5 is still in beta), we're just gonna append it every time + return token + }, + session({ session, token }) { + session.user.role = token.role; + return session; + }, + }, +}); +``` + +As usual, let's break it down! + +- the `GitHub` provider accepts a **`profile()`** callback. +In this callback, we receive a `Profile` returned by the `OAuth` provider +(in our case, it's `GitHub`). +We can return a subset using the profile's information +to **define user's information in our application**. +By default, it returns the +`id`, `email`, `name`, `image`, +but we can add more. +That's what we did, by adding the **`role`** property. + +> [!NOTE] +> +> If you're using a custom provider, +> it is your responsibility to return the role so you can capture it in +> your `Next.js`/`Nextra` application. + +- we defined **`callbacks`** to add the role to our `JWT` tokens +and `session` cookies. +In order, the `jwt` callback receives the user information we've defined earlier. +We append the `role` to the token. +Afterwards, the `session` callback is invoked, +where we use the `role` property we've just appended to the `token` +and add it to the `session` cookie. + +> [!NOTE] +> +> In our code, we hardcode it every time. +> It is because, at the time of writing, +> `next-auth` is releasing a `v5`, +> which has some bugs, +> including the `GitHub` provider not properly downstreaming the user +> to the `jwt` and `session` callbacks. +> They receive the `user` as `undefined`. +> +> Unfortunately, this not an isolated occurrence. +> https://stackoverflow.com/questions/76986309/nextauth-nextjs-13-unable-to-add-user-role +> describes our exact scenario +> and doesn't have an answer 😕. +> +> Here are a few more examples. +> Hopefully it will be resolved in time: +> - https://github.com/nextauthjs/next-auth/issues/9836 +> - https://github.com/nextauthjs/next-auth/discussions/9609 +> - https://stackoverflow.com/questions/72073321/why-did-user-object-is-undefined-in-nextauth-session-callback +> - https://github.com/nextauthjs/next-auth/discussions/8456 +> +> If you're using a custom provider, +> it seems this is unlikely to happen to you. +> In the links above, +> people found solutions using custom providers +> and not the in-built ones, like we are using in this demo. + +But that's not all! +Because we are effectively +*extending* the properties of the `User`, +we can [**augment it through types**](https://authjs.dev/getting-started/typescript#module-augmentation), +so `Typescript` doesn't complain about `role` +being an undefined property. + +In the same `auth.ts` file, +add the following code at the top. + +```ts +import { } from 'next-auth/adapters'; +import GitHub from "next-auth/providers/github"; +import NextAuth, { type DefaultSession } from "next-auth"; +import { } from "next-auth/jwt"; + +// We need to add the role to the JWT inside `NextAuth` below, so the `middleware.ts` can have access to it. +// The problem is that it wasn't added this `role` custom field, even if we defined it in `auth.ts`. +// Apparently, the problem is with the types of `next-auth`, which we need to redefine. +// See https://stackoverflow.com/questions/74425533/property-role-does-not-exist-on-type-user-adapteruser-in-nextauth +// and see https://authjs.dev/getting-started/typescript#module-augmentation. + +declare module "next-auth" { + interface Session extends DefaultSession { + /** + * By default, TypeScript merges new interface properties and overwrites existing ones. + * In this case, the default session user properties will be overwritten, + * with the new ones defined above. To keep the default session user properties, + * we need to add them back into the newly declared interface. + */ + user: DefaultSession["user"] & { + role?: string; + }; + } + + interface User { + // Additional properties here: + role?: string; + } +} + +declare module "next-auth/adapters" { + interface AdapterUser { + // Additional properties here: + role?: string; + } +} + +declare module "next-auth/jwt" { + interface JWT { + role?: string; + } +} +``` + +And that's it! 🎉 +Give yourself a pat on the back! + +Now that we have the authentication and authorization set up, +it's time to *finally use it*. + + +## 4. Generating private routes + + + +- adding jwt refresh token https://authjs.dev/guides/refresh-token-rotation + + + + +# Change theme + +- custom theme is the only option +- although yuyou can change some aspects of the sidebar (https://nextra.site/docs/docs-theme/theme-configuration#customize-sidebar-content), you can't do it on the navbar (https://github.com/shuding/nextra/discussions/2799). Either way, the way Nextra does it doesn't allow us to have access to the authorization and change the display accordingly. We need to go deeper. + +# zones +https://github.com/shuding/nextra/discussions/93 \ No newline at end of file diff --git a/auth.ts b/auth.ts index b4c6e16..3b01d34 100644 --- a/auth.ts +++ b/auth.ts @@ -1,6 +1,78 @@ -import NextAuth from "next-auth"; -import GitHub from "next-auth/providers/github" +import { } from 'next-auth/adapters'; +import GitHub from "next-auth/providers/github"; +import NextAuth, { type DefaultSession } from "next-auth"; +import { } from "next-auth/jwt"; + +// We need to add the role to the JWT inside `NextAuth` below, so the `middleware.ts` can have access to it. +// The problem is that it wasn't added this `role` custom field, even if we defined it in `auth.ts`. +// Apparently, the problem is with the types of `next-auth`, which we need to redefine. +// See https://stackoverflow.com/questions/74425533/property-role-does-not-exist-on-type-user-adapteruser-in-nextauth +// and see https://authjs.dev/getting-started/typescript#module-augmentation. + +declare module "next-auth" { + interface Session extends DefaultSession { + /** + * By default, TypeScript merges new interface properties and overwrites existing ones. + * In this case, the default session user properties will be overwritten, + * with the new ones defined above. To keep the default session user properties, + * we need to add them back into the newly declared interface. + */ + user: DefaultSession["user"] & { + role?: string; + }; + } + + interface User { + // Additional properties here: + role?: string; + } +} + +declare module "next-auth/adapters" { + interface AdapterUser { + // Additional properties here: + role?: string; + } +} + +declare module "next-auth/jwt" { + interface JWT { + role?: string; + } +} + +// ---------- export const { handlers, signIn, signOut, auth } = NextAuth({ - providers: [GitHub], + providers: [ + GitHub({ + profile(profile) { + // GitHub's OAuth apps don't allow you to define roles. + // So `profile` here doesn't have a `role` property. + // But on other providers, you'd add the role here through it. + return { + id: profile.id.toString(), + name: profile.name ?? profile.login, + email: profile.email, + image: profile.avatar_url, + role: "user", + }; + }, + }), + ], + callbacks: { + jwt({ token, user, account, profile }) { + // Normally, it would be like this + // if(user) return {...token, role: token.role} + + // But because Github's provider is not passing the role + // (it should, according to https://authjs.dev/guides/role-based-access-control#with-jwt - + // maybe it's because v5 is still in beta), we're just gonna append it every time + return token + }, + session({ session, token }) { + session.user.role = token.role; + return session; + }, + }, }); diff --git a/components/LoginOrUserInfo/index.tsx b/components/LoginOrUserInfo/index.tsx index b291398..98f6594 100644 --- a/components/LoginOrUserInfo/index.tsx +++ b/components/LoginOrUserInfo/index.tsx @@ -1,5 +1,4 @@ -import Link from "next/link"; -import { signOut } from "next-auth/react"; +import { signOut, signIn } from "next-auth/react"; import { Session } from "next-auth"; export function LoginOrUserInfo({ session } : Readonly<{session: Session}>) { @@ -10,10 +9,10 @@ export function LoginOrUserInfo({ session } : Readonly<{session: Session}>) { Welcome {session.user.name} {" "}
- + ); } else { - return LOGIN; + return ; } } diff --git a/middleware.ts b/middleware.ts index 2df914b..1a173bc 100644 --- a/middleware.ts +++ b/middleware.ts @@ -1 +1,50 @@ -export { auth as middleware } from "@/auth" \ No newline at end of file +"server only"; + +import { auth } from "@/auth"; +import { NextResponse } from "next/server"; + +// !!!! DO NOT CHANGE THE NAME OF THE VARIABLE !!!! +// It is manipulated before the project is compiled so it knows all the routes that are private +// according to what is defined in "_meta.json" files. +// See `package.json` and the `private-route-gen` script for context. +const privateRoutesMap: any = {"/reference_api":["user"],"/reference_api/mega_private":["cant_enter"]}; + +export default auth(async (req, ctx) => { + const currentPath = req.nextUrl.pathname; + const basePath = req.nextUrl.basePath; + const isProtectedRoute = currentPath in privateRoutesMap + + if(isProtectedRoute) { + // Check for valid session + const session = req.auth + + // Redirect unauthed users + if(!session?.user || !session.user.role) { + return NextResponse.redirect(new URL('/api/auth/signin', req.nextUrl)) + } + + // Redirect users that don't have the necessary roles + const neededRolesForPath = privateRoutesMap[currentPath] + if(!(session.user.role && session.user.role in neededRolesForPath)) { + return NextResponse.redirect(new URL('/api/auth/signin', req.nextUrl)) + } + } + + return NextResponse.next() + + + +}); + +export const config = { + matcher: [ + /* + * Match all request paths except for the ones starting with: + * - api (API routes) + * - _next/static (static files) + * - _next/image (image optimization files) + * - favicon.ico (favicon file) + */ + '/((?!api|_next/static|_next/image|favicon.ico).*)', + ], +} From cf1d82df384af1cc48528d9e76457137a421734f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 20 Jun 2024 15:21:07 +0400 Subject: [PATCH 12/75] chore: Renaming `api_reference` to `reference_api`. --- pages/_meta.json | 4 ++-- pages/{api_reference => reference_api}/_meta.json | 5 ++++- pages/{api_reference => reference_api}/about.mdx | 0 .../{api_reference => reference_api}/mega_private/_meta.json | 0 .../{api_reference => reference_api}/mega_private/hello.mdx | 0 pages/{api_reference => reference_api}/users.mdx | 0 6 files changed, 6 insertions(+), 3 deletions(-) rename pages/{api_reference => reference_api}/_meta.json (65%) rename pages/{api_reference => reference_api}/about.mdx (100%) rename pages/{api_reference => reference_api}/mega_private/_meta.json (100%) rename pages/{api_reference => reference_api}/mega_private/hello.mdx (100%) rename pages/{api_reference => reference_api}/users.mdx (100%) diff --git a/pages/_meta.json b/pages/_meta.json index 60a29eb..8e2a71d 100644 --- a/pages/_meta.json +++ b/pages/_meta.json @@ -4,12 +4,12 @@ "type": "page", "display": "hidden" }, - "api_reference": { + "reference_api": { "title": "API Reference", "type": "page", "private": { "private": true, - "roles": ["role1", "role2"] + "roles": ["user"] } }, "about": { diff --git a/pages/api_reference/_meta.json b/pages/reference_api/_meta.json similarity index 65% rename from pages/api_reference/_meta.json rename to pages/reference_api/_meta.json index 5db147b..b04afbe 100644 --- a/pages/api_reference/_meta.json +++ b/pages/reference_api/_meta.json @@ -6,6 +6,9 @@ "users": "users", "mega_private": { "title": "Mega Private Section", - "private": true + "private": { + "private": true, + "roles": ["cant_enter"] + } } } diff --git a/pages/api_reference/about.mdx b/pages/reference_api/about.mdx similarity index 100% rename from pages/api_reference/about.mdx rename to pages/reference_api/about.mdx diff --git a/pages/api_reference/mega_private/_meta.json b/pages/reference_api/mega_private/_meta.json similarity index 100% rename from pages/api_reference/mega_private/_meta.json rename to pages/reference_api/mega_private/_meta.json diff --git a/pages/api_reference/mega_private/hello.mdx b/pages/reference_api/mega_private/hello.mdx similarity index 100% rename from pages/api_reference/mega_private/hello.mdx rename to pages/reference_api/mega_private/hello.mdx diff --git a/pages/api_reference/users.mdx b/pages/reference_api/users.mdx similarity index 100% rename from pages/api_reference/users.mdx rename to pages/reference_api/users.mdx From 7276c8956672bae28efe330306b387bb50ad158a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 09:18:31 +0400 Subject: [PATCH 13/75] fix: Fixing generate private routes script. --- generateMiddleware.ts | 54 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/generateMiddleware.ts b/generateMiddleware.ts index 7544073..036efcd 100644 --- a/generateMiddleware.ts +++ b/generateMiddleware.ts @@ -20,6 +20,7 @@ type PrivateRoutes = { /** * This function looks at the file system under a path and goes through each `_meta.json` looking for private roots recursively. * It is expecting the `_meta.json` values of keys to have a property called "private" to consider the route as private for specific roles. + * If a parent is private, all the children are private as well. The roles **are not propagated to the children**. * @param pagesDir path to recursively look for. * @returns map of private routes as key and array of roles that are permitted to access the route. */ @@ -29,33 +30,64 @@ function getPrivateRoutes(pagesDir: string): PrivateRoutes { // Find all _meta.json files recursively const metaFiles = globSync(path.join(pagesDir, "**/_meta.json")); + // Variable to keep track if parent is private on nested routes and its role + const rootPrivateSettings: { [key: string]: { private: boolean, roles: string[] } } = {}; + // Iterate over the found meta files for (const file of metaFiles) { // Get the path of file and read it const dir = path.dirname(file); const metaJson: MetaJson = JSON.parse(fs.readFileSync(file, "utf-8")); - // Iterate over the key/value pairs + // Iterate over the key/value pairs of the "_meta.json" file for (const [key, meta] of Object.entries(metaJson)) { - // Check if the current meta has a private property + const route = path.join(dir, key) + .replace(pagesDir, '').replace(/\\/g, '/'); + + // Check if the current meta has a "private" property if (meta.private !== undefined) { - if (typeof meta.private === "boolean") { - // If private is a boolean, directly use it + if (typeof meta.private === 'boolean') { if (meta.private) { - const route = path.join(dir, key).replace(pagesDir, "").replace(/\\/g, "/"); - privateRoutes[route] = []; + privateRoutes[route] = [] + rootPrivateSettings[dir] = { private: true, roles: [] }; } + } + // If the "private" property is an object with possible roles + else if (meta.private.private === true) { + const roles = meta.private.roles ? meta.private.roles : []; + privateRoutes[route] = roles + rootPrivateSettings[dir] = { private: true, roles: roles }; } - // If private is an object with private true and roles array (which can be omitted) - else if (meta.private.private) { - const route = path.join(dir, key).replace(pagesDir, "").replace(/\\/g, "/"); - privateRoutes[route] = meta.private.roles || []; + } else { + // Check if the parent folder is private and inherit roles + const parentDir = path.resolve(dir, '..'); + if (rootPrivateSettings[parentDir] && rootPrivateSettings[parentDir].private) { + const parentRoles = rootPrivateSettings[parentDir].roles; + privateRoutes[route] = parentRoles; } - // Do nothing if private is an object with private false or without roles array } } } + + // Now let's just do a second pass to clean-up possible unwanted/invalid routes + for (const route of Object.keys(privateRoutes)) { + const fullPath = path.join(pagesDir, route); + const lastSegment = route.split('/').pop(); + + // Remove separators or any route that doesn't correspond to an existing file/directory + if (lastSegment === '---') { + delete privateRoutes[route]; + continue; + } + + // Check for the existence of .mdx file + const mdxPath = `${fullPath}.mdx`; + if (!fs.existsSync(fullPath) && !fs.existsSync(mdxPath)) { + delete privateRoutes[route]; + } + } + return privateRoutes; } From f498a589d19cc07cd261824da2a397afd309ac53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 11:24:09 +0400 Subject: [PATCH 14/75] feat: Adding script to generate routes and documenting it. --- README.md | 354 +++++++++++++++++- auth.ts | 7 +- ...eMiddleware.ts => generatePrivateRoutes.ts | 26 +- middleware.ts | 5 +- package.json | 2 +- pages/reference_api/mega_private.mdx | 3 + 6 files changed, 368 insertions(+), 29 deletions(-) rename generateMiddleware.ts => generatePrivateRoutes.ts (87%) create mode 100644 pages/reference_api/mega_private.mdx diff --git a/README.md b/README.md index 72d5a58..282baeb 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,12 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [3.2 Adding `middleware.ts` logic](#32-adding-middlewarets-logic) - [3.3 Configuring `auth.ts`](#33-configuring-authts) - [4. Generating private routes](#4-generating-private-routes) + - [4.1 Installing `ts-morph` and setup](#41-installing-ts-morph-and-setup) + - [4.2 Creating `generatePrivateRoutes.ts`](#42-creating-generateprivateroutests) + - [4.3 Implementing private route retrieval function](#43-implementing-private-route-retrieval-function) + - [4.3.1 Defining `_meta.json` files with `private` properties](#431-defining-_metajson-files-with-private-properties) + - [4.3.2 Implementing the function](#432-implementing-the-function) + - [4.4 Running the script before building](#44-running-the-script-before-building) - [Change theme](#change-theme) - [zones](#zones) @@ -688,6 +694,7 @@ pages |_ hello.mdx |_ _meta.json |_ about.mdx + |_ mega_private.mdx // This is the index page of `mega_private` that will show on the sidebar. Write whatever. |_ users.mdx |_ _meta.json |_ about.mdx @@ -920,7 +927,6 @@ const privateRoutesMap: any = {}; export default auth(async (req, ctx) => { const currentPath = req.nextUrl.pathname; - const basePath = req.nextUrl.basePath; const isProtectedRoute = currentPath in privateRoutesMap if(isProtectedRoute) { @@ -934,7 +940,7 @@ export default auth(async (req, ctx) => { // Redirect users that don't have the necessary roles const neededRolesForPath = privateRoutesMap[currentPath] - if(!(session.user.role && session.user.role in neededRolesForPath)) { + if(!(session.user.role && neededRolesForPath.includes(session.user.role))) { return NextResponse.redirect(new URL('/api/auth/signin', req.nextUrl)) } } @@ -987,7 +993,7 @@ We use [`RegEx`](https://regexr.com/) to configure which paths we want the middl in order to do role-based authorization. For it to have access to it (and throughout the whole application), -we ought to head over to `auth.ts` +we ought to head over to `auth.ts` and do additional configuration. Open `auth.ts` and change it the following. @@ -1016,11 +1022,12 @@ export const { handlers, signIn, signOut, auth } = NextAuth({ jwt({ token, user, account, profile }) { // Normally, it would be like this // if(user) return {...token, role: token.role} + // return token // But because Github's provider is not passing the role // (it should, according to https://authjs.dev/guides/role-based-access-control#with-jwt - // maybe it's because v5 is still in beta), we're just gonna append it every time - return token + return {...token, role: "user"} }, session({ session, token }) { session.user.role = token.role; @@ -1084,21 +1091,32 @@ and add it to the `session` cookie. > people found solutions using custom providers > and not the in-built ones, like we are using in this demo. + +> [!IMPORTANT] +> +> To make the experience better for the user, +> we can implement a **refresh token rotation system**, +> where once a token expires, +> the application automatically refreshes it instead of asking the user to sign in again. +> +> Read https://authjs.dev/guides/refresh-token-rotation to implement this with `next-auth`. + But that's not all! Because we are effectively *extending* the properties of the `User`, we can [**augment it through types**](https://authjs.dev/getting-started/typescript#module-augmentation), so `Typescript` doesn't complain about `role` -being an undefined property. +being an `undefined` property. In the same `auth.ts` file, add the following code at the top. ```ts -import { } from 'next-auth/adapters'; import GitHub from "next-auth/providers/github"; import NextAuth, { type DefaultSession } from "next-auth"; -import { } from "next-auth/jwt"; +// we don't use these but we need to import something so we can override the interface +import { DefaultJWT } from "next-auth/jwt"; +import { AdapterSession } from 'next-auth/adapters'; // We need to add the role to the JWT inside `NextAuth` below, so the `middleware.ts` can have access to it. // The problem is that it wasn't added this `role` custom field, even if we defined it in `auth.ts`. @@ -1148,10 +1166,330 @@ it's time to *finally use it*. ## 4. Generating private routes +As you may have noticed by now, +`Nextra` statically generates the page for you +following the structure and the `_meta.json` files +that you define in your project. +These changes are then reflected in your navbar and sidebar. + +However, there is *no way for us to define private routes* +and **use them at build-time**, +like you do when generating the pages with `Nextra`. +Unfortunately, `Nextra` doesn't have this feature in place, +and authentication is not something they had in mind to implement +for a framework that was primarily meant for public-facing documentation. + +*However*, it is possible to do this, +considering what was discussed in +[3.1 A word about `middleware.ts`](#31-a-word-about-middlewarets), +_as long as we have access to the private routes at **build-time**_. + +To accomplish this, we're using [`ts-morph`](https://ts-morph.com/), +a package that will allow us to manipulate Typescript source files. +We will create a script with `ts-morph` that manipulates the `const privateRoutesMap` inside `middleware.ts`. +This script will populate the `const` with all the private routes +and the needed roles to access them. + +Let's crack on! + + +### 4.1 Installing `ts-morph` and setup + +Install `ts-morph`, [`ts-node`](https://www.npmjs.com/package/ts-node) (to run the script we're implementing) +and [`fast-glob`](https://www.npmjs.com/package/fast-glob) +(to traverse the file system). + +```sh +pnpm add ts-morph ts-node fast-glob +``` +After installing these dependencies, +we will have to adjust our `tsconfig.json` file +so we can run our script independently. +Below the `exclude` property, in the last line, +add the following piece of code. -- adding jwt refresh token https://authjs.dev/guides/refresh-token-rotation +```json + "exclude": ["node_modules"], + + // These are only used by `ts-node` to run the script that generates the private routes. + // These options are overrides used only by ts-node, same as the --compilerOptions flag and the TS_NODE_COMPILER_OPTIONS environment variable + "ts-node": { + "compilerOptions": { + "module": "commonjs" + } + }, +``` + +Great! +Let's start implementing our script now. + + +### 4.2 Creating `generatePrivateRoutes.ts` + +In the root of the project, +create a file called `generatePrivateRoutes.ts`. +Add the following code. + +```ts +import { Project } from "ts-morph"; +import path from "path"; +import fs from "fs"; +import { globSync } from "fast-glob"; + +// - - - - - - - - - - - - - - - - - - - - - - - +// `middleware.ts` is changed by executing the code below. + +const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated +const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) + +// Get private routes +const pagesDir = path.join(__dirname, DIRECTORY); +const privateRoutes = getPrivateRoutes(pagesDir); + +// Initialize the project and source file +const project = new Project(); +const sourceFile = project.addSourceFileAtPath(path.resolve(__dirname, "middleware.ts")); + +// Find the variable to replace and change it's declaration +const variable = sourceFile.getVariableDeclaration(CONST_VARIABLE_NAME); +if (variable) { + variable.setInitializer(JSON.stringify(privateRoutes)); + sourceFile.saveSync(); +} else { + console.error("Variable not found in `middleware.ts`. File wasn't changed."); +} +``` + +The code is fairly simple. +We get the private routes by calling a function called `getPrivateRoutes()` +(which we will implement shortly). +Then, we find the `middleware.ts` file +and find the variable we want to change. +If we do find it, we change its initialization +to the private routes map we retrieved earlier. +Otherwise, we log an error. + +Now, it's time to add the function +that will *retrieve the private routes*! + + +### 4.3 Implementing private route retrieval function + +Our function `getPrivateRoutes` will need to recursively iterate +over a given folder directory and find a way to know which routes are private. +As of now, there's no way of doing so. + +That's why we're going +**to define a new property inside `_meta.json` files**. + + +#### 4.3.1 Defining `_meta.json` files with `private` properties + +We need to tell our function which pages/routes are private. +To do this, we are going to use the `_meta.json` files +that come with `Nextra`. + +To achieve this, +we are going to allow people to declare a route as private +by adding a **`private`** property to a route defined in the respective `_meta.json`. + +```json +// pages/_meta.json +{ + "index": { + "title": "Homepage", + "type": "page", + "display": "hidden" + }, + "reference_api": { + "title": "API Reference", + "type": "page", + "private": { // We add this property to make `reference_api` private + "private": true, + "roles": ["user"] + } + }, + "about": { + "title": "About Us", + "type": "page" + }, + "contact": { + "title": "Contact Us", + "type": "page" + }, + "github_link": { + "title": "Github", + "href": "https://github.com/shuding/nextra", + "newWindow": true, + "display": "hidden" + } +} +``` + +As you can see, we've added a property called **`private`** +to the `reference_api` route, +where we define if it's private or not by boolean in the `private` property +and where we define the roles that can access it +in the `roles` property. + +Alternatively, people can define private routes by simply +passing `"private": true`, instead of passing an object. +In these cases, the `roles` empty will default to an empty array, + +```json + "reference_api": { + "title": "API Reference", + "type": "page", + "private": true // Simpler version + }, +``` + +We'll take into account both of these scenarios. + + +#### 4.3.2 Implementing the function + +Okay, now let's start coding our function! +Inside `generatePrivateRoutes.ts`, +add this function above the `ts-morph` code +we've written earlier. + +```ts +// Types for the `_meta.json` structure +type PrivateInfo = { + private: boolean; + roles?: string[]; +}; + +type MetaJson = { + [key: string]: string | any | PrivateInfo; +}; + +type PrivateRoutes = { + [key: string]: string[]; +}; + +/** + * This function looks at the file system under a path and goes through each `_meta.json` looking for private routes recursively. + * It is expecting the `_meta.json` values of keys to have a property called "private" to consider the route as private for specific roles. + * If a parent is private, all the children are private as well. The children inherit the roles of their direct parent. + * @param pagesDir path to recursively look for. + * @returns map of private routes as key and array of roles that are permitted to access the route. + */ +function getPrivateRoutes(pagesDir: string): PrivateRoutes { + let privateRoutes: PrivateRoutes = {}; + + // Find all _meta.json files recursively + const metaFiles = globSync(path.join(pagesDir, "**/_meta.json")); + + // Variable to keep track if parent is private on nested routes and its role + const rootPrivateSettings: { [key: string]: { private: boolean; roles: string[] } } = {}; + + // Iterate over the found meta files + for (const file of metaFiles) { + // Get the path of file and read it + const dir = path.dirname(file); + const metaJson: MetaJson = JSON.parse(fs.readFileSync(file, "utf-8")); + + // Iterate over the key/value pairs of the "_meta.json" file + for (const [key, meta] of Object.entries(metaJson)) { + const route = path.join(dir, key).replace(pagesDir, "").replace(/\\/g, "/"); + + // Check if the current meta has a "private" property + if (meta.private !== undefined) { + if (typeof meta.private === "boolean") { + if (meta.private) { + privateRoutes[route] = []; + rootPrivateSettings[dir] = { private: true, roles: [] }; + } + } + // If the "private" property is an object with possible roles + else if (meta.private.private === true) { + const roles = meta.private.roles ? meta.private.roles : []; + privateRoutes[route] = roles; + rootPrivateSettings[dir] = { private: true, roles: roles }; + } + } else { + // Check if the parent folder is private and inherit roles + const parentDir = path.resolve(dir, ".."); + if (rootPrivateSettings[parentDir] && rootPrivateSettings[parentDir].private) { + const parentRoles = rootPrivateSettings[parentDir].roles; + privateRoutes[route] = parentRoles; + } + } + } + } + + // Now let's just do a second pass to clean-up possible unwanted/invalid routes + for (const route of Object.keys(privateRoutes)) { + const fullPath = path.join(pagesDir, route); + const lastSegment = route.split("/").pop(); + + // Remove separators or any route that doesn't correspond to an existing file/directory + if (lastSegment === "---") { + delete privateRoutes[route]; + continue; + } + + // Check for the existence of .mdx file + const mdxPath = `${fullPath}.mdx`; + if (!fs.existsSync(fullPath) && !fs.existsSync(mdxPath)) { + delete privateRoutes[route]; + } + } + + return privateRoutes; +} +``` + +Whoa, that's a lot! +The code is fairly documented so you can follow along easier. +But the gist of it is: +- we use `fast-glob` to find all the `_meta.json` files recursively. +- we iterate over the `_meta.json` files. + - in each `_meta.json`, we look over the key-value pairs to construct the route. + - in each key-value, we check for the `private` property and resolve its boolean. + - while iterating, we keep track of the routes and check if the parent is also private. If the parent is private, the child must be private too. It also inherits the direct parent's roles. +- after iteration, we do a second pass to clean-up possible invalid routes. +- we return a map of `private route` as **key** and `roles array` as **value**. + +And that's it! + + +### 4.4 Running the script before building + +Now that we have our handy-dandy script ready, +we need to make sure it always gets executed before running our application, +whether it is being built for production +or compiling to be running on `localhost`. + +To do this, we only need to change our `package.json` file. +Head over there and change the scripts, like so: + +```json + "scripts": { + "private-route-gen": "ts-node generatePrivateRoutes.ts", + "dev": "npm run private-route-gen && next", + "prebuild": "npm run private-route-gen", + "build": "next build", + "start": "next start" + }, +``` + +We've created a `private-route-gen` +that uses `ts-node` to run our script. +This newly added script is executed +when running `pnpm run dev` (running the app locally) +and `pnpm run build`. +[We've added it to the `prebuild` script](https://kontent.ai/blog/how-to-run-scripts-before-every-build-on-next-js/) +so it executes before production builds. + +And that's it! +Now every time you run your application, +we are sure that the private routes are correctly materialized! +Hurray! 🎉 diff --git a/auth.ts b/auth.ts index 3b01d34..f79f379 100644 --- a/auth.ts +++ b/auth.ts @@ -1,7 +1,7 @@ -import { } from 'next-auth/adapters'; import GitHub from "next-auth/providers/github"; import NextAuth, { type DefaultSession } from "next-auth"; -import { } from "next-auth/jwt"; +import { DefaultJWT } from "next-auth/jwt"; +import { AdapterSession } from 'next-auth/adapters'; // We need to add the role to the JWT inside `NextAuth` below, so the `middleware.ts` can have access to it. // The problem is that it wasn't added this `role` custom field, even if we defined it in `auth.ts`. @@ -64,11 +64,12 @@ export const { handlers, signIn, signOut, auth } = NextAuth({ jwt({ token, user, account, profile }) { // Normally, it would be like this // if(user) return {...token, role: token.role} + // return token // But because Github's provider is not passing the role // (it should, according to https://authjs.dev/guides/role-based-access-control#with-jwt - // maybe it's because v5 is still in beta), we're just gonna append it every time - return token + return {...token, role: "user"} }, session({ session, token }) { session.user.role = token.role; diff --git a/generateMiddleware.ts b/generatePrivateRoutes.ts similarity index 87% rename from generateMiddleware.ts rename to generatePrivateRoutes.ts index 036efcd..2d9947c 100644 --- a/generateMiddleware.ts +++ b/generatePrivateRoutes.ts @@ -18,9 +18,9 @@ type PrivateRoutes = { }; /** - * This function looks at the file system under a path and goes through each `_meta.json` looking for private roots recursively. + * This function looks at the file system under a path and goes through each `_meta.json` looking for private routes recursively. * It is expecting the `_meta.json` values of keys to have a property called "private" to consider the route as private for specific roles. - * If a parent is private, all the children are private as well. The roles **are not propagated to the children**. + * If a parent is private, all the children are private as well. The children inherit the roles of their direct parent. * @param pagesDir path to recursively look for. * @returns map of private routes as key and array of roles that are permitted to access the route. */ @@ -31,7 +31,7 @@ function getPrivateRoutes(pagesDir: string): PrivateRoutes { const metaFiles = globSync(path.join(pagesDir, "**/_meta.json")); // Variable to keep track if parent is private on nested routes and its role - const rootPrivateSettings: { [key: string]: { private: boolean, roles: string[] } } = {}; + const rootPrivateSettings: { [key: string]: { private: boolean; roles: string[] } } = {}; // Iterate over the found meta files for (const file of metaFiles) { @@ -41,26 +41,25 @@ function getPrivateRoutes(pagesDir: string): PrivateRoutes { // Iterate over the key/value pairs of the "_meta.json" file for (const [key, meta] of Object.entries(metaJson)) { - const route = path.join(dir, key) - .replace(pagesDir, '').replace(/\\/g, '/'); + const route = path.join(dir, key).replace(pagesDir, "").replace(/\\/g, "/"); // Check if the current meta has a "private" property if (meta.private !== undefined) { - if (typeof meta.private === 'boolean') { + if (typeof meta.private === "boolean") { if (meta.private) { - privateRoutes[route] = [] + privateRoutes[route] = []; rootPrivateSettings[dir] = { private: true, roles: [] }; } - } + } // If the "private" property is an object with possible roles else if (meta.private.private === true) { const roles = meta.private.roles ? meta.private.roles : []; - privateRoutes[route] = roles + privateRoutes[route] = roles; rootPrivateSettings[dir] = { private: true, roles: roles }; } } else { // Check if the parent folder is private and inherit roles - const parentDir = path.resolve(dir, '..'); + const parentDir = path.resolve(dir, ".."); if (rootPrivateSettings[parentDir] && rootPrivateSettings[parentDir].private) { const parentRoles = rootPrivateSettings[parentDir].roles; privateRoutes[route] = parentRoles; @@ -69,18 +68,17 @@ function getPrivateRoutes(pagesDir: string): PrivateRoutes { } } - // Now let's just do a second pass to clean-up possible unwanted/invalid routes for (const route of Object.keys(privateRoutes)) { const fullPath = path.join(pagesDir, route); - const lastSegment = route.split('/').pop(); + const lastSegment = route.split("/").pop(); // Remove separators or any route that doesn't correspond to an existing file/directory - if (lastSegment === '---') { + if (lastSegment === "---") { delete privateRoutes[route]; continue; } - + // Check for the existence of .mdx file const mdxPath = `${fullPath}.mdx`; if (!fs.existsSync(fullPath) && !fs.existsSync(mdxPath)) { diff --git a/middleware.ts b/middleware.ts index 1a173bc..6c83918 100644 --- a/middleware.ts +++ b/middleware.ts @@ -7,11 +7,10 @@ import { NextResponse } from "next/server"; // It is manipulated before the project is compiled so it knows all the routes that are private // according to what is defined in "_meta.json" files. // See `package.json` and the `private-route-gen` script for context. -const privateRoutesMap: any = {"/reference_api":["user"],"/reference_api/mega_private":["cant_enter"]}; +const privateRoutesMap: any = {"/reference_api":["user"],"/reference_api/about":["user"],"/reference_api/users":["user"],"/reference_api/mega_private":["cant_enter"],"/reference_api/mega_private/hello":["cant_enter"]}; export default auth(async (req, ctx) => { const currentPath = req.nextUrl.pathname; - const basePath = req.nextUrl.basePath; const isProtectedRoute = currentPath in privateRoutesMap if(isProtectedRoute) { @@ -25,7 +24,7 @@ export default auth(async (req, ctx) => { // Redirect users that don't have the necessary roles const neededRolesForPath = privateRoutesMap[currentPath] - if(!(session.user.role && session.user.role in neededRolesForPath)) { + if(!(session.user.role && neededRolesForPath.includes(session.user.role))) { return NextResponse.redirect(new URL('/api/auth/signin', req.nextUrl)) } } diff --git a/package.json b/package.json index 77f5828..3c33221 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "scripts": { - "private-route-gen": "ts-node generateMiddleware.ts", + "private-route-gen": "ts-node generatePrivateRoutes.ts", "dev": "npm run private-route-gen && next", "prebuild": "npm run private-route-gen", "build": "next build", diff --git a/pages/reference_api/mega_private.mdx b/pages/reference_api/mega_private.mdx new file mode 100644 index 0000000..577d64f --- /dev/null +++ b/pages/reference_api/mega_private.mdx @@ -0,0 +1,3 @@ +# Mega Private Page + +You should never see this page! 🤭 \ No newline at end of file From 11e3d1efbd2570477f6497fece0e61ed95ad56b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 11:57:04 +0400 Subject: [PATCH 15/75] feat: Adding note about error when compiling. --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 282baeb..341c750 100644 --- a/README.md +++ b/README.md @@ -1492,6 +1492,20 @@ we are sure that the private routes are correctly materialized! Hurray! 🎉 +> [!NOTE] +> +> You may get an error when building the project saying: +> +> ``` +> Error validating _meta.json file for "reference_api" property. +> Unrecognized key(s) in object: 'private' +> ``` +> +> This is expected, since `Nextra` doesn't know what the `private` property is. +> This doesn't affect the performance of the application, +> it's simply a warning. + + # Change theme From 5d2537ab9b62f08379e957161f3b6f94e9250879 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 12:23:13 +0400 Subject: [PATCH 16/75] test: Setup Playwright for E2E testing. --- .github/workflows/playwright.yml | 27 ++++++++++ .gitignore | 4 ++ package.json | 1 + playwright.config.ts | 88 ++++++++++++++++++++++++++++++++ pnpm-lock.yaml | 75 ++++++++++++++++++++------- tests/home.spec.ts | 10 ++++ 6 files changed, 187 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/playwright.yml create mode 100644 playwright.config.ts create mode 100644 tests/home.spec.ts diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..9662b54 --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm install -g pnpm && pnpm install + - name: Install Playwright Browsers + run: pnpm exec playwright install --with-deps + - name: Run Playwright tests + run: pnpm exec playwright test + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 30 diff --git a/.gitignore b/.gitignore index c6bba59..3160408 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,7 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/package.json b/package.json index 3c33221..b8691a5 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "react-dom": "^18.3.1" }, "devDependencies": { + "@playwright/test": "^1.44.1", "@types/node": "20.14.5", "fast-glob": "^3.3.2", "ts-morph": "^22.0.0", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..08ac7fa --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,88 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: "http://localhost:3000", + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Run your local dev server before starting the tests */ + webServer: { + command: 'pnpm run dev', + url: 'http://localhost:3000', + reuseExistingServer: !process.env.CI, + stdout: 'ignore', + stderr: 'pipe', + timeout: 120 * 1000, + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 171b948..d785dd2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,16 +10,16 @@ importers: dependencies: next: specifier: ^14.2.4 - version: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-auth: specifier: 5.0.0-beta.19 - version: 5.0.0-beta.19(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 5.0.0-beta.19(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) nextra: specifier: ^2.13.4 - version: 2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nextra-theme-docs: specifier: ^2.13.4 - version: 2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.3.1 version: 18.3.1 @@ -27,6 +27,9 @@ importers: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) devDependencies: + '@playwright/test': + specifier: ^1.44.1 + version: 1.44.1 '@types/node': specifier: 20.14.5 version: 20.14.5 @@ -237,6 +240,11 @@ packages: '@panva/hkdf@1.1.1': resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} + '@playwright/test@1.44.1': + resolution: {integrity: sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==} + engines: {node: '>=16'} + hasBin: true + '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} @@ -730,6 +738,11 @@ packages: focus-visible@5.2.0: resolution: {integrity: sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + get-stream@3.0.0: resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} engines: {node: '>=4'} @@ -1276,6 +1289,16 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + playwright-core@1.44.1: + resolution: {integrity: sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==} + engines: {node: '>=16'} + hasBin: true + + playwright@1.44.1: + resolution: {integrity: sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==} + engines: {node: '>=16'} + hasBin: true + postcss@8.4.31: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} @@ -1785,6 +1808,10 @@ snapshots: '@panva/hkdf@1.1.1': {} + '@playwright/test@1.44.1': + dependencies: + playwright: 1.44.1 + '@popperjs/core@2.11.8': {} '@swc/counter@0.1.3': {} @@ -2282,6 +2309,9 @@ snapshots: focus-visible@5.2.0: {} + fsevents@2.3.2: + optional: true + get-stream@3.0.0: {} git-up@7.0.0: @@ -3033,10 +3063,10 @@ snapshots: nanoid@3.3.7: {} - next-auth@5.0.0-beta.19(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + next-auth@5.0.0-beta.19(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: '@auth/core': 0.32.0 - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 next-mdx-remote@4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): @@ -3050,19 +3080,19 @@ snapshots: transitivePeerDependencies: - supports-color - next-seo@6.5.0(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-seo@6.5.0(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next-themes@0.2.1(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-themes@0.2.1(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.4 '@swc/helpers': 0.5.5 @@ -3083,11 +3113,12 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.4 '@next/swc-win32-ia32-msvc': 14.2.4 '@next/swc-win32-x64-msvc': 14.2.4 + '@playwright/test': 1.44.1 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - nextra-theme-docs@2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextra-theme-docs@2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@popperjs/core': 2.11.8 @@ -3098,16 +3129,16 @@ snapshots: git-url-parse: 13.1.1 intersection-observer: 0.12.2 match-sorter: 6.3.4 - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - next-seo: 6.5.0(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - next-themes: 0.2.1(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - nextra: 2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-seo: 6.5.0(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-themes: 0.2.1(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + nextra: 2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) scroll-into-view-if-needed: 3.1.0 zod: 3.23.8 - nextra@2.13.4(next@14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextra@2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mdx-js/mdx': 2.3.0 @@ -3121,7 +3152,7 @@ snapshots: gray-matter: 4.0.3 katex: 0.16.10 lodash.get: 4.4.2 - next: 14.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-mdx-remote: 4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) p-limit: 3.1.0 react: 18.3.1 @@ -3196,6 +3227,14 @@ snapshots: picomatch@2.3.1: {} + playwright-core@1.44.1: {} + + playwright@1.44.1: + dependencies: + playwright-core: 1.44.1 + optionalDependencies: + fsevents: 2.3.2 + postcss@8.4.31: dependencies: nanoid: 3.3.7 diff --git a/tests/home.spec.ts b/tests/home.spec.ts new file mode 100644 index 0000000..b00c7ba --- /dev/null +++ b/tests/home.spec.ts @@ -0,0 +1,10 @@ +import { test, expect } from "@playwright/test"; + +test.describe("homepage", () => { + test("is mounted", async ({ page }) => { + await page.goto("/"); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Welcome to Nextra Documentation/); + }); +}); From 96b359a8f51da0b68090ca41e123c0e8d5581e99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 15:29:19 +0400 Subject: [PATCH 17/75] test: Adding E2E testing infrastructure. --- .gitignore | 8 +- package.json | 7 +- playwright.config.ts | 21 +- playwright.global-setup.ts | 42 ++ playwright.monocart-reporter.ts | 106 +++ pnpm-lock.yaml | 666 ++++++++++++++++++- test-results/.last-run.json | 4 + tests/_shared/app-fixtures.ts | 34 + tests/_shared/fixtures/v8-code-coverage.ts | 64 ++ tests/{home.spec.ts => e2e/homepage.spec.ts} | 3 +- 10 files changed, 944 insertions(+), 11 deletions(-) create mode 100644 playwright.global-setup.ts create mode 100644 playwright.monocart-reporter.ts create mode 100644 test-results/.last-run.json create mode 100644 tests/_shared/app-fixtures.ts create mode 100644 tests/_shared/fixtures/v8-code-coverage.ts rename tests/{home.spec.ts => e2e/homepage.spec.ts} (60%) diff --git a/.gitignore b/.gitignore index 3160408..0be026b 100644 --- a/.gitignore +++ b/.gitignore @@ -128,7 +128,13 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* -/test-results/ +/e2e-test-results/ /playwright-report/ /blob-report/ /playwright/.cache/ + +# Playwright +/e2e-test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ \ No newline at end of file diff --git a/package.json b/package.json index b8691a5..19c9abb 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,10 @@ "dev": "npm run private-route-gen && next", "prebuild": "npm run private-route-gen", "build": "next build", - "start": "next start" + "start": "next start", + "test": "npx playwright test", + "test:show-report": "npx monocart show-report ./e2e-test-results/monocart-report.html", + "coverage:show-report": "open-cli ./e2e-test-results/code-coverage/v8/index.html" }, "dependencies": { "next": "^14.2.4", @@ -18,6 +21,8 @@ "@playwright/test": "^1.44.1", "@types/node": "20.14.5", "fast-glob": "^3.3.2", + "monocart-reporter": "^2.5.0", + "open-cli": "^8.0.0", "ts-morph": "^22.0.0", "ts-node": "^10.9.2", "typescript": "5.4.5" diff --git a/playwright.config.ts b/playwright.config.ts index 08ac7fa..19be182 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -1,4 +1,6 @@ -import { defineConfig, devices } from '@playwright/test'; +import { ReporterDescription, defineConfig, devices } from '@playwright/test'; +import path from "path"; +import { getMonocartReporterOptions } from "./playwright.monocart-reporter"; /** * Read environment variables from file. @@ -7,6 +9,17 @@ import { defineConfig, devices } from '@playwright/test'; // import dotenv from 'dotenv'; // dotenv.config({ path: path.resolve(__dirname, '.env') }); +const _testResultsDir = path.resolve("./e2e-test-results"); +const _codeCoverageDir = path.resolve(_testResultsDir, "code-coverage"); +let _reporters: ReporterDescription[] = [ + ["list"], + [ + // See https://github.com/cenfun/monocart-reporter + "monocart-reporter", + getMonocartReporterOptions(_testResultsDir, _codeCoverageDir), + ], +]; + /** * See https://playwright.dev/docs/test-configuration. */ @@ -21,7 +34,9 @@ export default defineConfig({ /* Opt out of parallel tests on CI. */ workers: process.env.CI ? 1 : undefined, /* Reporter to use. See https://playwright.dev/docs/test-reporters */ - reporter: 'html', + reporter: _reporters, + /* See https://playwright.dev/docs/test-global-setup-teardown#option-2-configure-globalsetup-and-globalteardown */ + globalSetup: require.resolve("./playwright.global-setup.ts"), /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Base URL to use in actions like `await page.goto('/')`. */ @@ -36,8 +51,6 @@ export default defineConfig({ command: 'pnpm run dev', url: 'http://localhost:3000', reuseExistingServer: !process.env.CI, - stdout: 'ignore', - stderr: 'pipe', timeout: 120 * 1000, }, diff --git a/playwright.global-setup.ts b/playwright.global-setup.ts new file mode 100644 index 0000000..2a97294 --- /dev/null +++ b/playwright.global-setup.ts @@ -0,0 +1,42 @@ +import { FullConfig } from "@playwright/test"; + +// See https://playwright.dev/docs/test-global-setup-teardown#option-2-configure-globalsetup-and-globalteardown +type PlaywrightCliOptions = { + UIMode: boolean; + }; + + export const playwrightCliOptions: PlaywrightCliOptions = { + UIMode: process.argv.includes("--ui"), + }; + +function startupLog(config: FullConfig) { + console.log(""); // just for the new line + console.log("Starting playwright tests:"); + console.log(`- Playwright version: ${config.version}`); + console.log(`- UI mode: ${playwrightCliOptions.UIMode}`); + console.log(`- update snapshots: ${config.updateSnapshots}`); + console.log(`- webServer.command: ${config.webServer?.command}`); + console.log(`- webServer.url: ${config.webServer?.url}`); + // prettier-ignore + console.log(`- webServer.reuseExistingServer: ${config.webServer?.reuseExistingServer}`); + console.log(`- testDir: ${config.projects[0].testDir}`); + console.log(`- outputDir: ${config.projects[0].outputDir}`); + const monocartReporter = config.reporter[1]; + if (monocartReporter) { + const monocartReporterOptions = monocartReporter[1]; + // prettier-ignore + console.log(`- monocart-reporter outputFile: ${monocartReporterOptions.outputFile}`); + // prettier-ignore + console.log(`- monocart-reporter coverage.outputDir: ${monocartReporterOptions.coverage.outputDir}`); + // prettier-ignore + console.log(`- monocart-reporter coverage.reportPath: ${monocartReporterOptions.coverage.reportPath}`); + } + + console.log(""); // just for the new line +} + +async function globalSetup(config: FullConfig): Promise { + startupLog(config); +} + +export default globalSetup; \ No newline at end of file diff --git a/playwright.monocart-reporter.ts b/playwright.monocart-reporter.ts new file mode 100644 index 0000000..1aeef95 --- /dev/null +++ b/playwright.monocart-reporter.ts @@ -0,0 +1,106 @@ +import { + CoverageReportOptions, + MonocartReporterOptions, + ReportDescription, +} from "monocart-reporter"; +import path from "path"; + +function getCodeCoverageOptions( + codeCoverageDir: string, +): CoverageReportOptions { + const v8RelativeFilePath = "v8/index.html"; + + // The paths in the codeCoverageReports variable are all relative to monocart-reporter coverage.outputDir. + // + // Note that you can configure the reports to produce just an lcov or cobertura report for instance. + // No need to produce html report like the html-spa or v8 reports if the only thing you want is an lcov + // report to upload to sonarQ. + // However, I do recommend always having an html report so a human can look at it. Even if you only generate + // it outside your CI environment, just for local dev purposes. + const _codeCoverageReports: ReportDescription[] = [ + [ + "v8", + { + outputFile: v8RelativeFilePath, // v8 sub dir and html file name, relative to coverage.outputDir. + inline: true, // inline all scripts required for the V8 html report into a single HTML file. + metrics: ["lines"], // metrics is an Array<"bytes" | "functions" | "branches" | "lines"> + }, + ], + [ + "console-summary", + { + metrics: ["lines"], + }, + ], + [ + // This must be set as the first reporter of the list of istanbul reporters. + // This configuration is using the `cobertura` and `lcovonly` instanbul reporters. + // For a list of all istanbul built-in reporters see: https://github.com/cenfun/monocart-coverage-reports?tab=readme-ov-file#available-reports + // + // If this reporter is not set as the first of the istanbul built-in reporters, + // the index.html is not generated at {subdir}/index.html and instead is placed at + // {subdir}/app/index.html. This then makes it so that the index.html doesn't display + // the code coverage report when opened because the index.html has references + // to files that should be at the same directory which is {subdir} and they're not + // found at {subdir}/app. Example: + // + // + // + // And bundle.js exists at {subdir} and not at {subdir}/app. + // + "html-spa", + { + subdir: "html-spa", + }, + ], + [ + "cobertura", + { + file: "cobertura/code-coverage.cobertura.xml", + }, + ], + [ + "lcovonly", + { + file: "lcov/code-coverage.lcov.info", + }, + ], + ]; + + // for documentation on the monocart code coverage options see: + // - https://github.com/cenfun/monocart-reporter#code-coverage-report + // - https://github.com/cenfun/monocart-coverage-reports + // - https://github.com/cenfun/monocart-coverage-reports/blob/main/lib/index.d.ts + const coverageOptions: CoverageReportOptions = { + outputDir: codeCoverageDir, // all code coverage reports will be created in this dir. + reportPath: path.resolve(codeCoverageDir, v8RelativeFilePath), // code coverage html report filepath which shows up in the monocart report under global attachments. + reports: _codeCoverageReports, + // !!!! IMPORTANT !!!!!! + // These are where we filter the files for reporting, thus affecting coverage. + // In E2E testing, the sourcemaps don't seem to be working (it's covering the output files). + // See https://github.com/cenfun/monocart-coverage-reports?#using-entryfilter-and-sourcefilter-to-filter-the-results-for-v8-report for options about this. + // I'm leaving as it is because E2E matter mostly if they **pass** or not. This is just coverage. + entryFilter: { + '**/node_modules/**': false, + '**/vendor.js': false, + '**/pages/**': true + }, + sourceFilter: { + '**/node_modules/**': false, + '**/**': true + } + }; + return coverageOptions; +} + +export function getMonocartReporterOptions( + testResultsDir: string, + codeCoverageDir: string, +): MonocartReporterOptions { + const monocartOptions: MonocartReporterOptions = { + name: "playwright code coverage demo with monocart reporter", + outputFile: path.resolve(testResultsDir, "monocart-report.html"), + coverage: getCodeCoverageOptions(codeCoverageDir), + }; + return monocartOptions; +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d785dd2..8d3b8fb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-auth: specifier: 5.0.0-beta.19 - version: 5.0.0-beta.19(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + version: 5.0.0-beta.19(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.9.14)(react@18.3.1) nextra: specifier: ^2.13.4 version: 2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -36,6 +36,12 @@ importers: fast-glob: specifier: ^3.3.2 version: 3.3.2 + monocart-reporter: + specifier: ^2.5.0 + version: 2.5.0 + open-cli: + specifier: ^8.0.0 + version: 8.0.0 ts-morph: specifier: ^22.0.0 version: 22.0.0 @@ -271,6 +277,9 @@ packages: '@theguild/remark-npm2yarn@0.2.1': resolution: {integrity: sha512-jUTFWwDxtLEFtGZh/TW/w30ySaDJ8atKWH8dq2/IiQF61dPrGfETpl0WxD0VdBfuLOeU14/kop466oBSRO/5CA==} + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@ts-morph/common@0.23.0': resolution: {integrity: sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==} @@ -352,6 +361,10 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -405,10 +418,18 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} + cache-content-type@1.0.1: + resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==} + engines: {node: '>= 6.0.0'} + caniuse-lite@1.0.30001636: resolution: {integrity: sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==} @@ -442,6 +463,10 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + code-block-writer@13.0.1: resolution: {integrity: sha512-c5or4P6erEA69TxaxTNcHUNcIn+oyxSRTOWV+pSYF+z4epXqNvwvJ70XPGjPNgue83oAFAPBRQYwpAJ/Hpe/Sg==} @@ -465,10 +490,25 @@ packages: compute-scroll-into-view@3.1.0: resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} + console-grid@2.2.2: + resolution: {integrity: sha512-ohlgXexdDTKLNsZz7DSJuCAwmRc8omSS61txOk39W3NOthgKGr1a1jJpZ5BCQe4PlrwMw01OvPQ1Bl3G7Y/uFg==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + cookies@0.9.1: + resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} + engines: {node: '>= 0.8'} + cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} @@ -478,6 +518,10 @@ packages: cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + crypto-random-string@4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -647,13 +691,43 @@ packages: decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + deep-equal@1.0.1: + resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} + + default-browser-id@5.0.0: + resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} + engines: {node: '>=18'} + + default-browser@5.2.1: + resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} + engines: {node: '>=18'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} @@ -668,13 +742,26 @@ packages: dompurify@3.1.5: resolution: {integrity: sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==} + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + eight-colors@1.3.0: + resolution: {integrity: sha512-hVoK898cR71ADj7L1LZWaECLaSkzzPtqGXIaKv4K6Pzb72QgjLVsQaNI+ELDQQshzFvgp5xTPkaYkPGqw3YR+g==} + elkjs@0.9.3: resolution: {integrity: sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==} + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} @@ -728,6 +815,10 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + file-type@18.7.0: + resolution: {integrity: sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==} + engines: {node: '>=14.16'} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -738,11 +829,19 @@ packages: focus-visible@5.2.0: resolution: {integrity: sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==} + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + get-stdin@9.0.0: + resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} + engines: {node: '>=12'} + get-stream@3.0.0: resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} engines: {node: '>=4'} @@ -771,6 +870,18 @@ packages: resolution: {integrity: sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==} engines: {node: '>=0.10.0'} + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + hash-obj@4.0.0: resolution: {integrity: sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==} engines: {node: '>=12'} @@ -811,13 +922,30 @@ packages: hastscript@8.0.0: resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-void-elements@3.0.0: resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + http-assert@1.5.0: + resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==} + engines: {node: '>= 0.8'} + + http-errors@1.8.1: + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + inline-style-parser@0.1.1: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} @@ -844,6 +972,11 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + is-extendable@0.1.1: resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} engines: {node: '>=0.10.0'} @@ -852,6 +985,10 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -859,6 +996,11 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -885,9 +1027,29 @@ packages: resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} engines: {node: '>=0.10.0'} + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + jose@5.4.0: resolution: {integrity: sha512-6rpxTHPAQyWMb9A35BroFl1Sp0ST3DpPcm5EVIxZxdH+e0Hv9fwhyB3XLKFUcHNpdSDnETmBfuPPTTlYz5+USw==} @@ -909,6 +1071,10 @@ packages: resolution: {integrity: sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA==} hasBin: true + keygrip@1.1.0: + resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==} + engines: {node: '>= 0.6'} + khroma@2.1.0: resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} @@ -920,6 +1086,20 @@ packages: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} + koa-compose@4.1.0: + resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==} + + koa-convert@2.0.0: + resolution: {integrity: sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==} + engines: {node: '>= 10'} + + koa-static-resolver@1.0.6: + resolution: {integrity: sha512-ZX5RshSzH8nFn05/vUNQzqw32nEigsPa67AVUr6ZuQxuGdnCcTLcdgr4C81+YbJjpgqKHfacMBd7NmJIbj7fXw==} + + koa@2.15.3: + resolution: {integrity: sha512-j/8tY9j5t+GVMLeioLaxweJiKUayFhlGqNTzf2ZGwL0ZCQijd2RLHK0SLW5Tsko8YyyqCZC2cojIb0/s62qTAg==} + engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} + layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} @@ -939,6 +1119,13 @@ packages: lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + lz-utils@2.0.2: + resolution: {integrity: sha512-i1PJN4hNEevkrvLMqNWCCac1BcB5SRaghywG7HVzWOyVkFOasLCG19ND1sY1F/ZEsM6SnGtoXyBWnmfqOM5r6g==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} @@ -1009,6 +1196,14 @@ packages: mdast-util-to-string@3.2.0: resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==} + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1143,6 +1338,14 @@ packages: resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + minimatch@9.0.4: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} @@ -1152,6 +1355,23 @@ packages: engines: {node: '>=10'} hasBin: true + monocart-code-viewer@1.1.4: + resolution: {integrity: sha512-ehSe1lBG7D1VDVLjTkHV63J3zAgzyhlC9OaxOri7D0X4L5/EcZUOG5TEoMmYErL+YGSOQXghU9kSSAelwNnp1Q==} + + monocart-coverage-reports@2.8.4: + resolution: {integrity: sha512-RpE7O8+p9DMrBLSnW6gALEy0nn69cxFd6QJd7Cv+ERNFPAEqBur1jV3DQcpcr00C6IcnCm2Pw5/aTpsGNUGdUQ==} + hasBin: true + + monocart-formatter@3.0.0: + resolution: {integrity: sha512-91OQpUb/9iDqvrblUv6ki11Jxi1d3Fp5u2jfVAPl3UdNp9TM+iBleLzXntUS51W0o+zoya3CJjZZ01z2XWn25g==} + + monocart-locator@1.0.0: + resolution: {integrity: sha512-qIHJ7f99miF2HbVUWAFKR93SfgGYpFPUCQPmW9q1VXU9onxMUFJxhQDdG3HkEteogUbsKB7Gr5MRgjzcIxwTaQ==} + + monocart-reporter@2.5.0: + resolution: {integrity: sha512-atEEsAtBpUSYf+eahmRCAIzOZi7X03qD82qHeiuxrRWpevrODNBG38FamXB1+EWINx5Cs1YdDpzFnDk9tzXHSg==} + hasBin: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1164,6 +1384,10 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + next-auth@5.0.0-beta.19: resolution: {integrity: sha512-YHu1igcAxZPh8ZB7GIM93dqgY6gcAzq66FOhQFheAdOx1raxNcApt05nNyNCSB6NegSiyJ4XOPsaNow4pfDmsg==} peerDependencies: @@ -1235,6 +1459,10 @@ packages: react: '>=16.13.1' react-dom: '>=16.13.1' + nodemailer@6.9.14: + resolution: {integrity: sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==} + engines: {node: '>=6.0.0'} + non-layered-tidy-tree-layout@2.0.2: resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} @@ -1249,6 +1477,22 @@ packages: oauth4webapi@2.10.4: resolution: {integrity: sha512-DSoj8QoChzOCQlJkRmYxAJCIpnXFW32R0Uq7avyghIeB6iJq0XAblOD7pcq3mx4WEBDwMuKr0Y1qveCBleG2Xw==} + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + only@0.0.2: + resolution: {integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==} + + open-cli@8.0.0: + resolution: {integrity: sha512-3muD3BbfLyzl+aMVSEfn2FfOqGdPYR0O4KNnxXsLEPE2q9OSjBfJAaB6XKbrUzLgymoSMejvb5jpXJfru/Ko2A==} + engines: {node: '>=18'} + hasBin: true + + open@10.1.0: + resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} + engines: {node: '>=18'} + p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} @@ -1272,6 +1516,10 @@ packages: parse5@7.1.2: resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -1279,6 +1527,10 @@ packages: resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} engines: {node: '>=4'} + peek-readable@5.0.0: + resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==} + engines: {node: '>=14.16'} + periscopic@3.1.0: resolution: {integrity: sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==} @@ -1335,6 +1587,14 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readable-web-to-node-stream@3.0.2: + resolution: {integrity: sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==} + engines: {node: '>=8'} + reading-time@1.5.0: resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==} @@ -1381,6 +1641,10 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + run-applescript@7.0.0: + resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} + engines: {node: '>=18'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -1391,6 +1655,9 @@ packages: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -1404,6 +1671,14 @@ packages: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} + semver@7.6.2: + resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + engines: {node: '>=10'} + hasBin: true + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + shebang-command@1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -1440,10 +1715,17 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} @@ -1455,6 +1737,10 @@ packages: resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} engines: {node: '>=0.10.0'} + strtok3@7.0.0: + resolution: {integrity: sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==} + engines: {node: '>=14.16'} + style-to-object@0.4.4: resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==} @@ -1478,6 +1764,18 @@ packages: resolution: {integrity: sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==} engines: {node: '>=4'} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + temp-dir@3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} + + tempy@3.1.0: + resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} + engines: {node: '>=14.16'} + title@3.5.3: resolution: {integrity: sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==} hasBin: true @@ -1490,6 +1788,14 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + token-types@5.0.1: + resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==} + engines: {node: '>=14.16'} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -1520,10 +1826,25 @@ packages: tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tsscmp@1.0.6: + resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} + engines: {node: '>=0.6.x'} + + turbogrid@3.2.0: + resolution: {integrity: sha512-c+2qrCGWzoYpLlxtHgRJ4V5dDRE9fUT7D9maxtdBCqJ0NzCdY+x7xF3/F6cG/+n3VIzKfIS+p9Z/0YMQPf6k/Q==} + type-fest@1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} engines: {node: '>=10'} + type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + typescript@5.4.5: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} @@ -1535,6 +1856,10 @@ packages: unified@10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} + unique-string@3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} + unist-util-find-after@5.0.0: resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} @@ -1589,6 +1914,9 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -1601,6 +1929,10 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + vfile-location@5.0.2: resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} @@ -1638,6 +1970,10 @@ packages: yallist@2.1.2: resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + ylru@1.4.0: + resolution: {integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==} + engines: {node: '>= 4.0.0'} + yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -1654,7 +1990,7 @@ packages: snapshots: - '@auth/core@0.32.0': + '@auth/core@0.32.0(nodemailer@6.9.14)': dependencies: '@panva/hkdf': 1.1.1 '@types/cookie': 0.6.0 @@ -1663,6 +1999,8 @@ snapshots: oauth4webapi: 2.10.4 preact: 10.11.3 preact-render-to-string: 5.2.3(preact@10.11.3) + optionalDependencies: + nodemailer: 6.9.14 '@babel/runtime@7.24.7': dependencies: @@ -1842,6 +2180,8 @@ snapshots: npm-to-yarn: 2.2.1 unist-util-visit: 5.0.0 + '@tokenizer/token@0.3.0': {} + '@ts-morph/common@0.23.0': dependencies: fast-glob: 3.3.2 @@ -1922,6 +2262,11 @@ snapshots: '@ungap/structured-clone@1.2.0': {} + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + acorn-jsx@5.3.2(acorn@8.12.0): dependencies: acorn: 8.12.0 @@ -1964,10 +2309,19 @@ snapshots: dependencies: fill-range: 7.1.1 + bundle-name@4.1.0: + dependencies: + run-applescript: 7.0.0 + busboy@1.6.0: dependencies: streamsearch: 1.1.0 + cache-content-type@1.0.1: + dependencies: + mime-types: 2.1.35 + ylru: 1.4.0 + caniuse-lite@1.0.30001636: {} ccount@2.0.1: {} @@ -1995,6 +2349,8 @@ snapshots: clsx@2.1.1: {} + co@4.6.0: {} + code-block-writer@13.0.1: {} color-convert@1.9.3: @@ -2011,8 +2367,21 @@ snapshots: compute-scroll-into-view@3.1.0: {} + console-grid@2.2.2: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + cookie@0.6.0: {} + cookies@0.9.1: + dependencies: + depd: 2.0.0 + keygrip: 1.1.0 + cose-base@1.0.3: dependencies: layout-base: 1.0.2 @@ -2025,6 +2394,10 @@ snapshots: shebang-command: 1.2.0 which: 1.3.1 + crypto-random-string@4.0.0: + dependencies: + type-fest: 1.4.0 + csstype@3.1.3: {} cytoscape-cose-bilkent@4.1.0(cytoscape@3.29.2): @@ -2216,12 +2589,31 @@ snapshots: dependencies: character-entities: 2.0.2 + deep-equal@1.0.1: {} + + default-browser-id@5.0.0: {} + + default-browser@5.2.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.0 + + define-lazy-prop@3.0.0: {} + delaunator@5.0.1: dependencies: robust-predicates: 3.0.2 + delegates@1.0.0: {} + + depd@1.1.2: {} + + depd@2.0.0: {} + dequal@2.0.3: {} + destroy@1.2.0: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 @@ -2232,10 +2624,18 @@ snapshots: dompurify@3.1.5: {} + ee-first@1.1.1: {} + + eight-colors@1.3.0: {} + elkjs@0.9.3: {} + encodeurl@1.0.2: {} + entities@4.5.0: {} + escape-html@1.0.3: {} + escape-string-regexp@1.0.5: {} escape-string-regexp@5.0.0: {} @@ -2301,6 +2701,12 @@ snapshots: dependencies: reusify: 1.0.4 + file-type@18.7.0: + dependencies: + readable-web-to-node-stream: 3.0.2 + strtok3: 7.0.0 + token-types: 5.0.1 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -2309,9 +2715,13 @@ snapshots: focus-visible@5.2.0: {} + fresh@0.5.2: {} + fsevents@2.3.2: optional: true + get-stdin@9.0.0: {} + get-stream@3.0.0: {} git-up@7.0.0: @@ -2340,6 +2750,14 @@ snapshots: has-flag@2.0.0: {} + has-flag@4.0.0: {} + + has-symbols@1.0.3: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.0.3 + hash-obj@4.0.0: dependencies: is-obj: 3.0.0 @@ -2450,12 +2868,31 @@ snapshots: property-information: 6.5.0 space-separated-tokens: 2.0.2 + html-escaper@2.0.2: {} + html-void-elements@3.0.0: {} + http-assert@1.5.0: + dependencies: + deep-equal: 1.0.1 + http-errors: 1.8.1 + + http-errors@1.8.1: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 + ieee754@1.2.1: {} + + inherits@2.0.4: {} + inline-style-parser@0.1.1: {} internmap@1.0.1: {} @@ -2475,16 +2912,26 @@ snapshots: is-decimal@2.0.1: {} + is-docker@3.0.0: {} + is-extendable@0.1.1: {} is-extglob@2.1.1: {} + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 is-hexadecimal@2.0.1: {} + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + is-number@7.0.0: {} is-obj@3.0.0: {} @@ -2503,8 +2950,27 @@ snapshots: is-stream@1.1.0: {} + is-stream@3.0.0: {} + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + jose@5.4.0: {} js-tokens@4.0.0: {} @@ -2524,12 +2990,53 @@ snapshots: dependencies: commander: 8.3.0 + keygrip@1.1.0: + dependencies: + tsscmp: 1.0.6 + khroma@2.1.0: {} kind-of@6.0.3: {} kleur@4.1.5: {} + koa-compose@4.1.0: {} + + koa-convert@2.0.0: + dependencies: + co: 4.6.0 + koa-compose: 4.1.0 + + koa-static-resolver@1.0.6: {} + + koa@2.15.3: + dependencies: + accepts: 1.3.8 + cache-content-type: 1.0.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookies: 0.9.1 + debug: 4.3.5 + delegates: 1.0.0 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + fresh: 0.5.2 + http-assert: 1.5.0 + http-errors: 1.8.1 + is-generator-function: 1.0.10 + koa-compose: 4.1.0 + koa-convert: 2.0.0 + on-finished: 2.4.1 + only: 0.0.2 + parseurl: 1.3.3 + statuses: 1.5.0 + type-is: 1.6.18 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + layout-base@1.0.2: {} lodash-es@4.17.21: {} @@ -2547,6 +3054,12 @@ snapshots: pseudomap: 1.0.2 yallist: 2.1.2 + lz-utils@2.0.2: {} + + make-dir@4.0.0: + dependencies: + semver: 7.6.2 + make-error@1.3.6: {} markdown-extensions@1.1.1: {} @@ -2728,6 +3241,10 @@ snapshots: dependencies: '@types/mdast': 3.0.15 + media-typer@0.3.0: {} + + meow@12.1.1: {} + merge2@1.4.1: {} mermaid@10.9.1: @@ -3051,23 +3568,67 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 mkdirp@3.0.1: {} + monocart-code-viewer@1.1.4: {} + + monocart-coverage-reports@2.8.4: + dependencies: + console-grid: 2.2.2 + eight-colors: 1.3.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.1.7 + lz-utils: 2.0.2 + monocart-code-viewer: 1.1.4 + monocart-formatter: 3.0.0 + monocart-locator: 1.0.0 + turbogrid: 3.2.0 + + monocart-formatter@3.0.0: {} + + monocart-locator@1.0.0: {} + + monocart-reporter@2.5.0: + dependencies: + console-grid: 2.2.2 + eight-colors: 1.3.0 + koa: 2.15.3 + koa-static-resolver: 1.0.6 + lz-utils: 2.0.2 + monocart-coverage-reports: 2.8.4 + monocart-formatter: 3.0.0 + monocart-locator: 1.0.0 + nodemailer: 6.9.14 + turbogrid: 3.2.0 + transitivePeerDependencies: + - supports-color + mri@1.2.0: {} ms@2.1.2: {} nanoid@3.3.7: {} - next-auth@5.0.0-beta.19(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): + negotiator@0.6.3: {} + + next-auth@5.0.0-beta.19(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.9.14)(react@18.3.1): dependencies: - '@auth/core': 0.32.0 + '@auth/core': 0.32.0(nodemailer@6.9.14) next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 + optionalDependencies: + nodemailer: 6.9.14 next-mdx-remote@4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: @@ -3172,6 +3733,8 @@ snapshots: transitivePeerDependencies: - supports-color + nodemailer@6.9.14: {} + non-layered-tidy-tree-layout@2.0.2: {} npm-run-path@2.0.2: @@ -3182,6 +3745,27 @@ snapshots: oauth4webapi@2.10.4: {} + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + only@0.0.2: {} + + open-cli@8.0.0: + dependencies: + file-type: 18.7.0 + get-stdin: 9.0.0 + meow: 12.1.1 + open: 10.1.0 + tempy: 3.1.0 + + open@10.1.0: + dependencies: + default-browser: 5.2.1 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + is-wsl: 3.1.0 + p-finally@1.0.0: {} p-limit@3.1.0: @@ -3213,10 +3797,14 @@ snapshots: dependencies: entities: 4.5.0 + parseurl@1.3.3: {} + path-browserify@1.0.1: {} path-key@2.0.1: {} + peek-readable@5.0.0: {} + periscopic@3.1.0: dependencies: '@types/estree': 1.0.5 @@ -3268,6 +3856,16 @@ snapshots: dependencies: loose-envify: 1.4.0 + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readable-web-to-node-stream@3.0.2: + dependencies: + readable-stream: 3.6.2 + reading-time@1.5.0: {} regenerator-runtime@0.14.1: {} @@ -3346,6 +3944,8 @@ snapshots: robust-predicates@3.0.2: {} + run-applescript@7.0.0: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -3356,6 +3956,8 @@ snapshots: dependencies: mri: 1.2.0 + safe-buffer@5.2.1: {} + safer-buffer@2.1.2: {} scheduler@0.23.2: @@ -3371,6 +3973,10 @@ snapshots: extend-shallow: 2.0.1 kind-of: 6.0.3 + semver@7.6.2: {} + + setprototypeof@1.2.0: {} + shebang-command@1.2.0: dependencies: shebang-regex: 1.0.0 @@ -3400,8 +4006,14 @@ snapshots: sprintf-js@1.0.3: {} + statuses@1.5.0: {} + streamsearch@1.1.0: {} + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + stringify-entities@4.0.4: dependencies: character-entities-html4: 2.1.0 @@ -3411,6 +4023,11 @@ snapshots: strip-eof@1.0.0: {} + strtok3@7.0.0: + dependencies: + '@tokenizer/token': 0.3.0 + peek-readable: 5.0.0 + style-to-object@0.4.4: dependencies: inline-style-parser: 0.1.1 @@ -3426,6 +4043,19 @@ snapshots: dependencies: has-flag: 2.0.0 + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + temp-dir@3.0.0: {} + + tempy@3.1.0: + dependencies: + is-stream: 3.0.0 + temp-dir: 3.0.0 + type-fest: 2.19.0 + unique-string: 3.0.0 + title@3.5.3: dependencies: arg: 1.0.0 @@ -3439,6 +4069,13 @@ snapshots: dependencies: is-number: 7.0.0 + toidentifier@1.0.1: {} + + token-types@5.0.1: + dependencies: + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -3470,8 +4107,19 @@ snapshots: tslib@2.6.3: {} + tsscmp@1.0.6: {} + + turbogrid@3.2.0: {} + type-fest@1.4.0: {} + type-fest@2.19.0: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + typescript@5.4.5: {} undici-types@5.26.5: {} @@ -3486,6 +4134,10 @@ snapshots: trough: 2.2.0 vfile: 5.3.7 + unique-string@3.0.0: + dependencies: + crypto-random-string: 4.0.0 + unist-util-find-after@5.0.0: dependencies: '@types/unist': 3.0.2 @@ -3570,6 +4222,8 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 + util-deprecate@1.0.2: {} + uuid@9.0.1: {} uvu@0.5.6: @@ -3581,6 +4235,8 @@ snapshots: v8-compile-cache-lib@3.0.1: {} + vary@1.1.2: {} + vfile-location@5.0.2: dependencies: '@types/unist': 3.0.2 @@ -3629,6 +4285,8 @@ snapshots: yallist@2.1.2: {} + ylru@1.4.0: {} + yn@3.1.1: {} yocto-queue@0.1.0: {} diff --git a/test-results/.last-run.json b/test-results/.last-run.json new file mode 100644 index 0000000..cbcc1fb --- /dev/null +++ b/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "passed", + "failedTests": [] +} \ No newline at end of file diff --git a/tests/_shared/app-fixtures.ts b/tests/_shared/app-fixtures.ts new file mode 100644 index 0000000..322bcc8 --- /dev/null +++ b/tests/_shared/app-fixtures.ts @@ -0,0 +1,34 @@ +import { test as baseTest } from "@playwright/test"; +import { + collectV8CodeCoverageAsync, + CollectV8CodeCoverageOptions, +} from "./fixtures/v8-code-coverage"; + +// re-exporting the default expect as well so that on the tests we can have +// a single import for expect and test, but the test will be the extended test below +export { expect } from "@playwright/test"; + +// See https://playwright.dev/docs/test-fixtures and https://playwright.dev/docs/test-parameterize +interface AppFixtures { + codeCoverageAutoTestFixture: void; +} + +// Export the extended test type. +// All tests that use this export 'test' type will have the automatic fixture applied to them. +export const test = baseTest.extend({ + codeCoverageAutoTestFixture: [ + async ({ browser, page }, use): Promise => { + const options: CollectV8CodeCoverageOptions = { + browserType: browser.browserType(), + page: page, + use: use, + enableJsCoverage: true, + enableCssCoverage: true, + }; + await collectV8CodeCoverageAsync(options); + }, + { + auto: true, + }, + ], +}); \ No newline at end of file diff --git a/tests/_shared/fixtures/v8-code-coverage.ts b/tests/_shared/fixtures/v8-code-coverage.ts new file mode 100644 index 0000000..3c2dc43 --- /dev/null +++ b/tests/_shared/fixtures/v8-code-coverage.ts @@ -0,0 +1,64 @@ +import { BrowserType, Page, test } from "@playwright/test"; +import { addCoverageReport } from "monocart-reporter"; + +export type CollectV8CodeCoverageOptions = { + browserType: BrowserType; + page: Page; + use: () => Promise; + enableJsCoverage: boolean; + enableCssCoverage: boolean; +}; + +function browserSupportsV8CodeCoverage(browserType: BrowserType): boolean { + return browserType.name() === "chromium"; +} + +// See https://playwright.dev/docs/api/class-coverage. +// This instruments code using v8 and then attaches the code coverage data +// to the monocart-reporter. +export async function collectV8CodeCoverageAsync( + options: CollectV8CodeCoverageOptions, +): Promise { + // prettier-ignore + const v8CodeCoverageSupported = browserSupportsV8CodeCoverage(options.browserType); + // prettier-ignore + const codeCoverageEnabled = options.enableJsCoverage || options.enableCssCoverage; + if (!v8CodeCoverageSupported || !codeCoverageEnabled) { + await options.use(); + return; + } + + const page = options.page; + let startCoveragePromises: Promise[] = []; + // When collecting code coverage make sure the 'resetOnNavigation' is set to false. + // Otherwise, if the test contains page navigations then only the coverage for the + // last page navigation is recorded. + if (options.enableJsCoverage) { + const startJsCoveragePromise = page.coverage.startJSCoverage({ + resetOnNavigation: false, + }); + startCoveragePromises.push(startJsCoveragePromise); + } + if (options.enableCssCoverage) { + const startCssCoveragePromise = page.coverage.startCSSCoverage({ + resetOnNavigation: false, + }); + startCoveragePromises.push(startCssCoveragePromise); + } + + await Promise.all(startCoveragePromises); + await options.use(); + + let stopCoveragePromises: Promise[] = []; + if (options.enableJsCoverage) { + const stopJsCoveragePromise = page.coverage.stopJSCoverage(); + stopCoveragePromises.push(stopJsCoveragePromise); + } + if (options.enableCssCoverage) { + const stopCssCoveragePromise = page.coverage.stopCSSCoverage(); + stopCoveragePromises.push(stopCssCoveragePromise); + } + + const coverageReports = await Promise.all(stopCoveragePromises); + await addCoverageReport(coverageReports.flat(), test.info()); +} \ No newline at end of file diff --git a/tests/home.spec.ts b/tests/e2e/homepage.spec.ts similarity index 60% rename from tests/home.spec.ts rename to tests/e2e/homepage.spec.ts index b00c7ba..1b21c48 100644 --- a/tests/home.spec.ts +++ b/tests/e2e/homepage.spec.ts @@ -1,4 +1,5 @@ -import { test, expect } from "@playwright/test"; +// must use this fixture instead of "@playwright/test" to be able to collect data for coverage +import { test, expect } from "../_shared/app-fixtures"; test.describe("homepage", () => { test("is mounted", async ({ page }) => { From da80741518aa51fc4a57f3e5b5897201f587d4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 15:39:25 +0400 Subject: [PATCH 18/75] chore: Deleting test-results folder that shouldn't be versioned in the first place. --- .gitignore | 1 + test-results/.last-run.json | 4 ---- tests/e2e/homepage.spec.ts | 11 +++++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) delete mode 100644 test-results/.last-run.json diff --git a/.gitignore b/.gitignore index 0be026b..7d79707 100644 --- a/.gitignore +++ b/.gitignore @@ -134,6 +134,7 @@ dist /playwright/.cache/ # Playwright +/test-results/ /e2e-test-results/ /playwright-report/ /blob-report/ diff --git a/test-results/.last-run.json b/test-results/.last-run.json deleted file mode 100644 index cbcc1fb..0000000 --- a/test-results/.last-run.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "status": "passed", - "failedTests": [] -} \ No newline at end of file diff --git a/tests/e2e/homepage.spec.ts b/tests/e2e/homepage.spec.ts index 1b21c48..f07c640 100644 --- a/tests/e2e/homepage.spec.ts +++ b/tests/e2e/homepage.spec.ts @@ -1,5 +1,12 @@ -// must use this fixture instead of "@playwright/test" to be able to collect data for coverage -import { test, expect } from "../_shared/app-fixtures"; +// !! PLEASE READ !! +/* +Coverage for E2E effectively works, but the coverage is not using the sourcemaps properly, so coverage doesn't mean much. +We've decided to leave the infrastructure (coverage uses `monocart`) with its configuration for posteriority in case we need them. +E2E testing is more relevant knowing **if they pass or not**. +*/ + + +import { test, expect } from "../_shared/app-fixtures"; // we use the overriden functions to get coverage test.describe("homepage", () => { test("is mounted", async ({ page }) => { From 24c66e29cca0913bfd096ba1f99c46e8e79e06fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 17:58:39 +0400 Subject: [PATCH 19/75] test: Adding E2E tests for authentication with Playwright. --- .env.local-example | 4 ++- auth.ts | 63 ++++++++++++++++++++++++++++---------- package.json | 1 + playwright.config.ts | 5 +-- pnpm-lock.yaml | 9 ++++++ tests/e2e/homepage.spec.ts | 18 ----------- tests/e2e/test.spec.ts | 55 +++++++++++++++++++++++++++++++++ 7 files changed, 118 insertions(+), 37 deletions(-) delete mode 100644 tests/e2e/homepage.spec.ts create mode 100644 tests/e2e/test.spec.ts diff --git a/.env.local-example b/.env.local-example index 90d0fe8..71692d0 100644 --- a/.env.local-example +++ b/.env.local-example @@ -1,4 +1,6 @@ AUTH_SECRET= AUTH_GITHUB_ID= -AUTH_GITHUB_SECRET= \ No newline at end of file +AUTH_GITHUB_SECRET= + +TEST_PASSWORD= \ No newline at end of file diff --git a/auth.ts b/auth.ts index f79f379..6abb3a9 100644 --- a/auth.ts +++ b/auth.ts @@ -2,6 +2,8 @@ import GitHub from "next-auth/providers/github"; import NextAuth, { type DefaultSession } from "next-auth"; import { DefaultJWT } from "next-auth/jwt"; import { AdapterSession } from 'next-auth/adapters'; +import { Provider } from "next-auth/providers"; +import Credentials from "next-auth/providers/credentials"; // We need to add the role to the JWT inside `NextAuth` below, so the `middleware.ts` can have access to it. // The problem is that it wasn't added this `role` custom field, even if we defined it in `auth.ts`. @@ -43,23 +45,52 @@ declare module "next-auth/jwt" { // ---------- -export const { handlers, signIn, signOut, auth } = NextAuth({ - providers: [ - GitHub({ - profile(profile) { - // GitHub's OAuth apps don't allow you to define roles. - // So `profile` here doesn't have a `role` property. - // But on other providers, you'd add the role here through it. - return { - id: profile.id.toString(), - name: profile.name ?? profile.login, - email: profile.email, - image: profile.avatar_url, - role: "user", - }; +// OAuth providers to sign-in +const providers: Provider[] = [ + GitHub({ + profile(profile) { + // GitHub's OAuth apps don't allow you to define roles. + // So `profile` here doesn't have a `role` property. + // But on other providers, you'd add the role here through it. + return { + id: profile.id.toString(), + name: profile.name ?? profile.login, + email: profile.email, + image: profile.avatar_url, + role: "user", + }; + }, + }), +] + +// Be sure to not put a development version in production! +// See https://authjs.dev/guides/testing#credentials-provider-in-development. +if (process.env.NODE_ENV === "development") { + providers.push( + Credentials({ + id: "password", + name: "Password", + credentials: { + password: { label: "Password", type: "password" }, + }, + authorize: (credentials) => { + if (credentials.password === process.env.TEST_PASSWORD) { + return { + email: "bob@alice.com", + name: "Bob Alice", + image: "", + } + } + return null }, - }), - ], + }) + ) +} + + +// The important part: where the `NextAuth` config is exported +export const { handlers, signIn, signOut, auth } = NextAuth({ + providers: providers, callbacks: { jwt({ token, user, account, profile }) { // Normally, it would be like this diff --git a/package.json b/package.json index 19c9abb..5fba726 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "devDependencies": { "@playwright/test": "^1.44.1", "@types/node": "20.14.5", + "dotenv": "^16.4.5", "fast-glob": "^3.3.2", "monocart-reporter": "^2.5.0", "open-cli": "^8.0.0", diff --git a/playwright.config.ts b/playwright.config.ts index 19be182..79faaef 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -6,8 +6,9 @@ import { getMonocartReporterOptions } from "./playwright.monocart-reporter"; * Read environment variables from file. * https://github.com/motdotla/dotenv */ -// import dotenv from 'dotenv'; -// dotenv.config({ path: path.resolve(__dirname, '.env') }); +import dotenv from 'dotenv'; +dotenv.config({ path: "./.env.local" }); + const _testResultsDir = path.resolve("./e2e-test-results"); const _codeCoverageDir = path.resolve(_testResultsDir, "code-coverage"); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d3b8fb..7a74b67 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,6 +33,9 @@ importers: '@types/node': specifier: 20.14.5 version: 20.14.5 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 fast-glob: specifier: ^3.3.2 version: 3.3.2 @@ -742,6 +745,10 @@ packages: dompurify@3.1.5: resolution: {integrity: sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==} + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -2624,6 +2631,8 @@ snapshots: dompurify@3.1.5: {} + dotenv@16.4.5: {} + ee-first@1.1.1: {} eight-colors@1.3.0: {} diff --git a/tests/e2e/homepage.spec.ts b/tests/e2e/homepage.spec.ts deleted file mode 100644 index f07c640..0000000 --- a/tests/e2e/homepage.spec.ts +++ /dev/null @@ -1,18 +0,0 @@ -// !! PLEASE READ !! -/* -Coverage for E2E effectively works, but the coverage is not using the sourcemaps properly, so coverage doesn't mean much. -We've decided to leave the infrastructure (coverage uses `monocart`) with its configuration for posteriority in case we need them. -E2E testing is more relevant knowing **if they pass or not**. -*/ - - -import { test, expect } from "../_shared/app-fixtures"; // we use the overriden functions to get coverage - -test.describe("homepage", () => { - test("is mounted", async ({ page }) => { - await page.goto("/"); - - // Expect a title "to contain" a substring. - await expect(page).toHaveTitle(/Welcome to Nextra Documentation/); - }); -}); diff --git a/tests/e2e/test.spec.ts b/tests/e2e/test.spec.ts new file mode 100644 index 0000000..1926632 --- /dev/null +++ b/tests/e2e/test.spec.ts @@ -0,0 +1,55 @@ +// !! PLEASE READ !! +/* +Coverage for E2E effectively works, but the coverage is not using the sourcemaps properly, so coverage doesn't mean much. +We've decided to leave the infrastructure (coverage uses `monocart`) with its configuration for posteriority in case we need them. +E2E testing is more relevant knowing **if they pass or not**. +*/ + +import { test, expect } from "../_shared/app-fixtures"; // we use the overriden functions to get coverage + +const BASE_URL = "http://localhost:3000" + +test.describe("homepage", () => { + test("is mounted", async ({ page }) => { + await page.goto("/"); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Welcome to Nextra Documentation/); + }); +}); + +test("Basic auth", async ({ page, browser }) => { + if (!process.env.TEST_PASSWORD) throw new TypeError("Missing TEST_PASSWORD"); + + await test.step("should login", async () => { + await page.goto(`${BASE_URL}/api/auth/signin`); + await page.getByLabel("Password").fill(process.env.TEST_PASSWORD ?? ""); + await page.getByRole("button", { name: "Sign in with Password" }).click(); + await page.waitForURL(`${BASE_URL}`); + + const sessionResponse = await page.goto( + `${BASE_URL}/api/auth/session` + ) + const session = await sessionResponse?.json() ?? {} + expect(session.user.email).toEqual("bob@alice.com") + expect(session.user.name).toEqual("Bob Alice") + expect(session.user.image).toEqual("") + }); + + await test.step("should logout", async () => { + // Move to the homepage to log out + await page.goto("/"); + + await page.getByText("SIGN OUT").click(); + expect(page.url()).toBe(`${BASE_URL}/`) + + await page.waitForURL(`${BASE_URL}`) + await page.waitForTimeout(1000); // wait for sign out to persist in IDP + + const sessionResponse = await page.goto( + `${BASE_URL}/api/auth/session` + ) + const session = await sessionResponse?.json() + expect(session).toBe(null) + }); +}); From 96bd19f2f6242f54dd07370c935a90ab85764af9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 18:08:14 +0400 Subject: [PATCH 20/75] chore: Renaming e2e testing scripts in package.json --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 5fba726..905be60 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,8 @@ "prebuild": "npm run private-route-gen", "build": "next build", "start": "next start", - "test": "npx playwright test", - "test:show-report": "npx monocart show-report ./e2e-test-results/monocart-report.html", - "coverage:show-report": "open-cli ./e2e-test-results/code-coverage/v8/index.html" + "e2e:test": "npx playwright test", + "e2e:test:show-report": "npx monocart show-report ./e2e-test-results/monocart-report.html" }, "dependencies": { "next": "^14.2.4", From b1f008879ba882e0fc53c402d1b59790508a2be8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 18:44:25 +0400 Subject: [PATCH 21/75] fix: Fixing CI --- .github/workflows/playwright.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 9662b54..4424f19 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -19,6 +19,8 @@ jobs: run: pnpm exec playwright install --with-deps - name: Run Playwright tests run: pnpm exec playwright test + env: + TEST_PASSWORD: password - uses: actions/upload-artifact@v4 if: always() with: From f42de88191056a5d03934d792428a3889d4988e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 21 Jun 2024 18:48:03 +0400 Subject: [PATCH 22/75] fix: Trying to fix env var issue on CI --- .github/workflows/playwright.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 4424f19..27396cb 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -20,6 +20,7 @@ jobs: - name: Run Playwright tests run: pnpm exec playwright test env: + AUTH_SECRET: some_nextauth_secret TEST_PASSWORD: password - uses: actions/upload-artifact@v4 if: always() From 2f03effe00e72c12313b4fa058c785a965f555e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Mon, 24 Jun 2024 12:31:06 +0100 Subject: [PATCH 23/75] chore: misc. --- README.md | 6 ++++-- auth.ts | 4 ++-- components/LoginOrUserInfo/index.tsx | 4 ++-- pages/index.mdx | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 341c750..c9ad1eb 100644 --- a/README.md +++ b/README.md @@ -744,9 +744,9 @@ and inside this one create a file called `index.ts` (`components/LoginOrUserInfo ```ts import { signOut, signIn } from "next-auth/react"; -import { Session } from "next-auth"; +import { DefaultSession } from "next-auth"; -export function LoginOrUserInfo({ session } : Readonly<{session: Session}>) { +export function LoginOrUserInfo({ session } : Readonly<{session: DefaultSession}>) { if (session?.user) { return (
@@ -1507,6 +1507,8 @@ Hurray! 🎉 + + # Change theme - custom theme is the only option diff --git a/auth.ts b/auth.ts index 6abb3a9..864da14 100644 --- a/auth.ts +++ b/auth.ts @@ -19,9 +19,9 @@ declare module "next-auth" { * with the new ones defined above. To keep the default session user properties, * we need to add them back into the newly declared interface. */ - user: DefaultSession["user"] & { + user: { role?: string; - }; + } & DefaultSession["user"]; } interface User { diff --git a/components/LoginOrUserInfo/index.tsx b/components/LoginOrUserInfo/index.tsx index 98f6594..661cd58 100644 --- a/components/LoginOrUserInfo/index.tsx +++ b/components/LoginOrUserInfo/index.tsx @@ -1,7 +1,7 @@ import { signOut, signIn } from "next-auth/react"; -import { Session } from "next-auth"; +import { DefaultSession } from "next-auth"; -export function LoginOrUserInfo({ session } : Readonly<{session: Session}>) { +export default function LoginOrUserInfo({ session } : Readonly<{session: DefaultSession}>) { if (session?.user) { return (
diff --git a/pages/index.mdx b/pages/index.mdx index aa19993..4aa7bff 100644 --- a/pages/index.mdx +++ b/pages/index.mdx @@ -2,7 +2,7 @@ import { auth } from "@/auth.ts" import { useData } from 'nextra/data' import Link from 'next/link' import { signOut } from "next-auth/react" -import { LoginOrUserInfo } from "@/components/LoginOrUserInfo" +import LoginOrUserInfo from "@/components/LoginOrUserInfo" export async function getServerSideProps(ctx) { const session = await auth(ctx) From ee78b27e1144a78cdaa4582842337680ee3fb9df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 25 Jun 2024 09:55:28 +0100 Subject: [PATCH 24/75] feat: Adding component testing with Jest. --- jest.config.ts | 30 + package.json | 8 +- playwright.config.ts | 2 +- pnpm-lock.yaml | 3008 ++++++++++++++++++++++++++- tests/unit/LoginOrUserInfo.test.tsx | 37 + 5 files changed, 2987 insertions(+), 98 deletions(-) create mode 100644 jest.config.ts create mode 100644 tests/unit/LoginOrUserInfo.test.tsx diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..f0f1815 --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,30 @@ +/** + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ + +import type { Config } from "jest"; +import nextJest from "next/jest.js"; + +const createJestConfig = nextJest({ + // Provide the path to your Next.js app to load next.config.js and .env files in your test environment + dir: "./", +}); + +const config: Config = { + collectCoverage: true, + collectCoverageFrom: ["components/**/*.tsx", "app/**/*.ts", "pages/*"], + coverageDirectory: "coverage", + coveragePathIgnorePatterns: ["/node_modules/"], + coverageProvider: "v8", + + moduleDirectories: ["node_modules"], + moduleNameMapper: { + 'next-auth/(.*)': '/node_modules/next-auth/$1' + }, + + testEnvironment: "jsdom", + testPathIgnorePatterns: ["tests/e2e"], +}; + +export default createJestConfig(config); diff --git a/package.json b/package.json index 905be60..b14be36 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "build": "next build", "start": "next start", "e2e:test": "npx playwright test", - "e2e:test:show-report": "npx monocart show-report ./e2e-test-results/monocart-report.html" + "e2e:test:show-report": "npx monocart show-report ./e2e-test-results/monocart-report.html", + "test": "jest" }, "dependencies": { "next": "^14.2.4", @@ -18,9 +19,14 @@ }, "devDependencies": { "@playwright/test": "^1.44.1", + "@testing-library/jest-dom": "^6.4.6", + "@testing-library/react": "^16.0.0", + "@types/jest": "^29.5.12", "@types/node": "20.14.5", "dotenv": "^16.4.5", "fast-glob": "^3.3.2", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", "monocart-reporter": "^2.5.0", "open-cli": "^8.0.0", "ts-morph": "^22.0.0", diff --git a/playwright.config.ts b/playwright.config.ts index 79faaef..d1533a8 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -25,7 +25,7 @@ let _reporters: ReporterDescription[] = [ * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', + testDir: './tests/e2e', /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7a74b67..5b8b6ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,16 +10,16 @@ importers: dependencies: next: specifier: ^14.2.4 - version: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-auth: specifier: 5.0.0-beta.19 - version: 5.0.0-beta.19(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.9.14)(react@18.3.1) + version: 5.0.0-beta.19(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.9.14)(react@18.3.1) nextra: specifier: ^2.13.4 - version: 2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.13.4(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) nextra-theme-docs: specifier: ^2.13.4 - version: 2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 2.13.4(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: specifier: ^18.3.1 version: 18.3.1 @@ -30,6 +30,15 @@ importers: '@playwright/test': specifier: ^1.44.1 version: 1.44.1 + '@testing-library/jest-dom': + specifier: ^6.4.6 + version: 6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5))) + '@testing-library/react': + specifier: ^16.0.0 + version: 16.0.0(@testing-library/dom@10.2.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@types/jest': + specifier: ^29.5.12 + version: 29.5.12 '@types/node': specifier: 20.14.5 version: 20.14.5 @@ -39,9 +48,15 @@ importers: fast-glob: specifier: ^3.3.2 version: 3.3.2 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + jest-environment-jsdom: + specifier: ^29.7.0 + version: 29.7.0 monocart-reporter: specifier: ^2.5.0 - version: 2.5.0 + version: 2.5.2 open-cli: specifier: ^8.0.0 version: 8.0.0 @@ -57,6 +72,13 @@ importers: packages: + '@adobe/css-tools@4.4.0': + resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + '@auth/core@0.32.0': resolution: {integrity: sha512-3+ssTScBd+1fd0/fscAyQN1tSygXzuhysuVVzB942ggU4mdfiTbv36P0ccVnExKWYJKvu3E2r3/zxXCCAmTOrg==} peerDependencies: @@ -71,10 +93,177 @@ packages: nodemailer: optional: true + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.24.7': + resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.24.7': + resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.24.7': + resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.24.7': + resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-environment-visitor@7.24.7': + resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-function-name@7.24.7': + resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-hoist-variables@7.24.7': + resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.24.7': + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.24.7': + resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.24.7': + resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-simple-access@7.24.7': + resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.24.7': + resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.24.7': + resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.24.7': + resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.24.7': + resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.24.7': + resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.24.7': + resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/runtime@7.24.7': resolution: {integrity: sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==} engines: {node: '>=6.9.0'} + '@babel/template@7.24.7': + resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.24.7': + resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.24.7': + resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@braintree/sanitize-url@6.0.4': resolution: {integrity: sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==} @@ -89,13 +278,98 @@ packages: react: ^16 || ^17 || ^18 react-dom: ^16 || ^17 || ^18 + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@29.7.0': + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/core@29.7.0': + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/reporters@29.7.0': + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/source-map@29.6.3': + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-result@29.7.0': + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-sequencer@29.7.0': + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + '@jridgewell/sourcemap-codec@1.4.15': resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} @@ -246,8 +520,8 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@panva/hkdf@1.1.1': - resolution: {integrity: sha512-dhPeilub1NuIG0X5Kvhh9lH4iW3ZsHlnzwgwbOlgwQ2wG1IqFzsgHqmKPk3WzsdWAeaxKJxgM0+W433RmN45GA==} + '@panva/hkdf@1.2.0': + resolution: {integrity: sha512-97ZQvZJ4gJhi24Io6zI+W7B67I82q1I8i3BSzQ4OyZj1z4OW87/ruF26lrMES58inTKLy2KgVIDcx8PU4AaANQ==} '@playwright/test@1.44.1': resolution: {integrity: sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==} @@ -257,20 +531,69 @@ packages: '@popperjs/core@2.11.8': resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} '@swc/helpers@0.5.5': resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==} - '@tanstack/react-virtual@3.5.1': - resolution: {integrity: sha512-jIsuhfgy8GqA67PdWqg73ZB2LFE+HD9hjWL1L6ifEIZVyZVAKpYmgUG4WsKQ005aEyImJmbuimPiEvc57IY0Aw==} + '@tanstack/react-virtual@3.7.0': + resolution: {integrity: sha512-3RtOwEU1HKS4iFBoTcCrV3Szqt4KoERMhZr8v57dvnh5o70sR9GAdF+0aE/qhiOmePrKujGwAayFNJSr/8Dbqw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@tanstack/virtual-core@3.5.1': - resolution: {integrity: sha512-046+AUSiDru/V9pajE1du8WayvBKeCvJ2NmKPy/mR8/SbKKrqmSbj7LJBfXE+nSq4f5TBXvnCzu0kcYebI9WdQ==} + '@tanstack/virtual-core@3.7.0': + resolution: {integrity: sha512-p0CWuqn+n8iZmsL7/l0Xg7kbyIKnHNqkEJkMDOkg4x3Ni3LohszmnJY8FPhTgG7Ad9ZFGcdKmn1R1mKUGEh9Xg==} + + '@testing-library/dom@10.2.0': + resolution: {integrity: sha512-CytIvb6tVOADRngTHGWNxH8LPgO/3hi/BdCEHOf7Qd2GvZVClhVP0Wo/QHzWhpki49Bk0b4VT6xpt3fx8HTSIw==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.4.6': + resolution: {integrity: sha512-8qpnGVincVDLEcQXWaHOf6zmlbwTKc6Us6PPu4CRnPXCzo2OGBS5cwgMMOWdxDpEz1mkbvXHpEy99M5Yvt682w==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + peerDependencies: + '@jest/globals': '>= 28' + '@types/bun': latest + '@types/jest': '>= 28' + jest: '>= 28' + vitest: '>= 0.32' + peerDependenciesMeta: + '@jest/globals': + optional: true + '@types/bun': + optional: true + '@types/jest': + optional: true + jest: + optional: true + vitest: + optional: true + + '@testing-library/react@16.0.0': + resolution: {integrity: sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.0 + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true '@theguild/remark-mermaid@0.0.5': resolution: {integrity: sha512-e+ZIyJkEv9jabI4m7q29wZtZv+2iwPGsXJ2d46Zi7e+QcFudiyuqhLhHG/3gX3ZEB+hxTch+fpItyMS8jwbIcw==} @@ -283,6 +606,10 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + '@ts-morph/common@0.23.0': resolution: {integrity: sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==} @@ -301,6 +628,21 @@ packages: '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} @@ -322,15 +664,33 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + '@types/hast@2.3.10': resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==} '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.12': + resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} + '@types/js-yaml@4.0.9': resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + '@types/jsdom@20.0.1': + resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} + '@types/katex@0.16.7': resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==} @@ -355,19 +715,38 @@ packages: '@types/react@18.3.3': resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/unist@2.0.10': resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} '@types/unist@3.0.2': resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.32': + resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} + acorn-globals@7.0.1: + resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -382,6 +761,18 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + ansi-sequence-parser@1.1.1: resolution: {integrity: sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==} @@ -389,6 +780,18 @@ packages: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + arch@2.2.0: resolution: {integrity: sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==} @@ -404,16 +807,50 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + astring@1.8.6: resolution: {integrity: sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==} hasBin: true + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-preset-current-node-syntax@1.0.1: + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + bail@2.0.2: resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} @@ -421,6 +858,17 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browserslist@4.23.1: + resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} @@ -433,6 +881,18 @@ packages: resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==} engines: {node: '>= 6.0.0'} + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + caniuse-lite@1.0.30001636: resolution: {integrity: sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==} @@ -443,6 +903,22 @@ packages: resolution: {integrity: sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==} engines: {node: '>=4'} + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -455,6 +931,13 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cjs-module-lexer@1.3.1: + resolution: {integrity: sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q==} + client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} @@ -462,6 +945,10 @@ packages: resolution: {integrity: sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw==} engines: {node: '>=4'} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -473,12 +960,26 @@ packages: code-block-writer@13.0.1: resolution: {integrity: sha512-c5or4P6erEA69TxaxTNcHUNcIn+oyxSRTOWV+pSYF+z4epXqNvwvJ70XPGjPNgue83oAFAPBRQYwpAJ/Hpe/Sg==} + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + color-name@1.1.3: resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + comma-separated-tokens@2.0.3: resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} @@ -493,6 +994,9 @@ packages: compute-scroll-into-view@3.1.0: resolution: {integrity: sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==} + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + console-grid@2.2.2: resolution: {integrity: sha512-ohlgXexdDTKLNsZz7DSJuCAwmRc8omSS61txOk39W3NOthgKGr1a1jJpZ5BCQe4PlrwMw01OvPQ1Bl3G7Y/uFg==} @@ -504,6 +1008,9 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie@0.6.0: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} @@ -515,16 +1022,38 @@ packages: cose-base@1.0.3: resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} + create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + crypto-random-string@4.0.0: resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} engines: {node: '>=12'} + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + + cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + + cssom@0.5.0: + resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + + cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -679,6 +1208,10 @@ packages: dagre-d3-es@7.0.10: resolution: {integrity: sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A==} + data-urls@3.0.2: + resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} + engines: {node: '>=12'} + dayjs@1.11.11: resolution: {integrity: sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==} @@ -691,12 +1224,27 @@ packages: supports-color: optional: true + decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + decode-named-character-reference@1.0.2: resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + deep-equal@1.0.1: resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + default-browser-id@5.0.0: resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} engines: {node: '>=18'} @@ -712,6 +1260,10 @@ packages: delaunator@5.0.1: resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} @@ -731,9 +1283,17 @@ packages: resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -742,6 +1302,17 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + + domexception@4.0.0: + resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} + engines: {node: '>=12'} + deprecated: Use your platform's native DOMException instead + dompurify@3.1.5: resolution: {integrity: sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA==} @@ -755,9 +1326,19 @@ packages: eight-colors@1.3.0: resolution: {integrity: sha512-hVoK898cR71ADj7L1LZWaECLaSkzzPtqGXIaKv4K6Pzb72QgjLVsQaNI+ELDQQshzFvgp5xTPkaYkPGqw3YR+g==} + electron-to-chromium@1.4.810: + resolution: {integrity: sha512-Kaxhu4T7SJGpRQx99tq216gCq2nMxJo+uuT6uzz9l8TVN2stL7M06MIIXAtr9jsrLs2Glflgf2vMQRepxawOdQ==} + elkjs@0.9.3: resolution: {integrity: sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==} + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -766,6 +1347,13 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -773,15 +1361,28 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + escape-string-regexp@5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + estree-util-attach-comments@2.1.1: resolution: {integrity: sha512-+5Ba/xGGS6mnwFbXIuQiDPTbuTxuMCooq3arVv7gPZtYpjp+VXH/NkHAP35OOefPhNG/UGqU3vt/LTABwcHX0w==} @@ -804,10 +1405,26 @@ packages: estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + execa@0.8.0: resolution: {integrity: sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==} engines: {node: '>=4'} + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + extend-shallow@2.0.1: resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} engines: {node: '>=0.10.0'} @@ -819,9 +1436,15 @@ packages: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + file-type@18.7.0: resolution: {integrity: sha512-ihHtXRzXEziMrQ56VSgU7wkxh55iNchFkosu7Y9/S+tXHdKyrGjVK0ujbqNnsxzea+78MaLhN6PGmfYSAv1ACw==} engines: {node: '>=14.16'} @@ -830,21 +1453,52 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + flexsearch@0.7.43: resolution: {integrity: sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==} focus-visible@5.2.0: resolution: {integrity: sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ==} + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + get-stdin@9.0.0: resolution: {integrity: sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==} engines: {node: '>=12'} @@ -853,6 +1507,10 @@ packages: resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==} engines: {node: '>=4'} + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + git-up@7.0.0: resolution: {integrity: sha512-ONdIrbBCFusq1Oy0sC71F5azx8bVkvtZtMJAsv+a6lz5YAmbNnLD6HAB4gptHZVLPR8S2/kVN6Gab7lryq5+lQ==} @@ -866,6 +1524,14 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -877,6 +1543,10 @@ packages: resolution: {integrity: sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==} engines: {node: '>=0.10.0'} + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -893,6 +1563,10 @@ packages: resolution: {integrity: sha512-FwO1BUVWkyHasWDW4S8o0ssQXjvyghLV2rfVhnN36b2bbcj45eGiuzdn9XOvOpjV3TKQD7Gm2BWNXdE9V4KKYg==} engines: {node: '>=12'} + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + hast-util-from-dom@5.0.0: resolution: {integrity: sha512-d6235voAp/XR3Hh5uy7aGLbM3S4KamdW0WEgOaU1YoewnuYw4HXb5eRtv9g65m/RFGEfUY1Mw4UqCc5Y8L4Stg==} @@ -929,6 +1603,10 @@ packages: hastscript@8.0.0: resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + html-encoding-sniffer@3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -943,6 +1621,18 @@ packages: resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} engines: {node: '>= 0.6'} + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -950,6 +1640,23 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -972,10 +1679,17 @@ packages: is-alphanumerical@2.0.1: resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-buffer@2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} + is-core-module@2.14.0: + resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} + engines: {node: '>= 0.4'} + is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -992,6 +1706,14 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + is-generator-function@1.0.10: resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} engines: {node: '>= 0.4'} @@ -1024,6 +1746,9 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-reference@3.0.2: resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} @@ -1034,6 +1759,10 @@ packages: resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} engines: {node: '>=0.10.0'} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1049,16 +1778,166 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.2: + resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} + engines: {node: '>=10'} + istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + istanbul-reports@3.1.7: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} - jose@5.4.0: - resolution: {integrity: sha512-6rpxTHPAQyWMb9A35BroFl1Sp0ST3DpPcm5EVIxZxdH+e0Hv9fwhyB3XLKFUcHNpdSDnETmBfuPPTTlYz5+USw==} + jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@29.7.0: + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-environment-jsdom@29.7.0: + resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jose@5.4.1: + resolution: {integrity: sha512-U6QajmpV/nhL9SyfAewo000fkiRQ+Yd2H0lBxJJ9apjpOgkOcBQJWOrMo917lxLptdS/n/o/xPzMkXhF46K8hQ==} js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1071,6 +1950,28 @@ packages: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsdom@20.0.3: + resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} + engines: {node: '>=14'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jsonc-parser@3.2.1: resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} @@ -1089,6 +1990,10 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -1110,12 +2015,26 @@ packages: layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -1126,6 +2045,13 @@ packages: lru-cache@4.1.5: resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + lz-utils@2.0.2: resolution: {integrity: sha512-i1PJN4hNEevkrvLMqNWCCac1BcB5SRaghywG7HVzWOyVkFOasLCG19ND1sY1F/ZEsM6SnGtoXyBWnmfqOM5r6g==} @@ -1136,6 +2062,9 @@ packages: make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + markdown-extensions@1.1.1: resolution: {integrity: sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==} engines: {node: '>=0.10.0'} @@ -1211,6 +2140,9 @@ packages: resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} engines: {node: '>=16.10'} + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -1353,6 +2285,17 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@9.0.4: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} @@ -1365,8 +2308,8 @@ packages: monocart-code-viewer@1.1.4: resolution: {integrity: sha512-ehSe1lBG7D1VDVLjTkHV63J3zAgzyhlC9OaxOri7D0X4L5/EcZUOG5TEoMmYErL+YGSOQXghU9kSSAelwNnp1Q==} - monocart-coverage-reports@2.8.4: - resolution: {integrity: sha512-RpE7O8+p9DMrBLSnW6gALEy0nn69cxFd6QJd7Cv+ERNFPAEqBur1jV3DQcpcr00C6IcnCm2Pw5/aTpsGNUGdUQ==} + monocart-coverage-reports@2.8.5: + resolution: {integrity: sha512-IUt+0spPBKCrgDX+knp0yg1SqQBMrgV16DL3KTObvTwudpbwQRgO141tWvisfowbR849j9yCVDWAGaD8+56LeA==} hasBin: true monocart-formatter@3.0.0: @@ -1375,8 +2318,8 @@ packages: monocart-locator@1.0.0: resolution: {integrity: sha512-qIHJ7f99miF2HbVUWAFKR93SfgGYpFPUCQPmW9q1VXU9onxMUFJxhQDdG3HkEteogUbsKB7Gr5MRgjzcIxwTaQ==} - monocart-reporter@2.5.0: - resolution: {integrity: sha512-atEEsAtBpUSYf+eahmRCAIzOZi7X03qD82qHeiuxrRWpevrODNBG38FamXB1+EWINx5Cs1YdDpzFnDk9tzXHSg==} + monocart-reporter@2.5.2: + resolution: {integrity: sha512-gjfGAT9Vjh88b/dnXJNY37VLJwhL8wyaOy0JLKLb5HdS6/t/5eg+rUNM6V3YwT7hC/KfFvlCQ4a0swviVDwPxQ==} hasBin: true mri@1.2.0: @@ -1391,6 +2334,9 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + negotiator@0.6.3: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} @@ -1466,6 +2412,12 @@ packages: react: '>=16.13.1' react-dom: '>=16.13.1' + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + nodemailer@6.9.14: resolution: {integrity: sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==} engines: {node: '>=6.0.0'} @@ -1473,21 +2425,39 @@ packages: non-layered-tidy-tree-layout@2.0.2: resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + npm-to-yarn@2.2.1: resolution: {integrity: sha512-O/j/ROyX0KGLG7O6Ieut/seQ0oiTpHF2tXAcFbpdTLQFiaNtkyTXXocM1fwpaa60dg1qpWj0nHlbNhx6qwuENQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - oauth4webapi@2.10.4: - resolution: {integrity: sha512-DSoj8QoChzOCQlJkRmYxAJCIpnXFW32R0Uq7avyghIeB6iJq0XAblOD7pcq3mx4WEBDwMuKr0Y1qveCBleG2Xw==} + nwsapi@2.2.10: + resolution: {integrity: sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==} + + oauth4webapi@2.11.1: + resolution: {integrity: sha512-aNzOnL98bL6izG97zgnZs1PFEyO4WDVRhz2Pd066NPak44w5ESLRCYmJIyey8avSBPOMtBjhF3ZDDm7bIb7UOg==} on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + only@0.0.2: resolution: {integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==} @@ -1504,13 +2474,29 @@ packages: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + parse-entities@4.0.1: resolution: {integrity: sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==} + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + parse-numeric-range@1.3.0: resolution: {integrity: sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==} @@ -1530,10 +2516,25 @@ packages: path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@2.0.1: resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} engines: {node: '>=4'} + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + peek-readable@5.0.0: resolution: {integrity: sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==} engines: {node: '>=14.16'} @@ -1548,6 +2549,14 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + playwright-core@1.44.1: resolution: {integrity: sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==} engines: {node: '>=16'} @@ -1570,9 +2579,21 @@ packages: preact@10.11.3: resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + pretty-format@3.8.0: resolution: {integrity: sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + property-information@6.5.0: resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} @@ -1582,6 +2603,19 @@ packages: pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -1590,6 +2624,12 @@ packages: peerDependencies: react: ^18.3.1 + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -1605,6 +2645,10 @@ packages: reading-time@1.5.0: resolution: {integrity: sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==} + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -1641,6 +2685,29 @@ packages: remove-accents@0.5.0: resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -1668,6 +2735,10 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -1678,6 +2749,10 @@ packages: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + semver@7.6.2: resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} @@ -1690,16 +2765,27 @@ packages: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + shebang-regex@1.0.0: resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} engines: {node: '>=0.10.0'} + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + shiki@0.14.7: resolution: {integrity: sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==} signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -1712,6 +2798,13 @@ packages: resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} engines: {node: '>=0.10.0'} + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} engines: {node: '>= 8'} @@ -1722,6 +2815,10 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + statuses@1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} engines: {node: '>= 0.6'} @@ -1730,20 +2827,48 @@ packages: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} stringify-entities@4.0.4: resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + strip-bom-string@1.0.0: resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} engines: {node: '>=0.10.0'} + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + strip-eof@1.0.0: resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} engines: {node: '>=0.10.0'} + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + strtok3@7.0.0: resolution: {integrity: sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==} engines: {node: '>=14.16'} @@ -1771,10 +2896,25 @@ packages: resolution: {integrity: sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw==} engines: {node: '>=4'} + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + temp-dir@3.0.0: resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} engines: {node: '>=14.16'} @@ -1783,6 +2923,10 @@ packages: resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} engines: {node: '>=14.16'} + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + title@3.5.3: resolution: {integrity: sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q==} hasBin: true @@ -1791,6 +2935,13 @@ packages: resolution: {integrity: sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw==} engines: {node: '>=0.10.0'} + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1803,6 +2954,14 @@ packages: resolution: {integrity: sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==} engines: {node: '>=14.16'} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@3.0.0: + resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} + engines: {node: '>=12'} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -1840,6 +2999,14 @@ packages: turbogrid@3.2.0: resolution: {integrity: sha512-c+2qrCGWzoYpLlxtHgRJ4V5dDRE9fUT7D9maxtdBCqJ0NzCdY+x7xF3/F6cG/+n3VIzKfIS+p9Z/0YMQPf6k/Q==} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + type-fest@1.4.0: resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} engines: {node: '>=10'} @@ -1921,6 +3088,19 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + update-browserslist-db@1.0.16: + resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1936,6 +3116,10 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -1964,29 +3148,102 @@ packages: vscode-textmate@8.0.0: resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==} + w3c-xmlserializer@4.0.0: + resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} + engines: {node: '>=14'} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + web-namespaces@2.0.1: resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} web-worker@1.3.0: resolution: {integrity: sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA==} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@2.0.0: + resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} + engines: {node: '>=12'} + + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + + whatwg-url@11.0.0: + resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} + engines: {node: '>=12'} + which@1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} hasBin: true - yallist@2.1.2: - resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true - ylru@1.4.0: - resolution: {integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==} - engines: {node: '>= 4.0.0'} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@2.1.2: + resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + ylru@1.4.0: + resolution: {integrity: sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==} + engines: {node: '>= 4.0.0'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} zod@3.23.8: @@ -1997,22 +3254,236 @@ packages: snapshots: + '@adobe/css-tools@4.4.0': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + '@auth/core@0.32.0(nodemailer@6.9.14)': dependencies: - '@panva/hkdf': 1.1.1 + '@panva/hkdf': 1.2.0 '@types/cookie': 0.6.0 cookie: 0.6.0 - jose: 5.4.0 - oauth4webapi: 2.10.4 + jose: 5.4.1 + oauth4webapi: 2.11.1 preact: 10.11.3 preact-render-to-string: 5.2.3(preact@10.11.3) optionalDependencies: nodemailer: 6.9.14 + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 + + '@babel/compat-data@7.24.7': {} + + '@babel/core@7.24.7': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helpers': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/template': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + convert-source-map: 2.0.0 + debug: 4.3.5 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + + '@babel/helper-compilation-targets@7.24.7': + dependencies: + '@babel/compat-data': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + browserslist: 4.23.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-environment-visitor@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/helper-function-name@7.24.7': + dependencies: + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 + + '@babel/helper-hoist-variables@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/helper-module-imports@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.24.7': {} + + '@babel/helper-simple-access@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-split-export-declaration@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/helper-string-parser@7.24.7': {} + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/helper-validator-option@7.24.7': {} + + '@babel/helpers@7.24.7': + dependencies: + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.1 + + '@babel/parser@7.24.7': + dependencies: + '@babel/types': 7.24.7 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/runtime@7.24.7': dependencies: regenerator-runtime: 0.14.1 + '@babel/template@7.24.7': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + + '@babel/traverse@7.24.7': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + debug: 4.3.5 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.24.7': + dependencies: + '@babel/helper-string-parser': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + + '@bcoe/v8-coverage@0.2.3': {} + '@braintree/sanitize-url@6.0.4': {} '@cspotcode/source-map-support@0.8.1': @@ -2021,15 +3492,200 @@ snapshots: '@headlessui/react@1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/react-virtual': 3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@tanstack/react-virtual': 3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) client-only: 0.0.1 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.7 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + jest-mock: 29.7.0 + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 20.14.5 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/reporters@29.7.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + '@types/node': 20.14.5 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.24.7 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.7 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 20.14.5 + '@types/yargs': 17.0.32 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/set-array@1.2.1': {} + '@jridgewell/sourcemap-codec@1.4.15': {} + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 @@ -2151,7 +3807,7 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@panva/hkdf@1.1.1': {} + '@panva/hkdf@1.2.0': {} '@playwright/test@1.44.1': dependencies: @@ -2159,6 +3815,16 @@ snapshots: '@popperjs/core@2.11.8': {} + '@sinclair/typebox@0.27.8': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + '@swc/counter@0.1.3': {} '@swc/helpers@0.5.5': @@ -2166,13 +3832,48 @@ snapshots: '@swc/counter': 0.1.3 tslib: 2.6.3 - '@tanstack/react-virtual@3.5.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@tanstack/react-virtual@3.7.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@tanstack/virtual-core': 3.5.1 + '@tanstack/virtual-core': 3.7.0 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@tanstack/virtual-core@3.5.1': {} + '@tanstack/virtual-core@3.7.0': {} + + '@testing-library/dom@10.2.0': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/runtime': 7.24.7 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.4.6(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)))': + dependencies: + '@adobe/css-tools': 4.4.0 + '@babel/runtime': 7.24.7 + aria-query: 5.3.0 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + optionalDependencies: + '@jest/globals': 29.7.0 + '@types/jest': 29.5.12 + jest: 29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + + '@testing-library/react@16.0.0(@testing-library/dom@10.2.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.24.7 + '@testing-library/dom': 10.2.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.3 '@theguild/remark-mermaid@0.0.5(react@18.3.1)': dependencies: @@ -2189,6 +3890,8 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tootallnate/once@2.0.0': {} + '@ts-morph/common@0.23.0': dependencies: fast-glob: 3.3.2 @@ -2208,6 +3911,29 @@ snapshots: dependencies: '@types/estree': 1.0.5 + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.24.7 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.24.7 + '@types/cookie@0.6.0': {} '@types/d3-scale-chromatic@3.0.3': {} @@ -2228,6 +3954,10 @@ snapshots: '@types/estree@1.0.5': {} + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 20.14.5 + '@types/hast@2.3.10': dependencies: '@types/unist': 2.0.10 @@ -2236,8 +3966,29 @@ snapshots: dependencies: '@types/unist': 3.0.2 + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.12': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + '@types/js-yaml@4.0.9': {} + '@types/jsdom@20.0.1': + dependencies: + '@types/node': 20.14.5 + '@types/tough-cookie': 4.0.5 + parse5: 7.1.2 + '@types/katex@0.16.7': {} '@types/mdast@3.0.15': @@ -2263,17 +4014,34 @@ snapshots: '@types/prop-types': 15.7.12 csstype: 3.1.3 + '@types/stack-utils@2.0.3': {} + + '@types/tough-cookie@4.0.5': {} + '@types/unist@2.0.10': {} '@types/unist@3.0.2': {} + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.32': + dependencies: + '@types/yargs-parser': 21.0.3 + '@ungap/structured-clone@1.2.0': {} + abab@2.0.6: {} + accepts@1.3.8: dependencies: mime-types: 2.1.35 negotiator: 0.6.3 + acorn-globals@7.0.1: + dependencies: + acorn: 8.12.0 + acorn-walk: 8.3.3 + acorn-jsx@5.3.2(acorn@8.12.0): dependencies: acorn: 8.12.0 @@ -2284,12 +4052,35 @@ snapshots: acorn@8.12.0: {} + agent-base@6.0.2: + dependencies: + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-regex@5.0.1: {} + ansi-sequence-parser@1.1.1: {} ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + arch@2.2.0: {} arg@1.0.0: {} @@ -2302,12 +4093,75 @@ snapshots: argparse@2.0.1: {} + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + astring@1.8.6: {} + asynckit@0.4.0: {} + + babel-jest@29.7.0(@babel/core@7.24.7): + dependencies: + '@babel/core': 7.24.7 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.24.7) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.24.7 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + + babel-preset-current-node-syntax@1.0.1(@babel/core@7.24.7): + dependencies: + '@babel/core': 7.24.7 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.7) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.7) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.7) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.7) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.7) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.7) + + babel-preset-jest@29.6.3(@babel/core@7.24.7): + dependencies: + '@babel/core': 7.24.7 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.7) + bail@2.0.2: {} balanced-match@1.0.2: {} + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 @@ -2316,6 +4170,19 @@ snapshots: dependencies: fill-range: 7.1.1 + browserslist@4.23.1: + dependencies: + caniuse-lite: 1.0.30001636 + electron-to-chromium: 1.4.810 + node-releases: 2.0.14 + update-browserslist-db: 1.0.16(browserslist@4.23.1) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + bundle-name@4.1.0: dependencies: run-applescript: 7.0.0 @@ -2329,6 +4196,12 @@ snapshots: mime-types: 2.1.35 ylru: 1.4.0 + callsites@3.1.0: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + caniuse-lite@1.0.30001636: {} ccount@2.0.1: {} @@ -2339,6 +4212,24 @@ snapshots: escape-string-regexp: 1.0.5 supports-color: 4.5.0 + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + char-regex@1.0.2: {} + character-entities-html4@2.1.0: {} character-entities-legacy@3.0.0: {} @@ -2347,6 +4238,10 @@ snapshots: character-reference-invalid@2.0.1: {} + ci-info@3.9.0: {} + + cjs-module-lexer@1.3.1: {} + client-only@0.0.1: {} clipboardy@1.2.2: @@ -2354,18 +4249,36 @@ snapshots: arch: 2.2.0 execa: 0.8.0 + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + clsx@2.1.1: {} co@4.6.0: {} code-block-writer@13.0.1: {} + collect-v8-coverage@1.0.2: {} + color-convert@1.9.3: dependencies: color-name: 1.1.3 + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + color-name@1.1.3: {} + color-name@1.1.4: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + comma-separated-tokens@2.0.3: {} commander@7.2.0: {} @@ -2374,6 +4287,8 @@ snapshots: compute-scroll-into-view@3.1.0: {} + concat-map@0.0.1: {} + console-grid@2.2.2: {} content-disposition@0.5.4: @@ -2382,6 +4297,8 @@ snapshots: content-type@1.0.5: {} + convert-source-map@2.0.0: {} + cookie@0.6.0: {} cookies@0.9.1: @@ -2393,6 +4310,21 @@ snapshots: dependencies: layout-base: 1.0.2 + create-jest@29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + create-require@1.1.1: {} cross-spawn@5.1.0: @@ -2401,10 +4333,26 @@ snapshots: shebang-command: 1.2.0 which: 1.3.1 + cross-spawn@7.0.3: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + crypto-random-string@4.0.0: dependencies: type-fest: 1.4.0 + css.escape@1.5.1: {} + + cssom@0.3.8: {} + + cssom@0.5.0: {} + + cssstyle@2.3.0: + dependencies: + cssom: 0.3.8 + csstype@3.1.3: {} cytoscape-cose-bilkent@4.1.0(cytoscape@3.29.2): @@ -2586,18 +4534,30 @@ snapshots: d3: 7.9.0 lodash-es: 4.17.21 + data-urls@3.0.2: + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + dayjs@1.11.11: {} debug@4.3.5: dependencies: ms: 2.1.2 + decimal.js@10.4.3: {} + decode-named-character-reference@1.0.2: dependencies: character-entities: 2.0.2 + dedent@1.5.3: {} + deep-equal@1.0.1: {} + deepmerge@4.3.1: {} + default-browser-id@5.0.0: {} default-browser@5.2.1: @@ -2611,6 +4571,8 @@ snapshots: dependencies: robust-predicates: 3.0.2 + delayed-stream@1.0.0: {} + delegates@1.0.0: {} depd@1.1.2: {} @@ -2621,14 +4583,26 @@ snapshots: destroy@1.2.0: {} + detect-newline@3.1.0: {} + devlop@1.1.0: dependencies: dequal: 2.0.3 + diff-sequences@29.6.3: {} + diff@4.0.2: {} diff@5.2.0: {} + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + domexception@4.0.0: + dependencies: + webidl-conversions: 7.0.0 + dompurify@3.1.5: {} dotenv@16.4.5: {} @@ -2637,20 +4611,44 @@ snapshots: eight-colors@1.3.0: {} + electron-to-chromium@1.4.810: {} + elkjs@0.9.3: {} + emittery@0.13.1: {} + + emoji-regex@8.0.0: {} + encodeurl@1.0.2: {} entities@4.5.0: {} + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + escalade@3.1.2: {} + escape-html@1.0.3: {} escape-string-regexp@1.0.5: {} + escape-string-regexp@2.0.0: {} + escape-string-regexp@5.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + esprima@4.0.1: {} + estraverse@5.3.0: {} + estree-util-attach-comments@2.1.1: dependencies: '@types/estree': 1.0.5 @@ -2682,6 +4680,8 @@ snapshots: dependencies: '@types/estree': 1.0.5 + esutils@2.0.3: {} + execa@0.8.0: dependencies: cross-spawn: 5.1.0 @@ -2692,6 +4692,28 @@ snapshots: signal-exit: 3.0.7 strip-eof: 1.0.0 + execa@5.1.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exit@0.1.2: {} + + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + extend-shallow@2.0.1: dependencies: is-extendable: 0.1.1 @@ -2706,10 +4728,16 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.7 + fast-json-stable-stringify@2.1.0: {} + fastq@1.17.1: dependencies: reusify: 1.0.4 + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + file-type@18.7.0: dependencies: readable-web-to-node-stream: 3.0.2 @@ -2720,19 +4748,45 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + flexsearch@0.7.43: {} focus-visible@5.2.0: {} + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + fresh@0.5.2: {} + fs.realpath@1.0.0: {} + fsevents@2.3.2: optional: true + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-package-type@0.1.0: {} + get-stdin@9.0.0: {} get-stream@3.0.0: {} + get-stream@6.0.1: {} + git-up@7.0.0: dependencies: is-ssh: 1.4.0 @@ -2748,6 +4802,17 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@7.2.3: + 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 + + globals@11.12.0: {} + graceful-fs@4.2.11: {} gray-matter@4.0.3: @@ -2759,6 +4824,8 @@ snapshots: has-flag@2.0.0: {} + has-flag@3.0.0: {} + has-flag@4.0.0: {} has-symbols@1.0.3: {} @@ -2773,6 +4840,10 @@ snapshots: sort-keys: 5.0.0 type-fest: 1.4.0 + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + hast-util-from-dom@5.0.0: dependencies: '@types/hast': 3.0.4 @@ -2877,6 +4948,10 @@ snapshots: property-information: 6.5.0 space-separated-tokens: 2.0.2 + html-encoding-sniffer@3.0.0: + dependencies: + whatwg-encoding: 2.0.0 + html-escaper@2.0.2: {} html-void-elements@3.0.0: {} @@ -2894,12 +4969,43 @@ snapshots: statuses: 1.5.0 toidentifier: 1.0.1 + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.3.5 + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 ieee754@1.2.1: {} + import-local@3.1.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + inherits@2.0.4: {} inline-style-parser@0.1.1: {} @@ -2908,79 +5014,445 @@ snapshots: internmap@2.0.3: {} - intersection-observer@0.12.2: {} + intersection-observer@0.12.2: {} + + is-alphabetical@2.0.1: {} + + is-alphanumerical@2.0.1: + dependencies: + is-alphabetical: 2.0.1 + is-decimal: 2.0.1 + + is-arrayish@0.2.1: {} + + is-buffer@2.0.5: {} + + is-core-module@2.14.0: + dependencies: + hasown: 2.0.2 + + is-decimal@2.0.1: {} + + is-docker@3.0.0: {} + + is-extendable@0.1.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-fn@2.1.0: {} + + is-generator-function@1.0.10: + dependencies: + has-tostringtag: 1.0.2 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-hexadecimal@2.0.1: {} + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-number@7.0.0: {} + + is-obj@3.0.0: {} + + is-plain-obj@3.0.0: {} + + is-plain-obj@4.1.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-reference@3.0.2: + dependencies: + '@types/estree': 1.0.5 + + is-ssh@1.4.0: + dependencies: + protocols: 2.0.1 + + is-stream@1.1.0: {} + + is-stream@2.0.1: {} + + is-stream@3.0.0: {} + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isexe@2.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.24.7 + '@babel/parser': 7.24.7 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.2: + dependencies: + '@babel/core': 7.24.7 + '@babel/parser': 7.24.7 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.6.2 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.3.5 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jest-changed-files@29.7.0: + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + + jest-circus@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color - is-alphabetical@2.0.1: {} + jest-cli@29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)): + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-config@29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)): + dependencies: + '@babel/core': 7.24.7 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.24.7) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.7 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.14.5 + ts-node: 10.9.2(@types/node@20.14.5)(typescript@5.4.5) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color - is-alphanumerical@2.0.1: + jest-diff@29.7.0: dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 - is-buffer@2.0.5: {} + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 - is-decimal@2.0.1: {} + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 - is-docker@3.0.0: {} + jest-environment-jsdom@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/jsdom': 20.0.1 + '@types/node': 20.14.5 + jest-mock: 29.7.0 + jest-util: 29.7.0 + jsdom: 20.0.3 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate - is-extendable@0.1.1: {} + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + jest-mock: 29.7.0 + jest-util: 29.7.0 - is-extglob@2.1.1: {} + jest-get-type@29.6.3: {} - is-generator-function@1.0.10: + jest-haste-map@29.7.0: dependencies: - has-tostringtag: 1.0.2 + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 20.14.5 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.7 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 - is-glob@4.0.3: + jest-leak-detector@29.7.0: dependencies: - is-extglob: 2.1.1 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 - is-hexadecimal@2.0.1: {} + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 - is-inside-container@1.0.0: + jest-message-util@29.7.0: dependencies: - is-docker: 3.0.0 + '@babel/code-frame': 7.24.7 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.7 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 - is-number@7.0.0: {} + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + jest-util: 29.7.0 - is-obj@3.0.0: {} + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 - is-plain-obj@3.0.0: {} + jest-regex-util@29.6.3: {} - is-plain-obj@4.1.0: {} + jest-resolve-dependencies@29.7.0: + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color - is-reference@3.0.2: + jest-resolve@29.7.0: dependencies: - '@types/estree': 1.0.5 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.8 + resolve.exports: 2.0.2 + slash: 3.0.0 - is-ssh@1.4.0: + jest-runner@29.7.0: dependencies: - protocols: 2.0.1 + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color - is-stream@1.1.0: {} + jest-runtime@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + chalk: 4.1.2 + cjs-module-lexer: 1.3.1 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color - is-stream@3.0.0: {} + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.7) + '@babel/types': 7.24.7 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.24.7) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.6.2 + transitivePeerDependencies: + - supports-color - is-wsl@3.1.0: + jest-util@29.7.0: dependencies: - is-inside-container: 1.0.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 - isexe@2.0.0: {} + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 - istanbul-lib-coverage@3.2.2: {} + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.14.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 - istanbul-lib-report@3.0.1: + jest-worker@29.7.0: dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 + '@types/node': 20.14.5 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 - istanbul-reports@3.1.7: + jest@29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)): dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@20.14.5)(ts-node@10.9.2(@types/node@20.14.5)(typescript@5.4.5)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node - jose@5.4.0: {} + jose@5.4.1: {} js-tokens@4.0.0: {} @@ -2993,6 +5465,45 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@20.0.3: + dependencies: + abab: 2.0.6 + acorn: 8.12.0 + acorn-globals: 7.0.1 + cssom: 0.5.0 + cssstyle: 2.3.0 + data-urls: 3.0.2 + decimal.js: 10.4.3 + domexception: 4.0.0 + escodegen: 2.1.0 + form-data: 4.0.0 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.10 + parse5: 7.1.2 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + ws: 8.17.1 + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@2.5.2: {} + + json-parse-even-better-errors@2.3.1: {} + + json5@2.2.3: {} + jsonc-parser@3.2.1: {} katex@0.16.10: @@ -3007,6 +5518,8 @@ snapshots: kind-of@6.0.3: {} + kleur@3.0.3: {} + kleur@4.1.5: {} koa-compose@4.1.0: {} @@ -3048,10 +5561,20 @@ snapshots: layout-base@1.0.2: {} + leven@3.1.0: {} + + lines-and-columns@1.2.4: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + lodash-es@4.17.21: {} lodash.get@4.4.2: {} + lodash@4.17.21: {} + longest-streak@3.1.0: {} loose-envify@1.4.0: @@ -3063,6 +5586,12 @@ snapshots: pseudomap: 1.0.2 yallist: 2.1.2 + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lz-string@1.5.0: {} + lz-utils@2.0.2: {} make-dir@4.0.0: @@ -3071,6 +5600,10 @@ snapshots: make-error@1.3.6: {} + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + markdown-extensions@1.1.1: {} markdown-table@3.0.3: {} @@ -3254,6 +5787,8 @@ snapshots: meow@12.1.1: {} + merge-stream@2.0.0: {} + merge2@1.4.1: {} mermaid@10.9.1: @@ -3583,6 +6118,14 @@ snapshots: dependencies: mime-db: 1.52.0 + mimic-fn@2.1.0: {} + + min-indent@1.0.1: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 @@ -3591,7 +6134,7 @@ snapshots: monocart-code-viewer@1.1.4: {} - monocart-coverage-reports@2.8.4: + monocart-coverage-reports@2.8.5: dependencies: console-grid: 2.2.2 eight-colors: 1.3.0 @@ -3608,14 +6151,14 @@ snapshots: monocart-locator@1.0.0: {} - monocart-reporter@2.5.0: + monocart-reporter@2.5.2: dependencies: console-grid: 2.2.2 eight-colors: 1.3.0 koa: 2.15.3 koa-static-resolver: 1.0.6 lz-utils: 2.0.2 - monocart-coverage-reports: 2.8.4 + monocart-coverage-reports: 2.8.5 monocart-formatter: 3.0.0 monocart-locator: 1.0.0 nodemailer: 6.9.14 @@ -3629,12 +6172,14 @@ snapshots: nanoid@3.3.7: {} + natural-compare@1.4.0: {} + negotiator@0.6.3: {} - next-auth@5.0.0-beta.19(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.9.14)(react@18.3.1): + next-auth@5.0.0-beta.19(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nodemailer@6.9.14)(react@18.3.1): dependencies: '@auth/core': 0.32.0(nodemailer@6.9.14) - next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 optionalDependencies: nodemailer: 6.9.14 @@ -3650,19 +6195,19 @@ snapshots: transitivePeerDependencies: - supports-color - next-seo@6.5.0(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-seo@6.5.0(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next-themes@0.2.1(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-themes@0.2.1(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@next/env': 14.2.4 '@swc/helpers': 0.5.5 @@ -3672,7 +6217,7 @@ snapshots: postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - styled-jsx: 5.1.1(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.24.7)(react@18.3.1) optionalDependencies: '@next/swc-darwin-arm64': 14.2.4 '@next/swc-darwin-x64': 14.2.4 @@ -3688,7 +6233,7 @@ snapshots: - '@babel/core' - babel-plugin-macros - nextra-theme-docs@2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextra-theme-docs@2.13.4(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(nextra@2.13.4(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@popperjs/core': 2.11.8 @@ -3699,16 +6244,16 @@ snapshots: git-url-parse: 13.1.1 intersection-observer: 0.12.2 match-sorter: 6.3.4 - next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - next-seo: 6.5.0(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - next-themes: 0.2.1(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - nextra: 2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-seo: 6.5.0(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next-themes: 0.2.1(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + nextra: 2.13.4(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) scroll-into-view-if-needed: 3.1.0 zod: 3.23.8 - nextra@2.13.4(next@14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + nextra@2.13.4(next@14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@headlessui/react': 1.7.19(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@mdx-js/mdx': 2.3.0 @@ -3722,7 +6267,7 @@ snapshots: gray-matter: 4.0.3 katex: 0.16.10 lodash.get: 4.4.2 - next: 14.2.4(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 14.2.4(@babel/core@7.24.7)(@playwright/test@1.44.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-mdx-remote: 4.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) p-limit: 3.1.0 react: 18.3.1 @@ -3742,22 +6287,42 @@ snapshots: transitivePeerDependencies: - supports-color + node-int64@0.4.0: {} + + node-releases@2.0.14: {} + nodemailer@6.9.14: {} non-layered-tidy-tree-layout@2.0.2: {} + normalize-path@3.0.0: {} + npm-run-path@2.0.2: dependencies: path-key: 2.0.1 + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + npm-to-yarn@2.2.1: {} - oauth4webapi@2.10.4: {} + nwsapi@2.2.10: {} + + oauth4webapi@2.11.1: {} on-finished@2.4.1: dependencies: ee-first: 1.1.1 + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + only@0.0.2: {} open-cli@8.0.0: @@ -3777,10 +6342,20 @@ snapshots: p-finally@1.0.0: {} + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-try@2.2.0: {} + parse-entities@4.0.1: dependencies: '@types/unist': 2.0.10 @@ -3792,6 +6367,13 @@ snapshots: is-decimal: 2.0.1 is-hexadecimal: 2.0.1 + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.24.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + parse-numeric-range@1.3.0: {} parse-path@7.0.0: @@ -3810,8 +6392,16 @@ snapshots: path-browserify@1.0.1: {} + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + path-key@2.0.1: {} + path-key@3.1.1: {} + + path-parse@1.0.7: {} + peek-readable@5.0.0: {} periscopic@3.1.0: @@ -3824,6 +6414,12 @@ snapshots: picomatch@2.3.1: {} + pirates@4.0.6: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + playwright-core@1.44.1: {} playwright@1.44.1: @@ -3845,14 +6441,39 @@ snapshots: preact@10.11.3: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + pretty-format@3.8.0: {} + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + property-information@6.5.0: {} protocols@2.0.1: {} pseudomap@1.0.2: {} + psl@1.9.0: {} + + punycode@2.3.1: {} + + pure-rand@6.1.0: {} + + querystringify@2.2.0: {} + queue-microtask@1.2.3: {} react-dom@18.3.1(react@18.3.1): @@ -3861,6 +6482,10 @@ snapshots: react: 18.3.1 scheduler: 0.23.2 + react-is@17.0.2: {} + + react-is@18.3.1: {} + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -3877,6 +6502,11 @@ snapshots: reading-time@1.5.0: {} + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + regenerator-runtime@0.14.1: {} rehype-katex@7.0.0: @@ -3949,6 +6579,24 @@ snapshots: remove-accents@0.5.0: {} + require-directory@2.1.1: {} + + requires-port@1.0.0: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@5.0.0: {} + + resolve.exports@2.0.2: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.14.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + reusify@1.0.4: {} robust-predicates@3.0.2: {} @@ -3969,6 +6617,10 @@ snapshots: safer-buffer@2.1.2: {} + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -3982,6 +6634,8 @@ snapshots: extend-shallow: 2.0.1 kind-of: 6.0.3 + semver@6.3.1: {} + semver@7.6.2: {} setprototypeof@1.2.0: {} @@ -3990,8 +6644,14 @@ snapshots: dependencies: shebang-regex: 1.0.0 + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + shebang-regex@1.0.0: {} + shebang-regex@3.0.0: {} + shiki@0.14.7: dependencies: ansi-sequence-parser: 1.1.1 @@ -4001,6 +6661,8 @@ snapshots: signal-exit@3.0.7: {} + sisteransi@1.0.5: {} + slash@3.0.0: {} sort-keys@5.0.0: @@ -4009,16 +6671,38 @@ snapshots: source-map-js@1.2.0: {} + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + source-map@0.7.4: {} space-separated-tokens@2.0.2: {} sprintf-js@1.0.3: {} + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + statuses@1.5.0: {} streamsearch@1.1.0: {} + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -4028,10 +6712,24 @@ snapshots: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + strip-bom-string@1.0.0: {} + strip-bom@4.0.0: {} + strip-eof@1.0.0: {} + strip-final-newline@2.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + strtok3@7.0.0: dependencies: '@tokenizer/token': 0.3.0 @@ -4041,10 +6739,12 @@ snapshots: dependencies: inline-style-parser: 0.1.1 - styled-jsx@5.1.1(react@18.3.1): + styled-jsx@5.1.1(@babel/core@7.24.7)(react@18.3.1): dependencies: client-only: 0.0.1 react: 18.3.1 + optionalDependencies: + '@babel/core': 7.24.7 stylis@4.3.2: {} @@ -4052,10 +6752,22 @@ snapshots: dependencies: has-flag: 2.0.0 + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-tree@3.2.4: {} + temp-dir@3.0.0: {} tempy@3.1.0: @@ -4065,6 +6777,12 @@ snapshots: type-fest: 2.19.0 unique-string: 3.0.0 + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + title@3.5.3: dependencies: arg: 1.0.0 @@ -4074,6 +6792,10 @@ snapshots: titleize@1.0.0: {} + tmpl@1.0.5: {} + + to-fast-properties@2.0.0: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -4085,6 +6807,17 @@ snapshots: '@tokenizer/token': 0.3.0 ieee754: 1.2.1 + tough-cookie@4.1.4: + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@3.0.0: + dependencies: + punycode: 2.3.1 + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -4120,6 +6853,10 @@ snapshots: turbogrid@3.2.0: {} + type-detect@4.0.8: {} + + type-fest@0.21.3: {} + type-fest@1.4.0: {} type-fest@2.19.0: {} @@ -4231,6 +6968,19 @@ snapshots: unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 + universalify@0.2.0: {} + + update-browserslist-db@1.0.16(browserslist@4.23.1): + dependencies: + browserslist: 4.23.1 + escalade: 3.1.2 + picocolors: 1.0.1 + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + util-deprecate@1.0.2: {} uuid@9.0.1: {} @@ -4244,6 +6994,12 @@ snapshots: v8-compile-cache-lib@3.0.1: {} + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + vary@1.1.2: {} vfile-location@5.0.2: @@ -4284,16 +7040,76 @@ snapshots: vscode-textmate@8.0.0: {} + w3c-xmlserializer@4.0.0: + dependencies: + xml-name-validator: 4.0.0 + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + web-namespaces@2.0.1: {} web-worker@1.3.0: {} + webidl-conversions@7.0.0: {} + + whatwg-encoding@2.0.0: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@3.0.0: {} + + whatwg-url@11.0.0: + dependencies: + tr46: 3.0.0 + webidl-conversions: 7.0.0 + which@1.3.1: dependencies: isexe: 2.0.0 + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrappy@1.0.2: {} + + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + + ws@8.17.1: {} + + xml-name-validator@4.0.0: {} + + xmlchars@2.2.0: {} + + y18n@5.0.8: {} + yallist@2.1.2: {} + yallist@3.1.1: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.1.2 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + ylru@1.4.0: {} yn@3.1.1: {} diff --git a/tests/unit/LoginOrUserInfo.test.tsx b/tests/unit/LoginOrUserInfo.test.tsx new file mode 100644 index 0000000..9010e51 --- /dev/null +++ b/tests/unit/LoginOrUserInfo.test.tsx @@ -0,0 +1,37 @@ +import { render, screen } from "@testing-library/react"; +import LoginOrUserInfo from "@/components/LoginOrUserInfo"; +import { DefaultSession } from "next-auth"; +import { signOut, signIn } from "next-auth/react"; + +// Mocking `signIn` and `signOut` API calls +jest.mock("next-auth/react", () => { + return { + signIn: jest.fn(() => "signed in"), + signOut: jest.fn(() => "signed out"), + }; +}); + +describe("LoginOrUserInfo", () => { + it('shows "Sign In" button when no session is found', () => { + const session: DefaultSession = { + expires: "", + }; + + render(); + expect(screen.getByRole("button", { name: "SIGN IN" })).toBeDefined(); + }); + + it('shows "Sign Out" button and user info when session is found', () => { + const username = "AlpheyaUsername" + const session: DefaultSession = { + user: { + name: username, + }, + expires: Date.now().toString(), + }; + + render(); + expect(screen.getByRole("button", { name: "SIGN OUT" })).toBeDefined(); + expect(screen.getByText(username)).toBeDefined(); + }); +}); From b96c0d242911c2ea63d7c63364f34bfcfde7fd4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 25 Jun 2024 10:26:30 +0100 Subject: [PATCH 25/75] refactor: Moving source files to `src` folder. --- .gitignore | 3 +- README.md | 60 +++++++++++++++++++ app/api/auth/[...nextauth]/route.ts | 2 - package.json | 2 +- src/app/api/auth/[...nextauth]/route.ts | 2 + auth.ts => src/auth.ts | 0 .../components}/LoginOrUserInfo/index.tsx | 0 .../generatePrivateRoutes.ts | 0 middleware.ts => src/middleware.ts | 2 +- {pages => src/pages}/_meta.json | 0 {pages => src/pages}/about.mdx | 0 {pages => src/pages}/api_reference.mdx | 0 {pages => src/pages}/contact.mdx | 0 {pages => src/pages}/index.mdx | 4 +- {pages => src/pages}/reference_api/_meta.json | 0 {pages => src/pages}/reference_api/about.mdx | 0 .../pages}/reference_api/mega_private.mdx | 0 .../reference_api/mega_private/_meta.json | 0 .../reference_api/mega_private/hello.mdx | 0 {pages => src/pages}/reference_api/users.mdx | 0 tests/unit/LoginOrUserInfo.test.tsx | 2 +- tsconfig.json | 2 +- 22 files changed, 70 insertions(+), 9 deletions(-) delete mode 100644 app/api/auth/[...nextauth]/route.ts create mode 100644 src/app/api/auth/[...nextauth]/route.ts rename auth.ts => src/auth.ts (100%) rename {components => src/components}/LoginOrUserInfo/index.tsx (100%) rename generatePrivateRoutes.ts => src/generatePrivateRoutes.ts (100%) rename middleware.ts => src/middleware.ts (97%) rename {pages => src/pages}/_meta.json (100%) rename {pages => src/pages}/about.mdx (100%) rename {pages => src/pages}/api_reference.mdx (100%) rename {pages => src/pages}/contact.mdx (100%) rename {pages => src/pages}/index.mdx (92%) rename {pages => src/pages}/reference_api/_meta.json (100%) rename {pages => src/pages}/reference_api/about.mdx (100%) rename {pages => src/pages}/reference_api/mega_private.mdx (100%) rename {pages => src/pages}/reference_api/mega_private/_meta.json (100%) rename {pages => src/pages}/reference_api/mega_private/hello.mdx (100%) rename {pages => src/pages}/reference_api/users.mdx (100%) diff --git a/.gitignore b/.gitignore index 7d79707..b60e595 100644 --- a/.gitignore +++ b/.gitignore @@ -138,4 +138,5 @@ dist /e2e-test-results/ /playwright-report/ /blob-report/ -/playwright/.cache/ \ No newline at end of file +/playwright/.cache/ +/.swc \ No newline at end of file diff --git a/README.md b/README.md index c9ad1eb..0c0a7a9 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one - [4.3.1 Defining `_meta.json` files with `private` properties](#431-defining-_metajson-files-with-private-properties) - [4.3.2 Implementing the function](#432-implementing-the-function) - [4.4 Running the script before building](#44-running-the-script-before-building) + - [5. Moving source files to `src` folder](#5-moving-source-files-to-src-folder) - [Change theme](#change-theme) - [zones](#zones) @@ -1506,6 +1507,65 @@ Hurray! 🎉 > it's simply a warning. +## 5. Moving source files to `src` folder + +Before proceeding, let's do some cleaning up 🧹. +Right now, we have some source files +(like `auth.ts`, `middleware.ts`, `generatePrivateRoutes.ts`) +mixed with several configuration files at root level. + +Luckily for us, `Next.js` supports adding a `src` folder +so we can keep the root directory focused on configuration files +and the `src` folder to source files. + +Let's move our source code to a `src` folder! +Start by creating it at root level. +Then, move the following items into it: +- the `app` folder. +- the `components` folder. +- the `pages` folder. +- `auth.ts`, `middleware.ts` and `generatePrivateRoutes.ts` files. + +Now we have to change some imports. +Check the following changes in each file so everything works again! + +```ts +// src/pages/index.mdx +import { auth } from "@/src/auth.ts" // changed from `@/auth.ts` +import { useData } from 'nextra/data' +import Link from 'next/link' +import { signOut } from "next-auth/react" +import LoginOrUserInfo from "@/src/components/LoginOrUserInfo" // changed from `@/components/LoginOrUserInfo` +``` + +```ts +// src/middleware.ts +"server only"; + +import { auth } from "@/src/auth"; // changed from `@/auth.ts` +import { NextResponse } from "next/server"; +``` + +```ts +// tests/unit/LoginOrUserInfo.test.tsx +import { render, screen } from "@testing-library/react"; +import LoginOrUserInfo from "@/src/components/LoginOrUserInfo"; // changed from `@/components/LoginOrUserInfo` +import { DefaultSession } from "next-auth"; +import { signOut, signIn } from "next-auth/react"; +``` + +```json +// package.json +"private-route-gen": "ts-node src/generatePrivateRoutes.ts", +``` + +And you're sorted! +We now have all our source files inside `src`, +the tests inside `tests`, +and all the configuration files at root level. + + + diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts deleted file mode 100644 index 0cf1408..0000000 --- a/app/api/auth/[...nextauth]/route.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { handlers } from "@/auth" // Referring to the auth.ts we just created -export const { GET, POST } = handlers \ No newline at end of file diff --git a/package.json b/package.json index b14be36..e62bb6e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "scripts": { - "private-route-gen": "ts-node generatePrivateRoutes.ts", + "private-route-gen": "ts-node src/generatePrivateRoutes.ts", "dev": "npm run private-route-gen && next", "prebuild": "npm run private-route-gen", "build": "next build", diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts new file mode 100644 index 0000000..2be797e --- /dev/null +++ b/src/app/api/auth/[...nextauth]/route.ts @@ -0,0 +1,2 @@ +import { handlers } from "@/src/auth" // Referring to the auth.ts we just created +export const { GET, POST } = handlers \ No newline at end of file diff --git a/auth.ts b/src/auth.ts similarity index 100% rename from auth.ts rename to src/auth.ts diff --git a/components/LoginOrUserInfo/index.tsx b/src/components/LoginOrUserInfo/index.tsx similarity index 100% rename from components/LoginOrUserInfo/index.tsx rename to src/components/LoginOrUserInfo/index.tsx diff --git a/generatePrivateRoutes.ts b/src/generatePrivateRoutes.ts similarity index 100% rename from generatePrivateRoutes.ts rename to src/generatePrivateRoutes.ts diff --git a/middleware.ts b/src/middleware.ts similarity index 97% rename from middleware.ts rename to src/middleware.ts index 6c83918..b910ad2 100644 --- a/middleware.ts +++ b/src/middleware.ts @@ -1,6 +1,6 @@ "server only"; -import { auth } from "@/auth"; +import { auth } from "@/src/auth"; import { NextResponse } from "next/server"; // !!!! DO NOT CHANGE THE NAME OF THE VARIABLE !!!! diff --git a/pages/_meta.json b/src/pages/_meta.json similarity index 100% rename from pages/_meta.json rename to src/pages/_meta.json diff --git a/pages/about.mdx b/src/pages/about.mdx similarity index 100% rename from pages/about.mdx rename to src/pages/about.mdx diff --git a/pages/api_reference.mdx b/src/pages/api_reference.mdx similarity index 100% rename from pages/api_reference.mdx rename to src/pages/api_reference.mdx diff --git a/pages/contact.mdx b/src/pages/contact.mdx similarity index 100% rename from pages/contact.mdx rename to src/pages/contact.mdx diff --git a/pages/index.mdx b/src/pages/index.mdx similarity index 92% rename from pages/index.mdx rename to src/pages/index.mdx index 4aa7bff..c113335 100644 --- a/pages/index.mdx +++ b/src/pages/index.mdx @@ -1,8 +1,8 @@ -import { auth } from "@/auth.ts" +import { auth } from "@/src/auth.ts" import { useData } from 'nextra/data' import Link from 'next/link' import { signOut } from "next-auth/react" -import LoginOrUserInfo from "@/components/LoginOrUserInfo" +import LoginOrUserInfo from "@/src/components/LoginOrUserInfo" export async function getServerSideProps(ctx) { const session = await auth(ctx) diff --git a/pages/reference_api/_meta.json b/src/pages/reference_api/_meta.json similarity index 100% rename from pages/reference_api/_meta.json rename to src/pages/reference_api/_meta.json diff --git a/pages/reference_api/about.mdx b/src/pages/reference_api/about.mdx similarity index 100% rename from pages/reference_api/about.mdx rename to src/pages/reference_api/about.mdx diff --git a/pages/reference_api/mega_private.mdx b/src/pages/reference_api/mega_private.mdx similarity index 100% rename from pages/reference_api/mega_private.mdx rename to src/pages/reference_api/mega_private.mdx diff --git a/pages/reference_api/mega_private/_meta.json b/src/pages/reference_api/mega_private/_meta.json similarity index 100% rename from pages/reference_api/mega_private/_meta.json rename to src/pages/reference_api/mega_private/_meta.json diff --git a/pages/reference_api/mega_private/hello.mdx b/src/pages/reference_api/mega_private/hello.mdx similarity index 100% rename from pages/reference_api/mega_private/hello.mdx rename to src/pages/reference_api/mega_private/hello.mdx diff --git a/pages/reference_api/users.mdx b/src/pages/reference_api/users.mdx similarity index 100% rename from pages/reference_api/users.mdx rename to src/pages/reference_api/users.mdx diff --git a/tests/unit/LoginOrUserInfo.test.tsx b/tests/unit/LoginOrUserInfo.test.tsx index 9010e51..b218ace 100644 --- a/tests/unit/LoginOrUserInfo.test.tsx +++ b/tests/unit/LoginOrUserInfo.test.tsx @@ -1,5 +1,5 @@ import { render, screen } from "@testing-library/react"; -import LoginOrUserInfo from "@/components/LoginOrUserInfo"; +import LoginOrUserInfo from "@/src/components/LoginOrUserInfo"; import { DefaultSession } from "next-auth"; import { signOut, signIn } from "next-auth/react"; diff --git a/tsconfig.json b/tsconfig.json index aff8218..ebb1273 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,7 +28,7 @@ "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", - "app/lib/placeholder-data.js", + "src/app/lib/placeholder-data.js", "scripts/seed.js" ], "exclude": ["node_modules"], From 6caba61decab486d64d6252a3a7fadcde388495b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 25 Jun 2024 12:00:14 +0100 Subject: [PATCH 26/75] test: Adding component testing to components. --- .vscode/launch.json | 20 +++++++++++++++++++ jest.config.ts | 4 ++-- .../{ => components}/LoginOrUserInfo.test.tsx | 0 3 files changed, 22 insertions(+), 2 deletions(-) rename tests/unit/{ => components}/LoginOrUserInfo.test.tsx (100%) diff --git a/.vscode/launch.json b/.vscode/launch.json index 4bf1534..10d9105 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,26 @@ { "version": "0.2.0", "configurations": [ + { + "name": "Jest file", + "type": "pwa-node", + "request": "launch", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/jest", + "args": [ + "${fileBasenameNoExtension}", + "--runInBand", + "--watch", + "--coverage=false", + "--no-cache" + ], + "cwd": "${workspaceRoot}", + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "sourceMaps": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest/bin/jest" + } + }, { "name": "Next.js: debug server-side", "type": "node-terminal", diff --git a/jest.config.ts b/jest.config.ts index f0f1815..43597fa 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -13,14 +13,14 @@ const createJestConfig = nextJest({ const config: Config = { collectCoverage: true, - collectCoverageFrom: ["components/**/*.tsx", "app/**/*.ts", "pages/*"], + collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}", "!/node_modules/"], coverageDirectory: "coverage", coveragePathIgnorePatterns: ["/node_modules/"], coverageProvider: "v8", moduleDirectories: ["node_modules"], moduleNameMapper: { - 'next-auth/(.*)': '/node_modules/next-auth/$1' + "next-auth/(.*)": "/node_modules/next-auth/$1", }, testEnvironment: "jsdom", diff --git a/tests/unit/LoginOrUserInfo.test.tsx b/tests/unit/components/LoginOrUserInfo.test.tsx similarity index 100% rename from tests/unit/LoginOrUserInfo.test.tsx rename to tests/unit/components/LoginOrUserInfo.test.tsx From 8ae1cff03ff59496af2e4cb24df7a00f0895bb22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Tue, 25 Jun 2024 17:10:26 +0100 Subject: [PATCH 27/75] test: Adding way to test script for generating private routes. --- .vscode/launch.json | 7 ++ README.md | 44 ++++++----- package.json | 3 +- src/generatePrivateRoutes.ts | 44 ++++++----- tests/unit/generatePrivateRoutes.test.tsx | 94 +++++++++++++++++++++++ 5 files changed, 152 insertions(+), 40 deletions(-) create mode 100644 tests/unit/generatePrivateRoutes.test.tsx diff --git a/.vscode/launch.json b/.vscode/launch.json index 10d9105..27b0629 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,6 +1,13 @@ { "version": "0.2.0", "configurations": [ + { + "type": "node-terminal", + "name": "Debug Current TS File (ts-node)", + "request": "launch", + "command": "npx ts-node -- ${fileBasenameNoExtension}", + "cwd": "${fileDirname}" + }, { "name": "Jest file", "type": "pwa-node", diff --git a/README.md b/README.md index 0c0a7a9..4641e11 100644 --- a/README.md +++ b/README.md @@ -1241,24 +1241,30 @@ import { globSync } from "fast-glob"; // - - - - - - - - - - - - - - - - - - - - - - - // `middleware.ts` is changed by executing the code below. -const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated -const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) - -// Get private routes -const pagesDir = path.join(__dirname, DIRECTORY); -const privateRoutes = getPrivateRoutes(pagesDir); - -// Initialize the project and source file -const project = new Project(); -const sourceFile = project.addSourceFileAtPath(path.resolve(__dirname, "middleware.ts")); - -// Find the variable to replace and change it's declaration -const variable = sourceFile.getVariableDeclaration(CONST_VARIABLE_NAME); -if (variable) { - variable.setInitializer(JSON.stringify(privateRoutes)); - sourceFile.saveSync(); -} else { - console.error("Variable not found in `middleware.ts`. File wasn't changed."); +export function changeMiddleware() { + const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated + const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) + + // Get private routes + const pagesDir = path.join(__dirname, DIRECTORY); + const privateRoutes = getPrivateRoutes(pagesDir); + + // Initialize the project and source file + const project = new Project(); + const sourceFile = project.addSourceFileAtPath(path.resolve(__dirname, "middleware.ts")); + + // Find the variable to replace and change it's declaration + const variable = sourceFile.getVariableDeclaration(CONST_VARIABLE_NAME); + if (variable) { + variable.setInitializer(JSON.stringify(privateRoutes)); + sourceFile.saveSync(); + } else { + console.error("Variable not found in `middleware.ts`. File wasn't changed."); + } +} + +export default { + changeMiddleware: () => changeMiddleware() } ``` @@ -1470,7 +1476,7 @@ Head over there and change the scripts, like so: ```json "scripts": { - "private-route-gen": "ts-node generatePrivateRoutes.ts", + "private-route-gen": "ts-node -e \"import gen from './src/generatePrivateRoutes'; gen.changeMiddleware()\"", "dev": "npm run private-route-gen && next", "prebuild": "npm run private-route-gen", "build": "next build", diff --git a/package.json b/package.json index e62bb6e..5b3d03c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "scripts": { - "private-route-gen": "ts-node src/generatePrivateRoutes.ts", + "private-route-gen": "ts-node -e \"import gen from './src/generatePrivateRoutes'; gen.changeMiddleware()\"", "dev": "npm run private-route-gen && next", "prebuild": "npm run private-route-gen", "build": "next build", @@ -10,7 +10,6 @@ "test": "jest" }, "dependencies": { - "next": "^14.2.4", "next-auth": "5.0.0-beta.19", "nextra": "^2.13.4", "nextra-theme-docs": "^2.13.4", diff --git a/src/generatePrivateRoutes.ts b/src/generatePrivateRoutes.ts index 2d9947c..d5a0be5 100644 --- a/src/generatePrivateRoutes.ts +++ b/src/generatePrivateRoutes.ts @@ -24,7 +24,7 @@ type PrivateRoutes = { * @param pagesDir path to recursively look for. * @returns map of private routes as key and array of roles that are permitted to access the route. */ -function getPrivateRoutes(pagesDir: string): PrivateRoutes { +export function getPrivateRoutes(pagesDir: string): PrivateRoutes { let privateRoutes: PrivateRoutes = {}; // Find all _meta.json files recursively @@ -92,22 +92,28 @@ function getPrivateRoutes(pagesDir: string): PrivateRoutes { // - - - - - - - - - - - - - - - - - - - - - - - // `middleware.ts` is changed by executing the code below. -const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated -const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) - -// Get private routes -const pagesDir = path.join(__dirname, DIRECTORY); -const privateRoutes = getPrivateRoutes(pagesDir); - -// Initialize the project and source file -const project = new Project(); -const sourceFile = project.addSourceFileAtPath(path.resolve(__dirname, "middleware.ts")); - -// Find the variable to replace and change it's declaration -const variable = sourceFile.getVariableDeclaration(CONST_VARIABLE_NAME); -if (variable) { - variable.setInitializer(JSON.stringify(privateRoutes)); - sourceFile.saveSync(); -} else { - console.error("Variable not found in `middleware.ts`. File wasn't changed."); +export function changeMiddleware() { + const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated + const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) + + // Get private routes + const pagesDir = path.join(__dirname, DIRECTORY); + const privateRoutes = getPrivateRoutes(pagesDir); + + // Initialize the project and source file + const project = new Project(); + const sourceFile = project.addSourceFileAtPath(path.resolve(__dirname, "middleware.ts")); + + // Find the variable to replace and change it's declaration + const variable = sourceFile.getVariableDeclaration(CONST_VARIABLE_NAME); + if (variable) { + variable.setInitializer(JSON.stringify(privateRoutes)); + sourceFile.saveSync(); + } else { + console.error("Variable not found in `middleware.ts`. File wasn't changed."); + } } + +export default { + changeMiddleware: () => changeMiddleware() +} \ No newline at end of file diff --git a/tests/unit/generatePrivateRoutes.test.tsx b/tests/unit/generatePrivateRoutes.test.tsx new file mode 100644 index 0000000..0765d6a --- /dev/null +++ b/tests/unit/generatePrivateRoutes.test.tsx @@ -0,0 +1,94 @@ +import { getPrivateRoutes } from "@/src/generatePrivateRoutes"; +import { readFileSync } from "fs"; +import path from "path"; + +// Mock path module +jest.mock("path", () => ({ + ...jest.requireActual("path"), + join: (...args: string[]) => args.join("/"), + resolve: (...args: string[]) => args.join("/"), +})); + +// Mock ts-morph module +jest.mock("ts-morph", () => { + const actualTsMorph = jest.requireActual("ts-morph"); + + class MockSourceFile { + getVariableDeclaration = jest.fn(); + saveSync = jest.fn(); + } + + class MockProject { + addSourceFileAtPath = jest.fn().mockReturnValue(new MockSourceFile()); + } + + return { + ...actualTsMorph, + Project: MockProject, + }; +}); + +// Mock fast-glob +jest.mock("fast-glob", () => ({ + globSync: jest.fn(() => ["pages/dir1/_meta.json"]), +})); + +// Mock fs module +jest.mock("fs", () => { + const actualFs = jest.requireActual("fs"); + + // Mock realpathSync and realpathSync.native + return { + ...actualFs, + realpathSync: jest.fn().mockReturnValue({ native: "" }), + existsSync: jest.fn().mockReturnValue(true), + readFileSync: jest.fn().mockReturnValue(`{ + "index": { + "title": "Homepage", + "display": "hidden" + }, + "reference_api": { + "title": "API Reference", + "type": "page", + "private": { + "private": true, + "roles": ["user"] + } + }, + "about": { + "title": "About Us", + "private": true + }, + "contact": { + "title": "Contact Us", + "type": "page" + }, + "---": { + "type": "separator", + "private": true + }, + "github_link": { + "title": "Github", + "href": "https://github.com/shuding/nextra", + "newWindow": true, + "display": "hidden" + } +} +`), + }; +}); + +describe("getPrivateRoutes", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it("should return the correct private routes", () => { + const privateRoutes = getPrivateRoutes(path.join(__dirname, "pages")); + + expect(privateRoutes).toEqual({ + "pages/dir1/reference_api": ["user"], + "pages/dir1/about": [], + }); + }); +}); From d09d36eafd32a9b91c072af7df623b6496522838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Wed, 26 Jun 2024 10:47:29 +0100 Subject: [PATCH 28/75] fix: Fixing jest tests to run mocks differently in-between tests. --- package.json | 2 +- tests/unit/generatePrivateRoutes.test.tsx | 89 ++++++++++++++++++----- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 5b3d03c..0226853 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "start": "next start", "e2e:test": "npx playwright test", "e2e:test:show-report": "npx monocart show-report ./e2e-test-results/monocart-report.html", - "test": "jest" + "test": "jest --runInBand" }, "dependencies": { "next-auth": "5.0.0-beta.19", diff --git a/tests/unit/generatePrivateRoutes.test.tsx b/tests/unit/generatePrivateRoutes.test.tsx index 0765d6a..762be8a 100644 --- a/tests/unit/generatePrivateRoutes.test.tsx +++ b/tests/unit/generatePrivateRoutes.test.tsx @@ -1,12 +1,13 @@ import { getPrivateRoutes } from "@/src/generatePrivateRoutes"; -import { readFileSync } from "fs"; -import path from "path"; +import { globSync } from "fast-glob"; +import { existsSync, readFileSync } from "fs"; +import path, { resolve } from "path"; // Mock path module jest.mock("path", () => ({ ...jest.requireActual("path"), join: (...args: string[]) => args.join("/"), - resolve: (...args: string[]) => args.join("/"), + resolve: jest.fn(), })); // Mock ts-morph module @@ -30,19 +31,28 @@ jest.mock("ts-morph", () => { // Mock fast-glob jest.mock("fast-glob", () => ({ - globSync: jest.fn(() => ["pages/dir1/_meta.json"]), + globSync: jest.fn(), })); // Mock fs module jest.mock("fs", () => { - const actualFs = jest.requireActual("fs"); - - // Mock realpathSync and realpathSync.native return { - ...actualFs, realpathSync: jest.fn().mockReturnValue({ native: "" }), existsSync: jest.fn().mockReturnValue(true), - readFileSync: jest.fn().mockReturnValue(`{ + readFileSync: jest.fn(), + }; +}); + + +// `jest` hoists the mocked imports. At this point, the functions are mocked, so we redefine them to not throw Typescript `undefined` errors. +const pathResolveMock = resolve as jest.Mock; +const globSyncMock = globSync as jest.Mock; +const readFileSyncMock = readFileSync as jest.Mock; + +describe("getPrivateRoutes", () => { + it("should return the correct private routes", () => { + globSyncMock.mockReturnValue(["pages/dir1/_meta.json"]); + readFileSyncMock.mockReturnValue(`{ "index": { "title": "Homepage", "display": "hidden" @@ -73,22 +83,65 @@ jest.mock("fs", () => { "newWindow": true, "display": "hidden" } -} -`), - }; -}); +}`); + const privateRoutes = getPrivateRoutes(path.join(__dirname, "pages")); -describe("getPrivateRoutes", () => { - afterEach(() => { - jest.clearAllMocks(); + expect(privateRoutes).toEqual({ + "pages/dir1/reference_api": ["user"], + "pages/dir1/about": [], + }); }); - it("should return the correct private routes", () => { + it("should return the correct nested private routes", () => { + globSyncMock.mockReturnValue([ + "pages/dir1/_meta.json", + "pages/dir1/reference_api/_meta.json", + "pages/dir1/reference_api/mega_private/_meta.json", + ]); + readFileSyncMock.mockReturnValueOnce(` +{ + "reference_api": { + "title": "API Reference", + "type": "page", + "private": { + "private": true, + "roles": ["user"] + } + } +} + `).mockReturnValueOnce(` +{ + "about": "about", + "---": { + "type": "separator" + }, + "users": "users", + "mega_private": { + "title": "Mega Private Section", + "private": { + "private": true, + "roles": ["cant_enter"] + } + } +} +`).mockReturnValueOnce(` +{ + "hello": "Hello page" +} +`); + pathResolveMock.mockImplementation((path: string, second: string) => { + const index = path.lastIndexOf("/"); + return path.substring(0, index); + }); // assumes the "resolve" will be called with (dir, "..") + const privateRoutes = getPrivateRoutes(path.join(__dirname, "pages")); expect(privateRoutes).toEqual({ "pages/dir1/reference_api": ["user"], - "pages/dir1/about": [], + "pages/dir1/reference_api/about": ["user"], + "pages/dir1/reference_api/users": ["user"], + "pages/dir1/reference_api/mega_private": ["cant_enter"], + "pages/dir1/reference_api/mega_private/hello": ["cant_enter"], }); }); }); From 9b1113562b2486409b93e2d406d862e7cec94ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Wed, 26 Jun 2024 17:48:47 +0100 Subject: [PATCH 29/75] test: Testing middleware changing script. --- README.md | 7 ++- src/generatePrivateRoutes.ts | 7 ++- tests/unit/generatePrivateRoutes.test.tsx | 76 ++++++++++++++++------- 3 files changed, 63 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 4641e11..53003b1 100644 --- a/README.md +++ b/README.md @@ -1241,10 +1241,11 @@ import { globSync } from "fast-glob"; // - - - - - - - - - - - - - - - - - - - - - - - // `middleware.ts` is changed by executing the code below. +const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated +const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) + export function changeMiddleware() { - const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated - const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) - + // Get private routes const pagesDir = path.join(__dirname, DIRECTORY); const privateRoutes = getPrivateRoutes(pagesDir); diff --git a/src/generatePrivateRoutes.ts b/src/generatePrivateRoutes.ts index d5a0be5..0282223 100644 --- a/src/generatePrivateRoutes.ts +++ b/src/generatePrivateRoutes.ts @@ -92,10 +92,11 @@ export function getPrivateRoutes(pagesDir: string): PrivateRoutes { // - - - - - - - - - - - - - - - - - - - - - - - // `middleware.ts` is changed by executing the code below. +const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated +const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) + export function changeMiddleware() { - const CONST_VARIABLE_NAME = "privateRoutesMap"; // Name of the constant inside `middleware.ts` to be manipulated - const DIRECTORY = "pages"; // Directory to look for the routes (should be `pages`, according to Nextra's file system) - + // Get private routes const pagesDir = path.join(__dirname, DIRECTORY); const privateRoutes = getPrivateRoutes(pagesDir); diff --git a/tests/unit/generatePrivateRoutes.test.tsx b/tests/unit/generatePrivateRoutes.test.tsx index 762be8a..ba22eed 100644 --- a/tests/unit/generatePrivateRoutes.test.tsx +++ b/tests/unit/generatePrivateRoutes.test.tsx @@ -1,7 +1,8 @@ -import { getPrivateRoutes } from "@/src/generatePrivateRoutes"; +import { changeMiddleware, getPrivateRoutes } from "@/src/generatePrivateRoutes"; import { globSync } from "fast-glob"; import { existsSync, readFileSync } from "fs"; import path, { resolve } from "path"; +import { Project } from "ts-morph"; // Mock path module jest.mock("path", () => ({ @@ -10,25 +11,6 @@ jest.mock("path", () => ({ resolve: jest.fn(), })); -// Mock ts-morph module -jest.mock("ts-morph", () => { - const actualTsMorph = jest.requireActual("ts-morph"); - - class MockSourceFile { - getVariableDeclaration = jest.fn(); - saveSync = jest.fn(); - } - - class MockProject { - addSourceFileAtPath = jest.fn().mockReturnValue(new MockSourceFile()); - } - - return { - ...actualTsMorph, - Project: MockProject, - }; -}); - // Mock fast-glob jest.mock("fast-glob", () => ({ globSync: jest.fn(), @@ -43,7 +25,6 @@ jest.mock("fs", () => { }; }); - // `jest` hoists the mocked imports. At this point, the functions are mocked, so we redefine them to not throw Typescript `undefined` errors. const pathResolveMock = resolve as jest.Mock; const globSyncMock = globSync as jest.Mock; @@ -145,3 +126,56 @@ describe("getPrivateRoutes", () => { }); }); }); + +const MockGetVariableDeclaration = { + setInitializer: jest.fn(), +}; + +const MockSourceFile = { + getVariableDeclaration: jest + .fn() + .mockReturnValueOnce(MockGetVariableDeclaration) // first run success + .mockReturnValueOnce(false), // second run fails + saveSync: jest.fn(), +}; + +const MockProject = { + addSourceFileAtPath: jest.fn().mockReturnValue(MockSourceFile), +}; + +// Mock ts-morph module +jest.mock("ts-morph", () => { + const actualTsMorph = jest.requireActual("ts-morph"); + return { + ...actualTsMorph, + Project: jest.fn().mockImplementation(() => { + return MockProject; + }), + }; +}); + +describe("changeMiddleware", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it("should successfully change the middleware.ts file with correct private routes (happy path) and fail on the second one (bad path)", () => { + // Call the function + changeMiddleware(); + + // Expectations + expect(MockProject.addSourceFileAtPath).toHaveBeenCalled(); + expect(MockSourceFile.getVariableDeclaration).toHaveBeenCalled(); + expect(MockSourceFile.saveSync).toHaveBeenCalled(); + expect(MockGetVariableDeclaration.setInitializer).toHaveBeenCalled(); + + const errorSpy = jest.spyOn(console, "error").mockImplementation(() => {}); + + // Call the function a second time + // It should fail, given how `getVariableDeclaration` is meant to return `false` on second run + changeMiddleware(); + + // Expectations + expect(errorSpy).toHaveBeenCalled(); + }); +}); From 0fb44e9d34d66dd613bc9a4d606fb17e42f174c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Wed, 26 Jun 2024 17:54:37 +0100 Subject: [PATCH 30/75] refactor: Refactoring test. --- tests/unit/generatePrivateRoutes.test.tsx | 153 +++++++++++----------- 1 file changed, 78 insertions(+), 75 deletions(-) diff --git a/tests/unit/generatePrivateRoutes.test.tsx b/tests/unit/generatePrivateRoutes.test.tsx index ba22eed..5261743 100644 --- a/tests/unit/generatePrivateRoutes.test.tsx +++ b/tests/unit/generatePrivateRoutes.test.tsx @@ -4,6 +4,9 @@ import { existsSync, readFileSync } from "fs"; import path, { resolve } from "path"; import { Project } from "ts-morph"; + +// MOCK AND TEST SUITES FOR `getPrivateRoutes` ---------------------------- + // Mock path module jest.mock("path", () => ({ ...jest.requireActual("path"), @@ -17,56 +20,54 @@ jest.mock("fast-glob", () => ({ })); // Mock fs module -jest.mock("fs", () => { - return { - realpathSync: jest.fn().mockReturnValue({ native: "" }), - existsSync: jest.fn().mockReturnValue(true), - readFileSync: jest.fn(), - }; -}); +jest.mock("fs", () => ({ + realpathSync: jest.fn().mockReturnValue({ native: "" }), + existsSync: jest.fn().mockReturnValue(true), + readFileSync: jest.fn(), +})); -// `jest` hoists the mocked imports. At this point, the functions are mocked, so we redefine them to not throw Typescript `undefined` errors. +// Redefine mocks to avoid TypeScript errors const pathResolveMock = resolve as jest.Mock; const globSyncMock = globSync as jest.Mock; const readFileSyncMock = readFileSync as jest.Mock; +// Test suite for getPrivateRoutes function describe("getPrivateRoutes", () => { it("should return the correct private routes", () => { globSyncMock.mockReturnValue(["pages/dir1/_meta.json"]); readFileSyncMock.mockReturnValue(`{ - "index": { - "title": "Homepage", - "display": "hidden" - }, - "reference_api": { - "title": "API Reference", - "type": "page", - "private": { - "private": true, - "roles": ["user"] - } - }, - "about": { - "title": "About Us", - "private": true - }, - "contact": { - "title": "Contact Us", - "type": "page" - }, - "---": { - "type": "separator", - "private": true - }, - "github_link": { - "title": "Github", - "href": "https://github.com/shuding/nextra", - "newWindow": true, - "display": "hidden" - } -}`); + "index": { + "title": "Homepage", + "display": "hidden" + }, + "reference_api": { + "title": "API Reference", + "type": "page", + "private": { + "private": true, + "roles": ["user"] + } + }, + "about": { + "title": "About Us", + "private": true + }, + "contact": { + "title": "Contact Us", + "type": "page" + }, + "---": { + "type": "separator", + "private": true + }, + "github_link": { + "title": "Github", + "href": "https://github.com/shuding/nextra", + "newWindow": true, + "display": "hidden" + } + }`); const privateRoutes = getPrivateRoutes(path.join(__dirname, "pages")); - expect(privateRoutes).toEqual({ "pages/dir1/reference_api": ["user"], "pages/dir1/about": [], @@ -80,43 +81,43 @@ describe("getPrivateRoutes", () => { "pages/dir1/reference_api/mega_private/_meta.json", ]); readFileSyncMock.mockReturnValueOnce(` -{ - "reference_api": { - "title": "API Reference", - "type": "page", - "private": { - "private": true, - "roles": ["user"] + { + "reference_api": { + "title": "API Reference", + "type": "page", + "private": { + "private": true, + "roles": ["user"] + } + } } - } -} - `).mockReturnValueOnce(` -{ - "about": "about", - "---": { - "type": "separator" - }, - "users": "users", - "mega_private": { - "title": "Mega Private Section", - "private": { - "private": true, - "roles": ["cant_enter"] + `) + .mockReturnValueOnce(` + { + "about": "about", + "---": { + "type": "separator" + }, + "users": "users", + "mega_private": { + "title": "Mega Private Section", + "private": { + "private": true, + "roles": ["cant_enter"] + } + } } - } -} -`).mockReturnValueOnce(` -{ - "hello": "Hello page" -} -`); + `).mockReturnValueOnce(` + { + "hello": "Hello page" + } + `); pathResolveMock.mockImplementation((path: string, second: string) => { const index = path.lastIndexOf("/"); return path.substring(0, index); - }); // assumes the "resolve" will be called with (dir, "..") + }); const privateRoutes = getPrivateRoutes(path.join(__dirname, "pages")); - expect(privateRoutes).toEqual({ "pages/dir1/reference_api": ["user"], "pages/dir1/reference_api/about": ["user"], @@ -127,18 +128,20 @@ describe("getPrivateRoutes", () => { }); }); + +// MOCK AND TEST SUITES FOR `changeMiddleware` ---------------------------- + +// Mock objects for ts-morph const MockGetVariableDeclaration = { setInitializer: jest.fn(), }; - const MockSourceFile = { getVariableDeclaration: jest .fn() - .mockReturnValueOnce(MockGetVariableDeclaration) // first run success - .mockReturnValueOnce(false), // second run fails + .mockReturnValueOnce(MockGetVariableDeclaration) + .mockReturnValueOnce(false), saveSync: jest.fn(), }; - const MockProject = { addSourceFileAtPath: jest.fn().mockReturnValue(MockSourceFile), }; @@ -154,6 +157,7 @@ jest.mock("ts-morph", () => { }; }); +// Test suite for changeMiddleware function describe("changeMiddleware", () => { afterEach(() => { jest.clearAllMocks(); @@ -172,7 +176,6 @@ describe("changeMiddleware", () => { const errorSpy = jest.spyOn(console, "error").mockImplementation(() => {}); // Call the function a second time - // It should fail, given how `getVariableDeclaration` is meant to return `false` on second run changeMiddleware(); // Expectations From e46f81167438df448b39d86e456166b045006efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Wed, 26 Jun 2024 18:07:57 +0100 Subject: [PATCH 31/75] test: Testing when file doesn't exist, so it removes from private routes. --- tests/unit/generatePrivateRoutes.test.tsx | 37 ++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/tests/unit/generatePrivateRoutes.test.tsx b/tests/unit/generatePrivateRoutes.test.tsx index 5261743..636da7a 100644 --- a/tests/unit/generatePrivateRoutes.test.tsx +++ b/tests/unit/generatePrivateRoutes.test.tsx @@ -22,7 +22,7 @@ jest.mock("fast-glob", () => ({ // Mock fs module jest.mock("fs", () => ({ realpathSync: jest.fn().mockReturnValue({ native: "" }), - existsSync: jest.fn().mockReturnValue(true), + existsSync: jest.fn(), readFileSync: jest.fn(), })); @@ -30,11 +30,13 @@ jest.mock("fs", () => ({ const pathResolveMock = resolve as jest.Mock; const globSyncMock = globSync as jest.Mock; const readFileSyncMock = readFileSync as jest.Mock; +const existsSyncMock = existsSync as jest.Mock; // Test suite for getPrivateRoutes function describe("getPrivateRoutes", () => { it("should return the correct private routes", () => { globSyncMock.mockReturnValue(["pages/dir1/_meta.json"]); + existsSyncMock.mockReturnValue(true); readFileSyncMock.mockReturnValue(`{ "index": { "title": "Homepage", @@ -67,7 +69,11 @@ describe("getPrivateRoutes", () => { "display": "hidden" } }`); + + // Call function const privateRoutes = getPrivateRoutes(path.join(__dirname, "pages")); + + // Expectation expect(privateRoutes).toEqual({ "pages/dir1/reference_api": ["user"], "pages/dir1/about": [], @@ -80,6 +86,7 @@ describe("getPrivateRoutes", () => { "pages/dir1/reference_api/_meta.json", "pages/dir1/reference_api/mega_private/_meta.json", ]); + existsSyncMock.mockReturnValue(true); readFileSyncMock.mockReturnValueOnce(` { "reference_api": { @@ -117,7 +124,10 @@ describe("getPrivateRoutes", () => { return path.substring(0, index); }); + // Call function const privateRoutes = getPrivateRoutes(path.join(__dirname, "pages")); + + // Expectations expect(privateRoutes).toEqual({ "pages/dir1/reference_api": ["user"], "pages/dir1/reference_api/about": ["user"], @@ -126,6 +136,31 @@ describe("getPrivateRoutes", () => { "pages/dir1/reference_api/mega_private/hello": ["cant_enter"], }); }); + + it("should return the correct private routes but deleting the ones which don't exist in the file system", () => { + globSyncMock.mockReturnValue(["pages/dir1/_meta.json"]); + existsSyncMock.mockReturnValue(false); + readFileSyncMock.mockReturnValue(`{ + "reference_api": { + "title": "API Reference", + "type": "page", + "private": { + "private": true, + "roles": ["user"] + } + }, + "about": { + "title": "About Us", + "private": true + } + }`); + + // Call function + const privateRoutes = getPrivateRoutes(path.join(__dirname, "pages")); + + // Expectations + expect(privateRoutes).toEqual({}); + }); }); From 3649579b65814b096dcf3a62baf9496f19761c24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Wed, 26 Jun 2024 18:24:42 +0100 Subject: [PATCH 32/75] fix: Finishing generating private routes test. --- src/generatePrivateRoutes.ts | 1 + tests/unit/generatePrivateRoutes.test.tsx | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/generatePrivateRoutes.ts b/src/generatePrivateRoutes.ts index 0282223..7867ad5 100644 --- a/src/generatePrivateRoutes.ts +++ b/src/generatePrivateRoutes.ts @@ -116,5 +116,6 @@ export function changeMiddleware() { } export default { + /* c8 ignore next */ changeMiddleware: () => changeMiddleware() } \ No newline at end of file diff --git a/tests/unit/generatePrivateRoutes.test.tsx b/tests/unit/generatePrivateRoutes.test.tsx index 636da7a..2aa3dbc 100644 --- a/tests/unit/generatePrivateRoutes.test.tsx +++ b/tests/unit/generatePrivateRoutes.test.tsx @@ -56,7 +56,9 @@ describe("getPrivateRoutes", () => { }, "contact": { "title": "Contact Us", - "type": "page" + "private": { + "private": true + } }, "---": { "type": "separator", @@ -77,6 +79,7 @@ describe("getPrivateRoutes", () => { expect(privateRoutes).toEqual({ "pages/dir1/reference_api": ["user"], "pages/dir1/about": [], + "pages/dir1/contact": [], }); }); From de64ba1ca1993f5287ce9d3fac8c23ef09fe25cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 27 Jun 2024 11:18:20 +0100 Subject: [PATCH 33/75] fix: Fixing CI --- .github/workflows/playwright.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 27396cb..c6a217c 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -13,8 +13,9 @@ jobs: - uses: actions/setup-node@v4 with: node-version: lts/* + - uses: pnpm/action-setup@v4 - name: Install dependencies - run: npm install -g pnpm && pnpm install + run: pnpm install - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run Playwright tests From 7c4663c57f87db224324e10031fa4dac4285e714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 27 Jun 2024 11:22:20 +0100 Subject: [PATCH 34/75] fix: Fix CI pnpm version install. --- .github/workflows/playwright.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index c6a217c..33f1988 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -14,8 +14,10 @@ jobs: with: node-version: lts/* - uses: pnpm/action-setup@v4 + with: + version: latest - name: Install dependencies - run: pnpm install + run: npm install -g pnpm && pnpm install - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run Playwright tests From c302f70deb1fffbcf62ebf3d88e789eb7fef52f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 27 Jun 2024 11:28:13 +0100 Subject: [PATCH 35/75] fix: Trying to fix frozen pnpm-lock in CI. --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 33f1988..b2fe661 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -17,7 +17,7 @@ jobs: with: version: latest - name: Install dependencies - run: npm install -g pnpm && pnpm install + run: pnpm install --frozen-lockfile - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run Playwright tests From d81311d29b27943bb9bf0e07486b4c5296b68370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 27 Jun 2024 11:30:03 +0100 Subject: [PATCH 36/75] fix: Fix frozen lock file command on CI. --- .github/workflows/playwright.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index b2fe661..6cf9d35 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -17,7 +17,7 @@ jobs: with: version: latest - name: Install dependencies - run: pnpm install --frozen-lockfile + run: pnpm install --no-frozen-lockfile - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run Playwright tests From 3c9fb4ec70588c0c672a3e44c8efea55bcd8f7de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 27 Jun 2024 11:40:57 +0100 Subject: [PATCH 37/75] fix: Installing next to run webserver when playwright tests execute. --- .github/workflows/playwright.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 6cf9d35..e822757 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -1,9 +1,9 @@ name: Playwright Tests on: push: - branches: [ main, master ] + branches: [ main ] pull_request: - branches: [ main, master ] + branches: [ main ] jobs: test: timeout-minutes: 60 @@ -17,7 +17,7 @@ jobs: with: version: latest - name: Install dependencies - run: pnpm install --no-frozen-lockfile + run: pnpm install --no-frozen-lockfile && pnpm install next - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run Playwright tests From 407e7a7b3bc308b99678e888c1ea058b7f6b04bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 27 Jun 2024 11:44:38 +0100 Subject: [PATCH 38/75] fix: Re-adding next to package.json and fixing CI. --- .github/workflows/playwright.yml | 2 +- package.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index e822757..2656a27 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -17,7 +17,7 @@ jobs: with: version: latest - name: Install dependencies - run: pnpm install --no-frozen-lockfile && pnpm install next + run: pnpm install --no-frozen-lockfile - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run Playwright tests diff --git a/package.json b/package.json index 0226853..7e4cbde 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test": "jest --runInBand" }, "dependencies": { + "next": "^14.2.4", "next-auth": "5.0.0-beta.19", "nextra": "^2.13.4", "nextra-theme-docs": "^2.13.4", From c7229fd4059519d3c726f0b9e7ce1912eb1a5b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 27 Jun 2024 12:01:27 +0100 Subject: [PATCH 39/75] refactor: Renaming test. --- ...neratePrivateRoutes.test.tsx => generatePrivateRoutes.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/unit/{generatePrivateRoutes.test.tsx => generatePrivateRoutes.test.ts} (100%) diff --git a/tests/unit/generatePrivateRoutes.test.tsx b/tests/unit/generatePrivateRoutes.test.ts similarity index 100% rename from tests/unit/generatePrivateRoutes.test.tsx rename to tests/unit/generatePrivateRoutes.test.ts From 21ef858cfdb86de949906eaccf60f4022cb9dd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Thu, 27 Jun 2024 16:42:42 +0100 Subject: [PATCH 40/75] test: Getting coverage to 100%. --- jest.config.ts | 11 ++++++++++- tests/unit/components/LoginOrUserInfo.test.tsx | 11 ++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/jest.config.ts b/jest.config.ts index 43597fa..739e926 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -18,7 +18,16 @@ const config: Config = { coveragePathIgnorePatterns: ["/node_modules/"], coverageProvider: "v8", - moduleDirectories: ["node_modules"], + moduleDirectories: [ + "node_modules" + ], + modulePathIgnorePatterns: [ + // Testing auth with `next-auth` complains (consider switching to Vitest) + // Doesn't seem to have a proper solution. See https://github.com/nextauthjs/next-auth/issues/4198. + "src/auth.ts", + "src/middleware.ts", + "src/app" + ], moduleNameMapper: { "next-auth/(.*)": "/node_modules/next-auth/$1", }, diff --git a/tests/unit/components/LoginOrUserInfo.test.tsx b/tests/unit/components/LoginOrUserInfo.test.tsx index b218ace..7ade893 100644 --- a/tests/unit/components/LoginOrUserInfo.test.tsx +++ b/tests/unit/components/LoginOrUserInfo.test.tsx @@ -1,6 +1,7 @@ import { render, screen } from "@testing-library/react"; import LoginOrUserInfo from "@/src/components/LoginOrUserInfo"; import { DefaultSession } from "next-auth"; +import { fireEvent } from "@testing-library/react"; import { signOut, signIn } from "next-auth/react"; // Mocking `signIn` and `signOut` API calls @@ -18,11 +19,13 @@ describe("LoginOrUserInfo", () => { }; render(); - expect(screen.getByRole("button", { name: "SIGN IN" })).toBeDefined(); + const button = screen.getByRole("button", { name: "SIGN IN" }); + button.click(); + expect(button).toBeDefined(); }); it('shows "Sign Out" button and user info when session is found', () => { - const username = "AlpheyaUsername" + const username = "AlpheyaUsername"; const session: DefaultSession = { user: { name: username, @@ -31,7 +34,9 @@ describe("LoginOrUserInfo", () => { }; render(); - expect(screen.getByRole("button", { name: "SIGN OUT" })).toBeDefined(); + const button = screen.getByRole("button", { name: "SIGN OUT" }); + button.click(); + expect(button).toBeDefined(); expect(screen.getByText(username)).toBeDefined(); }); }); From 9a6d0867d4aa346e94b771ff92ae3cf9bd82c4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lui=CC=81s=20Arteiro?= Date: Fri, 28 Jun 2024 10:14:58 +0100 Subject: [PATCH 41/75] feat: Adding theme from nextra-theme-docks. At this commit, it will not work because the workspaces aren't properly defined yet to install the packages. This is just to import the custom theme as is so we can change it accordingly. --- theme/LICENSE | 21 + theme/README.md | 7 + theme/css/hamburger.css | 41 ++ theme/css/styles.css | 177 +++++++ theme/css/typesetting-article.css | 28 + theme/package.json | 81 +++ theme/postcss.config.js | 11 + theme/src/components/404.tsx | 32 ++ theme/src/components/500.tsx | 34 ++ theme/src/components/anchor.tsx | 61 +++ theme/src/components/back-to-top.tsx | 38 ++ theme/src/components/banner.tsx | 50 ++ theme/src/components/bleed.tsx | 25 + theme/src/components/breadcrumb.tsx | 46 ++ theme/src/components/collapse.tsx | 80 +++ theme/src/components/flexsearch.tsx | 290 +++++++++++ theme/src/components/footer.tsx | 33 ++ theme/src/components/head.tsx | 83 +++ theme/src/components/highlight-matches.tsx | 48 ++ theme/src/components/index.ts | 20 + theme/src/components/input.tsx | 29 ++ theme/src/components/locale-switch.tsx | 50 ++ theme/src/components/match-sorter-search.tsx | 43 ++ theme/src/components/nav-links.tsx | 70 +++ theme/src/components/navbar.tsx | 203 ++++++++ theme/src/components/search.tsx | 296 +++++++++++ theme/src/components/select.tsx | 105 ++++ theme/src/components/sidebar.tsx | 515 +++++++++++++++++++ theme/src/components/skip-nav.tsx | 93 ++++ theme/src/components/theme-switch.tsx | 61 +++ theme/src/components/toc.tsx | 135 +++++ theme/src/constants.tsx | 368 +++++++++++++ theme/src/contexts/active-anchor.tsx | 106 ++++ theme/src/contexts/config.tsx | 126 +++++ theme/src/contexts/details.ts | 8 + theme/src/contexts/index.ts | 8 + theme/src/contexts/menu.ts | 16 + theme/src/env.d.ts | 0 theme/src/index.tsx | 277 ++++++++++ theme/src/mdx-components.tsx | 250 +++++++++ theme/src/polyfill.ts | 15 + theme/src/types.ts | 16 + theme/src/utils/get-git-issue-url.ts | 30 ++ theme/src/utils/index.ts | 4 + theme/src/utils/render.tsx | 23 + theme/src/utils/use-git-edit-url.ts | 11 + theme/src/utils/use-popper.ts | 42 ++ theme/tailwind.config.js | 76 +++ theme/tsconfig.json | 21 + theme/tsup.config.ts | 10 + theme/vite.config.ts | 9 + 51 files changed, 4222 insertions(+) create mode 100644 theme/LICENSE create mode 100644 theme/README.md create mode 100644 theme/css/hamburger.css create mode 100644 theme/css/styles.css create mode 100644 theme/css/typesetting-article.css create mode 100644 theme/package.json create mode 100644 theme/postcss.config.js create mode 100644 theme/src/components/404.tsx create mode 100644 theme/src/components/500.tsx create mode 100644 theme/src/components/anchor.tsx create mode 100644 theme/src/components/back-to-top.tsx create mode 100644 theme/src/components/banner.tsx create mode 100644 theme/src/components/bleed.tsx create mode 100644 theme/src/components/breadcrumb.tsx create mode 100644 theme/src/components/collapse.tsx create mode 100644 theme/src/components/flexsearch.tsx create mode 100644 theme/src/components/footer.tsx create mode 100644 theme/src/components/head.tsx create mode 100644 theme/src/components/highlight-matches.tsx create mode 100644 theme/src/components/index.ts create mode 100644 theme/src/components/input.tsx create mode 100644 theme/src/components/locale-switch.tsx create mode 100644 theme/src/components/match-sorter-search.tsx create mode 100644 theme/src/components/nav-links.tsx create mode 100644 theme/src/components/navbar.tsx create mode 100644 theme/src/components/search.tsx create mode 100644 theme/src/components/select.tsx create mode 100644 theme/src/components/sidebar.tsx create mode 100644 theme/src/components/skip-nav.tsx create mode 100644 theme/src/components/theme-switch.tsx create mode 100644 theme/src/components/toc.tsx create mode 100644 theme/src/constants.tsx create mode 100644 theme/src/contexts/active-anchor.tsx create mode 100644 theme/src/contexts/config.tsx create mode 100644 theme/src/contexts/details.ts create mode 100644 theme/src/contexts/index.ts create mode 100644 theme/src/contexts/menu.ts create mode 100644 theme/src/env.d.ts create mode 100644 theme/src/index.tsx create mode 100644 theme/src/mdx-components.tsx create mode 100644 theme/src/polyfill.ts create mode 100644 theme/src/types.ts create mode 100644 theme/src/utils/get-git-issue-url.ts create mode 100644 theme/src/utils/index.ts create mode 100644 theme/src/utils/render.tsx create mode 100644 theme/src/utils/use-git-edit-url.ts create mode 100644 theme/src/utils/use-popper.ts create mode 100644 theme/tailwind.config.js create mode 100644 theme/tsconfig.json create mode 100644 theme/tsup.config.ts create mode 100644 theme/vite.config.ts diff --git a/theme/LICENSE b/theme/LICENSE new file mode 100644 index 0000000..6734428 --- /dev/null +++ b/theme/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Shu Ding + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/theme/README.md b/theme/README.md new file mode 100644 index 0000000..5976df5 --- /dev/null +++ b/theme/README.md @@ -0,0 +1,7 @@ +# nextra-theme-docs + +A documentation site theme for [Nextra](https://github.com/shuding/nextra). + +## Example + +[nextra.vercel.app](https://nextra.vercel.app/) diff --git a/theme/css/hamburger.css b/theme/css/hamburger.css new file mode 100644 index 0000000..103ad0f --- /dev/null +++ b/theme/css/hamburger.css @@ -0,0 +1,41 @@ +.nextra-hamburger svg { + g { + @apply nx-origin-center; + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1); + } + path { + opacity: 1; + transition: + transform 0.2s cubic-bezier(0.25, 1, 0.5, 1) 0.2s, + opacity 0.2s ease 0.2s; + } + + &.open { + path { + transition: + transform 0.2s cubic-bezier(0.25, 1, 0.5, 1), + opacity 0s ease 0.2s; + } + g { + transition: transform 0.2s cubic-bezier(0.25, 1, 0.5, 1) 0.2s; + } + } + + &.open > { + path { + @apply nx-opacity-0; + } + g:nth-of-type(1) { + @apply nx-rotate-45; + path { + transform: translate3d(0, 6px, 0); + } + } + g:nth-of-type(2) { + @apply -nx-rotate-45; + path { + transform: translate3d(0, -6px, 0); + } + } + } +} diff --git a/theme/css/styles.css b/theme/css/styles.css new file mode 100644 index 0000000..b04749f --- /dev/null +++ b/theme/css/styles.css @@ -0,0 +1,177 @@ +@import 'tailwindcss/base'; +@import 'tailwindcss/components'; +@import 'tailwindcss/utilities'; +@import 'nextra/styles/variables.css'; +@import 'nextra/styles/code-block.css'; +@import 'nextra/styles/subheading-anchor.css'; +@import 'nextra/styles/scrollbar.css'; +@import 'nextra/styles/steps.css'; +@import 'nextra/styles/cards.css'; +@import './hamburger.css'; +@import './typesetting-article.css'; + +html { + @apply nx-antialiased nx-text-base nx-scroll-pt-[--nextra-navbar-height]; + font-feature-settings: + 'rlig' 1, + 'calt' 1, + 'ss01' 1; + -webkit-tap-highlight-color: transparent; +} + +body { + @apply nx-w-full nx-bg-white dark:nx-bg-dark dark:nx-text-gray-100; +} + +a, +summary, +button, +input, +[tabindex]:not([tabindex='-1']) { + @apply nx-outline-none; + &:focus-visible { + @apply nx-ring-2 nx-ring-primary-200 nx-ring-offset-1 nx-ring-offset-primary-300 dark:nx-ring-primary-800 dark:nx-ring-offset-primary-700; + } +} + +a, +summary { + @apply nx-rounded; +} + +.nextra-content { + @apply nx-text-slate-700 dark:nx-text-slate-200; +} + +@media (max-width: 767px) { + .nextra-sidebar-container { + @apply nx-fixed nx-pt-[calc(var(--nextra-navbar-height))] nx-top-0 nx-w-full nx-bottom-0 nx-z-[15] nx-overscroll-contain nx-bg-white dark:nx-bg-dark; + transition: transform 0.8s cubic-bezier(0.52, 0.16, 0.04, 1); + will-change: transform, opacity; + contain: layout style; + backface-visibility: hidden; + + & > .nextra-scrollbar { + mask-image: linear-gradient(to bottom, transparent, #000 20px), + linear-gradient(to left, #000 10px, transparent 10px); + } + } + + .nextra-banner-container ~ div { + .nextra-sidebar-container { + @apply nx-pt-[6.5rem]; + } + &.nextra-nav-container { + @apply nx-top-10 md:nx-top-0; + } + } + .nextra-banner-hidden { + .nextra-banner-container ~ div .nextra-sidebar-container { + @apply nx-pt-16; + } + .nextra-nav-container { + @apply !nx-top-0; + } + } + .nextra-search .excerpt { + @apply nx-overflow-hidden nx-text-ellipsis; + display: -webkit-box; + line-clamp: 1; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + } +} + +@media (prefers-reduced-motion: reduce) and (max-width: 767px) { + article:before, + .nextra-sidebar-container, + .nextra-sidebar-container.open, + body.resizing .nextra-sidebar-container { + @apply nx-transition-none; + } +} + +/* Content Typography */ +article details > summary { + &::-webkit-details-marker { + @apply nx-hidden; + } + &::before { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' class='h-5 w-5' viewBox='0 0 20 20' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z' clip-rule='evenodd' /%3E%3C/svg%3E"); + height: 1.2em; + width: 1.2em; + vertical-align: -4px; + } +} + +@media (min-width: 768px) { + .nextra-toc > .div, + .nextra-sidebar-container { + mask-image: linear-gradient(to bottom, transparent, #000 20px), + linear-gradient(to left, #000 10px, transparent 10px); + } +} + +@supports ( + (-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px)) +) { + .nextra-search ul { + @apply nx-backdrop-blur-lg nx-bg-white/70 dark:nx-bg-dark/80; + } + .nextra-nav-container-blur { + @apply nx-backdrop-blur-md nx-bg-white/[.85] dark:!nx-bg-dark/80; + } +} + +input[type='search'] { + &::-webkit-search-decoration, + &::-webkit-search-cancel-button, + &::-webkit-search-results-button, + &::-webkit-search-results-decoration { + -webkit-appearance: none; + } +} + +.contains-task-list { + @apply nx-ml-0 nx-list-none; + input[type='checkbox'] { + @apply nx-mr-1; + } +} + +.nextra-banner-hidden .nextra-banner-container { + @apply nx-hidden; +} + +.nextra-sidebar-container { + [data-toggle-animation='show'] button { + opacity: 0; + animation: nextra-fadein 1s ease 0.2s forwards; + } + [data-toggle-animation='hide'] button { + opacity: 0; + animation: nextra-fadein2 1s ease 0.2s forwards; + } +} + +.footnotes a[data-footnote-backref] { + font-family: initial; +} + +@keyframes nextra-fadein { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} + +@keyframes nextra-fadein2 { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} diff --git a/theme/css/typesetting-article.css b/theme/css/typesetting-article.css new file mode 100644 index 0000000..0cb3bab --- /dev/null +++ b/theme/css/typesetting-article.css @@ -0,0 +1,28 @@ +article.nextra-body-typesetting-article { + font-size: 17px; + font-feature-settings: + 'rlig' 1, + 'calt' 1; + h1 { + @apply nx-mt-6 nx-mb-4 nx-text-center; + font-size: 2.5rem; + } + h2 { + @apply nx-border-none; + } + a { + @apply nx-no-underline hover:nx-underline; + } + p { + @apply nx-leading-8; + } + code { + @apply nx-border-none dark:nx-bg-neutral-700; + } + pre code { + @apply dark:nx-bg-transparent; + } + .subheading-anchor + a { + @apply nx-no-underline hover:nx-no-underline after:nx-hidden; + } +} diff --git a/theme/package.json b/theme/package.json new file mode 100644 index 0000000..b493da2 --- /dev/null +++ b/theme/package.json @@ -0,0 +1,81 @@ +{ + "name": "nextra-theme-docs", + "version": "2.13.4", + "description": "A Nextra theme for documentation sites.", + "repository": "https://github.com/shuding/nextra", + "author": "Shu Ding ", + "license": "MIT", + "exports": { + "./style.css": "./style.css", + ".": { + "import": "./dist/index.js", + "types": "./dist/index.d.mts" + } + }, + "types": "./dist/index.d.mts", + "files": [ + "dist", + "style.css" + ], + "workspaces": [ + "theme" + ], + "scripts": { + "build": "tsup", + "build:all": "pnpm build && pnpm build:tailwind", + "build:tailwind": "pnpm postcss css/styles.css -o style.css --verbose", + "clean": "rimraf ./dist ./style.css", + "dev": "concurrently \"pnpm dev:layout\" \"pnpm dev:tailwind\"", + "dev:layout": "tsup --watch", + "dev:tailwind": "TAILWIND_MODE=watch pnpm postcss css/styles.css -o style.css --watch", + "prepublishOnly": "pnpm build:all", + "test": "echo ❗ No tests, previous tests were moved to the `nextra` package", + "types": "tsup --dts-only", + "types:check": "tsc --noEmit" + }, + "peerDependencies": { + "next": ">=9.5.3", + "nextra": "workspace:*", + "react": ">=16.13.1", + "react-dom": ">=16.13.1" + }, + "dependencies": { + "@headlessui/react": "^1.7.17", + "@popperjs/core": "^2.11.8", + "clsx": "^2.0.0", + "escape-string-regexp": "^5.0.0", + "flexsearch": "^0.7.31", + "focus-visible": "^5.2.0", + "git-url-parse": "^13.1.0", + "intersection-observer": "^0.12.2", + "match-sorter": "^6.3.1", + "next-seo": "^6.0.0", + "next-themes": "^0.2.1", + "scroll-into-view-if-needed": "^3.1.0", + "zod": "^3.22.3" + }, + "devDependencies": { + "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", + "@testing-library/react": "^14.0.0", + "@types/flexsearch": "^0.7.3", + "@types/git-url-parse": "^9.0.1", + "@types/react": "^18.2.21", + "@types/react-dom": "^18.2.7", + "@vitejs/plugin-react": "^3.0.1", + "concurrently": "^8.0.0", + "jsdom": "^23.0.0", + "next": "^13.5.6", + "nextra": "workspace:*", + "postcss": "^8.4.31", + "postcss-cli": "^10.1.0", + "postcss-import": "^15.1.0", + "postcss-lightningcss": "^1.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "tailwindcss": "^3.3.3", + "vitest": "^0.34.0" + }, + "sideEffects": [ + "./src/polyfill.ts" + ] +} diff --git a/theme/postcss.config.js b/theme/postcss.config.js new file mode 100644 index 0000000..c077b74 --- /dev/null +++ b/theme/postcss.config.js @@ -0,0 +1,11 @@ +/** @type {import('postcss').Postcss} */ +module.exports = { + plugins: { + 'postcss-import': {}, + 'tailwindcss/nesting': {}, + tailwindcss: {}, + 'postcss-lightningcss': { + browsers: '>= .25%' + } + } +} diff --git a/theme/src/components/404.tsx b/theme/src/components/404.tsx new file mode 100644 index 0000000..4587c2e --- /dev/null +++ b/theme/src/components/404.tsx @@ -0,0 +1,32 @@ +import { useRouter } from 'next/router' +import { useMounted } from 'nextra/hooks' +import type { ReactElement } from 'react' +import { useConfig } from '../contexts' +import { getGitIssueUrl, renderComponent } from '../utils' +import { Anchor } from './anchor' + +export function NotFoundPage(): ReactElement | null { + const config = useConfig() + const mounted = useMounted() + const { asPath } = useRouter() + const { content, labels } = config.notFound + if (!content) { + return null + } + + return ( +

+ + {renderComponent(content)} + +

+ ) +} diff --git a/theme/src/components/500.tsx b/theme/src/components/500.tsx new file mode 100644 index 0000000..3a92ee3 --- /dev/null +++ b/theme/src/components/500.tsx @@ -0,0 +1,34 @@ +import { useRouter } from 'next/router' +import { useMounted } from 'nextra/hooks' +import type { ReactElement } from 'react' +import { useConfig } from '../contexts' +import { getGitIssueUrl, renderComponent } from '../utils' +import { Anchor } from './anchor' + +export function ServerSideErrorPage(): ReactElement | null { + const config = useConfig() + const mounted = useMounted() + const { asPath } = useRouter() + const { content, labels } = config.serverSideError + if (!content) { + return null + } + + return ( +

+ + {renderComponent(content)} + +

+ ) +} diff --git a/theme/src/components/anchor.tsx b/theme/src/components/anchor.tsx new file mode 100644 index 0000000..21b904a --- /dev/null +++ b/theme/src/components/anchor.tsx @@ -0,0 +1,61 @@ +// eslint-disable-next-line no-restricted-imports -- only in this file we determine either we include as child of based of `newNextLinkBehavior` value +import NextLink from 'next/link' +import next from 'next/package.json' +import type { ComponentProps, ReactElement } from 'react' +import { forwardRef } from 'react' +import { useConfig } from '../contexts' + +export type AnchorProps = Omit, 'ref'> & { + newWindow?: boolean +} + +const nextVersion = Number(next.version.split('.')[0]) + +export const Anchor = forwardRef(function ( + { href = '', children, newWindow, ...props }, + // ref is used in + forwardedRef +): ReactElement { + const config = useConfig() + + if (newWindow) { + return ( + + {children} + (opens in a new tab) + + ) + } + + if (!href) { + return ( + + {children} + + ) + } + + if (nextVersion > 12 || config.newNextLinkBehavior) { + return ( + + {children} + + ) + } + + return ( + + + {children} + + + ) +}) + +Anchor.displayName = 'Anchor' diff --git a/theme/src/components/back-to-top.tsx b/theme/src/components/back-to-top.tsx new file mode 100644 index 0000000..8da3e0c --- /dev/null +++ b/theme/src/components/back-to-top.tsx @@ -0,0 +1,38 @@ +import cn from 'clsx' +import { ArrowRightIcon } from 'nextra/icons' +import type { ReactElement } from 'react' +import { useEffect, useRef } from 'react' + +function scrollToTop() { + window.scrollTo({ top: 0, behavior: 'smooth' }) +} + +export function BackToTop({ className }: { className?: string }): ReactElement { + const ref = useRef(null) + useEffect(() => { + function toggleVisible() { + const { scrollTop } = document.documentElement + ref.current?.classList.toggle('nx-opacity-0', scrollTop < 300) + } + + window.addEventListener('scroll', toggleVisible) + return () => { + window.removeEventListener('scroll', toggleVisible) + } + }, []) + + return ( + + ) +} diff --git a/theme/src/components/banner.tsx b/theme/src/components/banner.tsx new file mode 100644 index 0000000..8abf0b4 --- /dev/null +++ b/theme/src/components/banner.tsx @@ -0,0 +1,50 @@ +import cn from 'clsx' +import { XIcon } from 'nextra/icons' +import type { ReactElement } from 'react' +import { useConfig } from '../contexts' +import { renderComponent } from '../utils' + +export function Banner(): ReactElement | null { + const { banner } = useConfig() + if (!banner.text) { + return null + } + const hideBannerScript = `try{if(localStorage.getItem(${JSON.stringify( + banner.key + )})==='0'){document.body.classList.add('nextra-banner-hidden')}}catch(e){}` + + return ( + <> +