diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ce28960 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,70 @@ +name: eslint-plugin-cdk CI +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + pages: write + pull-requests: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + test-and-build: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 22.11.0 + - uses: pnpm/action-setup@v2 + name: Install pnpm + id: pnpm-install + with: + version: 8.7.6 + run_install: false + - name: Get pnpm store directory + id: pnpm-cache + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + - name: Install dependencies + run: pnpm i --frozen-lockfile + - name: Run Tests + run: pnpm run test + - name: Lint + run: pnpm run lint + - name: Build docs + run: pnpm run docs:build + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: docs/.vitepress/dist + deploy: + if: github.ref == 'refs/heads/main' + needs: test-and-build + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.npmignore b/.npmignore index c5992e9..555ef6e 100644 --- a/.npmignore +++ b/.npmignore @@ -2,6 +2,7 @@ node_modules/ src/ examples/ +docs/ eslint.config.mjs tsconfig.json vitest.config.mjs diff --git a/.vscode/settings.json b/.vscode/settings.json index d5b6024..4fd87d3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,5 +8,6 @@ "source.organizeImports", "source.fixAll.eslint" ], - "typescript.preferences.importModuleSpecifier": "relative" + "typescript.preferences.importModuleSpecifier": "relative", + "cSpell.words": ["vitepress"] } diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..5506568 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,3 @@ +node_modules +.vitepress/cache +.vitepress/dist diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts new file mode 100644 index 0000000..2ea2ce0 --- /dev/null +++ b/docs/.vitepress/config.mts @@ -0,0 +1,141 @@ +import { defineConfig } from "vitepress"; +import defaultConfig from "./sharedConfig.mjs"; + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + ...defaultConfig, + title: "eslint-plugin-cdk", + description: "documentation", + head: [ + [ + "link", + { + rel: "icon", + type: "image/png", + href: "/img/eslint-plugin-cdk.png", + }, + ], + ], + locales: { + root: { + label: "English", + lang: "en", + themeConfig: { + ...defaultConfig.themeConfig, + logo: "/img/eslint-plugin-cdk.png", + sidebar: [ + { + text: "Getting Started", + collapsed: true, + link: "/getting-started/", + items: [ + { + text: "Example", + link: "/getting-started/example", + }, + ], + }, + { + text: "Rules", + collapsed: true, + items: [ + { + text: "pascal-case-construct-id", + link: "/rules/pascal-case-construct-id", + }, + { + text: "no-parent-name-construct-id-match", + link: "/rules/no-parent-name-construct-id-match", + }, + { + text: "no-construct-stack-suffix", + link: "/rules/no-construct-stack-suffix", + }, + { + text: "no-class-in-interface", + link: "/rules/no-class-in-interface", + }, + { + text: "no-public-class-fields", + link: "/rules/no-public-class-fields", + }, + { + text: "no-import-private", + link: "/rules/no-import-private", + }, + ], + }, + ], + socialLinks: [ + { + icon: { + svg: `GitHub`, + }, + link: "https://github.com/ren-yamanashi/eslint-plugin-cdk/tree/main", + }, + ], + }, + }, + ja: { + label: "Japanese", + lang: "ja", + link: "/ja/", + title: "eslint-plugin-cdk", + themeConfig: { + ...defaultConfig.themeConfig, + logo: "/img/eslint-plugin-cdk.png", + sidebar: [ + { + text: "Getting Started", + collapsed: true, + link: "/ja/getting-started/", + items: [ + { + text: "Example", + link: "/ja/getting-started/example", + }, + ], + }, + { + text: "Rules", + collapsed: true, + items: [ + { + text: "pascal-case-construct-id", + link: "/ja/rules/pascal-case-construct-id", + }, + { + text: "no-parent-name-construct-id-match", + link: "/ja/rules/no-parent-name-construct-id-match", + }, + { + text: "no-construct-stack-suffix", + link: "/ja/rules/no-construct-stack-suffix", + }, + { + text: "no-class-in-interface", + link: "/ja/rules/no-class-in-interface", + }, + { + text: "no-public-class-fields", + link: "/ja/rules/no-public-class-fields", + }, + { + text: "no-import-private", + link: "/ja/rules/no-import-private", + }, + ], + }, + ], + socialLinks: [ + { + icon: { + svg: `GitHub`, + }, + link: "https://github.com/ren-yamanashi/eslint-plugin-cdk/tree/main", + }, + ], + }, + }, + }, +}); diff --git a/docs/.vitepress/sharedConfig.mts b/docs/.vitepress/sharedConfig.mts new file mode 100644 index 0000000..ca00e9b --- /dev/null +++ b/docs/.vitepress/sharedConfig.mts @@ -0,0 +1,11 @@ +import { DefaultTheme, UserConfig } from "vitepress"; + +export default { + themeConfig: { + outline: "deep", + search: { + provider: "local", + }, + }, + lastUpdated: true, +} satisfies UserConfig; diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js new file mode 100644 index 0000000..b607717 --- /dev/null +++ b/docs/.vitepress/theme/index.js @@ -0,0 +1,4 @@ +import DefaultTheme from 'vitepress/theme-without-fonts'; +import './main.css'; + +export default DefaultTheme; diff --git a/docs/.vitepress/theme/main.css b/docs/.vitepress/theme/main.css new file mode 100644 index 0000000..375622c --- /dev/null +++ b/docs/.vitepress/theme/main.css @@ -0,0 +1,67 @@ +/* TODO: theme color */ +:root { + /* --vp-button-brand-bg: #00A5EF; + --vp-c-brand: #00A5EF; + --vp-button-brand-border: #00A5EF; + --vp-button-brand-hover-bg: #00A5EF; + --vp-button-brand-hover-border: #00A5EF; + --vp-button-brand-active-bg: #00A5EF; + --vp-button-brand-active-border: #00A5EF; + --vp-home-hero-name-color: #00A5EF; + --vp-c-brand-1: #00A5EF; */ +} + +/* https://stackoverflow.com/questions/68789475/how-can-i-style-checkbox-with-css */ + +/* Basic styling */ + +[type='checkbox'] { + width: 1rem; + height: 1rem; + color: green; + vertical-align: middle; + -webkit-appearance: none; + background: none; + border: 0; + outline: 0; + flex-grow: 0; + border-radius: 50%; + background-color: #ffffff; + transition: background 300ms; + cursor: pointer; +} + +/* Pseudo element for check styling */ + +[type='checkbox']::before { + content: ''; + color: transparent; + display: block; + width: inherit; + height: inherit; + border-radius: inherit; + border: 0; + background-color: transparent; + background-size: contain; + box-shadow: inset 0 0 0 1px #ccd3d8; +} + +/* Checked */ + +[type='checkbox']:checked { + background-color: currentcolor; +} + +[type='checkbox']:checked::before { + box-shadow: none; + /* cSpell:disable */ + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E %3Cpath d='M15.88 8.29L10 14.17l-1.88-1.88a.996.996 0 1 0-1.41 1.41l2.59 2.59c.39.39 1.02.39 1.41 0L17.3 9.7a.996.996 0 0 0 0-1.41c-.39-.39-1.03-.39-1.42 0z' fill='%23fff'/%3E %3C/svg%3E"); +} + +/* Disabled */ + +[type='checkbox']:disabled { + background-color: #ccd3d8; + opacity: 0.84; + cursor: not-allowed; +} diff --git a/docs/getting-started/example.md b/docs/getting-started/example.md new file mode 100644 index 0000000..71b5cec --- /dev/null +++ b/docs/getting-started/example.md @@ -0,0 +1,45 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +prev: false +next: false +--- + +# Example + +Below is an example of eslint.config.mjs. + +Note: We recommend using typescript-eslint together. + +```js +import eslint from "@eslint/js"; +import cdkPlugin from "@nigg/eslint-plugin-cdk"; +import tsEslint from "typescript-eslint"; + +export default tsEslint.config( + eslint.configs.recommended, + ...tsEslint.configs.strict, + ...tsEslint.configs.stylistic, + { + files: ["**/*.ts"], + languageOptions: { + ecmaVersion: "latest", + sourceType: "module", + parserOptions: { + projectService: true, + project: "./tsconfig.json", + }, + }, + plugins: { + cdk: cdkPlugin, + }, + rules: { + ...cdkPlugin.configs.recommended.rules, + "cdk/no-import-private": "error", + }, + }, + { + ignores: ["node_modules"], + } +); +``` diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md new file mode 100644 index 0000000..e646632 --- /dev/null +++ b/docs/getting-started/index.md @@ -0,0 +1,67 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# eslint-plugin-cdk + +## Install + +Just run this: + +::: code-group + +```sh [npm] +npm install -D @nigg/eslint-plugin-cdk +``` + +```sh [yarn] +yarn add -D @nigg/eslint-plugin-cdk +``` + +```sh [pnpm] +pnpm install -D @nigg/eslint-plugin-cdk +``` + +::: + +## Setting eslint config + +Write eslint.config.mjs as follows: + +Note: This plugin only supports flatConfig + +```js +// eslint.config.mjs +import eslintPluginCdk from "@nigg/eslint-plugin-cdk"; +export default [ + { + plugins: { + cdk: eslintPluginCdk, + }, + rules: { + ...eslintPluginCdk.configs.recommended.rules, + }, + }, +]; +``` + +## Customize rules + +If you want to customize the rules, write eslint.config.mjs as follows: + +```js +// eslint.config.mjs +import eslintPluginCdk from "@nigg/eslint-plugin-cdk"; +export default [ + { + plugins: { + cdk: eslintPluginCdk, + }, + rules: { + ...eslintPluginCdk.configs.recommended.rules, + "cdk/no-public-class-fields": "warn", + }, + }, +]; +``` diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..bce8cc0 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,32 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: "eslint-plugin-cdk" + text: "ESLint plugin for AWS CDK" + tagline: AWS CDK best practices enforcing ESLint plugin + image: /img/eslint-plugin-cdk.png + actions: + - theme: brand + text: Getting Started + link: /getting-started/ + - theme: alt + text: View on GitHub + link: https://github.com/ren-yamanashi/eslint-plugin-cdk +features: + - title: Extensive Rules + details: Extensive rules for AWS CDK development. + link: /rules/ + linkText: see rules + icon: 📚 + - title: Purpose driven + details: A set of rules based on AWS CDK best practices, improving CloudFormation readability and maintainability. + icon: 🎯 + - title: Type Safety + details: Robust rules leveraging TypeScript's type system to help you write safer CDK code. + icon: 💪 + - title: Ease of use + details: Simple setup and installation and ready to use with recommended settings. + icon: 🔧 +--- diff --git a/docs/ja/getting-started/example.md b/docs/ja/getting-started/example.md new file mode 100644 index 0000000..a06ab60 --- /dev/null +++ b/docs/ja/getting-started/example.md @@ -0,0 +1,45 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +prev: false +next: false +--- + +# Example + +以下に、eslint.config.mjs の記述例を示します。 + +※typescript-eslint と一緒に使用することを推奨します。 + +```js +import eslint from "@eslint/js"; +import cdkPlugin from "@nigg/eslint-plugin-cdk"; +import tsEslint from "typescript-eslint"; + +export default tsEslint.config( + eslint.configs.recommended, + ...tsEslint.configs.strict, + ...tsEslint.configs.stylistic, + { + files: ["**/*.ts"], + languageOptions: { + ecmaVersion: "latest", + sourceType: "module", + parserOptions: { + projectService: true, + project: "./tsconfig.json", + }, + }, + plugins: { + cdk: cdkPlugin, + }, + rules: { + ...cdkPlugin.configs.recommended.rules, + "cdk/no-import-private": "error", + }, + }, + { + ignores: ["node_modules"], + } +); +``` diff --git a/docs/ja/getting-started/index.md b/docs/ja/getting-started/index.md new file mode 100644 index 0000000..b13d55e --- /dev/null +++ b/docs/ja/getting-started/index.md @@ -0,0 +1,67 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# eslint-plugin-cdk + +## インストール + +以下のコマンドを実行してインストールします。 + +::: code-group + +```sh [npm] +npm install -D @nigg/eslint-plugin-cdk +``` + +```sh [yarn] +yarn add -D @nigg/eslint-plugin-cdk +``` + +```sh [pnpm] +pnpm install -D @nigg/eslint-plugin-cdk +``` + +::: + +## eslint の設定 + +eslint.config.mjs を以下のように記述します。 + +※このプラグインは flatConfig のみをサポートしています。 + +```js +// eslint.config.mjs +import eslintPluginCdk from "@nigg/eslint-plugin-cdk"; +export default [ + { + plugins: { + cdk: eslintPluginCdk, + }, + rules: { + ...eslintPluginCdk.configs.recommended.rules, + }, + }, +]; +``` + +## ルールのカスタマイズ + +ルールをカスタマイズしたい場合は、eslint.config.mjs を以下のように記述します。 + +```js +// eslint.config.mjs +import eslintPluginCdk from "@nigg/eslint-plugin-cdk"; +export default [ + { + plugins: { + cdk: eslintPluginCdk, + }, + rules: { + ...eslintPluginCdk.configs.recommended.rules, + "cdk/no-public-class-fields": "warn", + }, + }, +]; +``` diff --git a/docs/ja/index.md b/docs/ja/index.md new file mode 100644 index 0000000..ac9ca50 --- /dev/null +++ b/docs/ja/index.md @@ -0,0 +1,32 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: "eslint-plugin-cdk" + text: "ESLint plugin for AWS CDK" + tagline: AWS CDK のベストプラクティスを強制する ESLint プラグイン + image: /img/eslint-plugin-cdk.png + actions: + - theme: brand + text: Getting Started + link: /ja/getting-started/ + - theme: alt + text: View on GitHub + link: https://github.com/ren-yamanashi/eslint-plugin-cdk +features: + - title: Extensive Rules + details: AWS CDK 開発のための広範なルールを提供します。 + link: /ja/rules/ + linkText: ルールを見る + icon: 📚 + - title: Purpose driven + details: AWS CDK のベストプラクティスに基づくルールを提供し、CloudFormation の読みやすさや保守性を向上させます。 + icon: 🎯 + - title: Type Safety + details: TypeScript の型システムを利用した堅牢なルールを提供し、より安全な CDK コードを書く手助けをします。 + icon: 💪 + - title: Ease of use + details: シンプルなセットアップとインストール、推奨設定ですぐに使用できます。 + icon: 🔧 +--- diff --git a/docs/ja/rules/no-class-in-interface.md b/docs/ja/rules/no-class-in-interface.md new file mode 100644 index 0000000..36f66d8 --- /dev/null +++ b/docs/ja/rules/no-class-in-interface.md @@ -0,0 +1,32 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# no-class-in-interface + +このルールは、インターフェイスのプロパティにクラスを使用することを禁止します。 + +インターフェイスのプロパティにクラスを使用すると、インターフェイスとクラス実装の間に密接な結合が作成されます。 +さらに、クラスは本質的に変更可能であるため、インターフェイスのプロパティ型としてクラスを使用すると予期しない動作が発生する可能性があります。 +したがって、このようなコードは避けるべきです。 + +#### ✅ 正しい例 + +```ts +import { IBucket } from "aws-cdk-lib/aws-s3"; + +interface MyConstructProps { + bucket: IBucket; +} +``` + +#### ❌ 不正な例 + +```ts +import { Bucket } from "aws-cdk-lib/aws-s3"; + +interface MyConstructProps { + bucket: Bucket; +} +``` diff --git a/docs/ja/rules/no-construct-stack-suffix.md b/docs/ja/rules/no-construct-stack-suffix.md new file mode 100644 index 0000000..32ff1f1 --- /dev/null +++ b/docs/ja/rules/no-construct-stack-suffix.md @@ -0,0 +1,32 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# no-construct-stack-suffix + +このルールは、コンストラクト ID およびスタック ID で `Construct` または `Stack` サフィックスの使用を禁止するものです。 + +コンストラクト ID に `Construct` が含まれていると、CDK の世界で止めるべき問題が CloudFormation テンプレートおよび AWS の世界に漏れてしまうため、好ましくありません。(スタック ID についても同様です) + +#### ✅ 正しい例 + +```ts +export class MyConstruct extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + const bucket = new Bucket(this, "MyBucket"); + } +} +``` + +#### ❌ 不正な例 + +```ts +export class MyConstruct extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + const bucket = new Bucket(this, "BucketConstruct"); + } +} +``` diff --git a/docs/ja/rules/no-import-private.md b/docs/ja/rules/no-import-private.md new file mode 100644 index 0000000..1b21289 --- /dev/null +++ b/docs/ja/rules/no-import-private.md @@ -0,0 +1,46 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +next: false +--- + +# no-import-private + +このルールは、異なる階層レベルの `private` ディレクトリからのモジュールのインポートを禁止します。 + +注: このルールは `recommended` ルールには含まれていません。 +設定する場合は、次のように記述する必要があります。 + +```js +// eslint.config.mjs +import eslintPluginCdk from "@nigg/eslint-plugin-cdk"; +export default [ + { + plugins: { + cdk: eslintPluginCdk, + }, + rules: { + ...cdkPlugin.configs.recommended.rules, + "cdk/no-import-private": "error", + }, + }, +]; +``` + +`private`ディレクトリは、親ディレクトリ内でのみ使用される内部実装を格納することを目的としています。 +異なる階層からのインポートを禁止することで、適切なモジュール化とカプセル化を促進します。 + +#### ✅ 正しい例 + +```ts +// src/constructs/my-construct.ts +import { MyConstruct } from "./private/my-construct"; +``` + +#### ❌ 不正な例 + +```ts +// src/constructs/my-construct.ts +import { MyConstruct } from "../private/my-construct"; +import { MyConstruct } from "../my-app/private/my-construct"; +``` diff --git a/docs/ja/rules/no-parent-name-construct-id-match.md b/docs/ja/rules/no-parent-name-construct-id-match.md new file mode 100644 index 0000000..6f8dba2 --- /dev/null +++ b/docs/ja/rules/no-parent-name-construct-id-match.md @@ -0,0 +1,32 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# no-parent-name-construct-id-match + +このルールでは、親クラス名をコンストラクト ID として使用することを禁止します。 + +コンストラクト ID に親クラス名と一致する文字列を指定すると、CloudFormation リソースの階層が不明瞭になるため、これは避けるべきです。 + +#### ✅ 正しい例 + +```ts +export class MyConstruct extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + const bucket = new Bucket(this, "MyBucket"); + } +} +``` + +#### ❌ 不正な例 + +```ts +export class MyConstruct extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + const bucket = new Bucket(this, "MyConstruct"); + } +} +``` diff --git a/docs/ja/rules/no-public-class-fields.md b/docs/ja/rules/no-public-class-fields.md new file mode 100644 index 0000000..56b30c5 --- /dev/null +++ b/docs/ja/rules/no-public-class-fields.md @@ -0,0 +1,38 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# no-public-class-fields + +このルールは、クラスの`public`変数にクラスを使用することを禁止します。 + +`public`変数でクラス型を使用すると、密結合が作成され、可変状態が公開されるため、好ましくありません。 + +#### ✅ 正しい例 + +```ts +import { IBucket } from "aws-cdk-lib/aws-s3"; + +class MyConstruct extends Construct { + public readonly bucket: IBucket; + constructor(scope: Construct, id: string) { + super(scope, id); + this.bucket = new Bucket(this, "MyBucket"); + } +} +``` + +#### ❌ 不正な例 + +```ts +import { Bucket } from "aws-cdk-lib/aws-s3"; + +class MyConstruct extends Construct { + public readonly bucket: Bucket; + constructor(scope: Construct, id: string) { + super(scope, id); + this.bucket = new Bucket(this, "MyBucket"); + } +} +``` diff --git a/docs/ja/rules/pascal-case-construct-id.md b/docs/ja/rules/pascal-case-construct-id.md new file mode 100644 index 0000000..ba5cdd0 --- /dev/null +++ b/docs/ja/rules/pascal-case-construct-id.md @@ -0,0 +1,21 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +prev: false +--- + +# pascal-case-construct-id + +このルールは、コンストラクト ID に PascalCase を強制します。 + +#### ✅ 正しい例 + +```ts +const bucket = new Bucket(this, "MyBucket"); +``` + +#### ❌ 不正な例 + +```ts +const bucket = new Bucket(this, "myBucket"); +``` diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..583466f --- /dev/null +++ b/docs/package.json @@ -0,0 +1,10 @@ +{ + "scripts": { + "dev": "vitepress dev --open", + "build": "vitepress build", + "preview": "vitepress preview" + }, + "devDependencies": { + "vitepress": "^1.5.0" + } +} diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml new file mode 100644 index 0000000..c0948fd --- /dev/null +++ b/docs/pnpm-lock.yaml @@ -0,0 +1,1417 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +devDependencies: + vitepress: + specifier: ^1.5.0 + version: 1.5.0(@algolia/client-search@4.22.0)(search-insights@2.13.0) + +packages: + + /@algolia/autocomplete-core@1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2)(search-insights@2.13.0): + resolution: {integrity: sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==} + dependencies: + '@algolia/autocomplete-plugin-algolia-insights': 1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2)(search-insights@2.13.0) + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2) + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + - search-insights + dev: true + + /@algolia/autocomplete-plugin-algolia-insights@1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2)(search-insights@2.13.0): + resolution: {integrity: sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==} + peerDependencies: + search-insights: '>= 1 < 3' + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2) + search-insights: 2.13.0 + transitivePeerDependencies: + - '@algolia/client-search' + - algoliasearch + dev: true + + /@algolia/autocomplete-preset-algolia@1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2): + resolution: {integrity: sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + dependencies: + '@algolia/autocomplete-shared': 1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2) + '@algolia/client-search': 4.22.0 + algoliasearch: 5.14.2 + dev: true + + /@algolia/autocomplete-shared@1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2): + resolution: {integrity: sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==} + peerDependencies: + '@algolia/client-search': '>= 4.9.1 < 6' + algoliasearch: '>= 4.9.1 < 6' + dependencies: + '@algolia/client-search': 4.22.0 + algoliasearch: 5.14.2 + dev: true + + /@algolia/cache-common@4.22.0: + resolution: {integrity: sha512-TPwUMlIGPN16eW67qamNQUmxNiGHg/WBqWcrOoCddhqNTqGDPVqmgfaM85LPbt24t3r1z0zEz/tdsmuq3Q6oaA==} + dev: true + + /@algolia/client-abtesting@5.14.2: + resolution: {integrity: sha512-7fq1tWIy1aNJEaNHxWy3EwDkuo4k22+NBnxq9QlYVSLLXtr6HqmAm6bQgNNzGT3vm21iKqWO9efk+HIhEM1SzQ==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/client-analytics@5.14.2: + resolution: {integrity: sha512-5Nm5cOOyAGcY+hKNJVmR2jgoGn1nvoANS8W5EfB8yAaUqUxL3lFNUHSkFafAMTCOcVKNDkZQYjUDbOOfdYJLqw==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/client-common@4.22.0: + resolution: {integrity: sha512-BlbkF4qXVWuwTmYxVWvqtatCR3lzXwxx628p1wj1Q7QP2+LsTmGt1DiUYRuy9jG7iMsnlExby6kRMOOlbhv2Ag==} + dependencies: + '@algolia/requester-common': 4.22.0 + '@algolia/transporter': 4.22.0 + dev: true + + /@algolia/client-common@5.14.2: + resolution: {integrity: sha512-BW1Qzhh9tMKEsWSQQsiOEcHAd6g7zxq9RpPVmyxbDO/O4eA4vyN+Qz5Jzo686kuYdIQKqIPCEtob/JM89tk57g==} + engines: {node: '>= 14.0.0'} + dev: true + + /@algolia/client-insights@5.14.2: + resolution: {integrity: sha512-17zg6pqifKORvvrMIqW6HhwUry9RKRXLgADrgFjZ6PZvGB4oVs12dwRG2/HMrIlpxd9cjeQfdlEgHj6lbAf6QA==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/client-personalization@5.14.2: + resolution: {integrity: sha512-5IYt8vbmTA52xyuaZKFwiRoDPeh7hiOC9aBZqqp9fVs6BU01djI/T8pGJXawvwczltCPYzNsdbllV3rqiDbxmQ==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/client-query-suggestions@5.14.2: + resolution: {integrity: sha512-gvCX/cczU76Bu1sGcxxTdoIwxe+FnuC1IlW9SF/gzxd3ZzsgzBpzD2puIJqt9fHQsjLxVGkJqKev2FtExnJYZg==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/client-search@4.22.0: + resolution: {integrity: sha512-bn4qQiIdRPBGCwsNuuqB8rdHhGKKWIij9OqidM1UkQxnSG8yzxHdb7CujM30pvp5EnV7jTqDZRbxacbjYVW20Q==} + dependencies: + '@algolia/client-common': 4.22.0 + '@algolia/requester-common': 4.22.0 + '@algolia/transporter': 4.22.0 + dev: true + + /@algolia/client-search@5.14.2: + resolution: {integrity: sha512-0imdBZDjqxrshw0+eyJUgnkRAbS2W93UQ3BVj8VjN4xQylIMf0fWs72W7MZFdHlH78JJYydevgzqvGMcV0Z1CA==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/ingestion@1.14.2: + resolution: {integrity: sha512-/p4rBNkW0fgCpCwrwre+jHfzlFQsLemgaAQqyui8NPxw95Wgf3p+DKxYzcmh8dygT7ub7FwztTW+uURLX1uqIQ==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/logger-common@4.22.0: + resolution: {integrity: sha512-HMUQTID0ucxNCXs5d1eBJ5q/HuKg8rFVE/vOiLaM4Abfeq1YnTtGV3+rFEhOPWhRQxNDd+YHa4q864IMc0zHpQ==} + dev: true + + /@algolia/monitoring@1.14.2: + resolution: {integrity: sha512-81R57Y/mS0uNhWpu6cNEfkbkADLW4bP0BNjuPpxAypobv7WzYycUnbMvv1YkN6OsociB4+3M7HfsVzj4Nc09vA==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/recommend@5.14.2: + resolution: {integrity: sha512-OwELnAZxCUyfjYjqsrFmC7Vfa12kqwbDdLUV0oi4j+4pxDsfPgkiZ6iCH2uPw6X8VK88Hl3InPt+RPaZvcrCWg==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /@algolia/requester-browser-xhr@5.14.2: + resolution: {integrity: sha512-irUvkK+TGBhyivtNCIIbVgNUgbUoHOSk8m/kFX4ddto/PUPmLFRRNNnMHtJ1+OzrJ/uD3Am4FUK2Yt+xgQr05w==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + dev: true + + /@algolia/requester-common@4.22.0: + resolution: {integrity: sha512-Y9cEH/cKjIIZgzvI1aI0ARdtR/xRrOR13g5psCxkdhpgRN0Vcorx+zePhmAa4jdQNqexpxtkUdcKYugBzMZJgQ==} + dev: true + + /@algolia/requester-fetch@5.14.2: + resolution: {integrity: sha512-UNBg5mM4MIYdxPuVjyDL22BC6P87g7WuM91Z1Ky0J19aEGvCSF+oR+9autthROFXdRnAa1rACOjuqn95iBbKpw==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + dev: true + + /@algolia/requester-node-http@5.14.2: + resolution: {integrity: sha512-CTFA03YiLcnpP+JoLRqjHt5pqDHuKWJpLsIBY/60Gmw8pjALZ3TwvbAquRX4Vy+yrin178NxMuU+ilZ54f2IrQ==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-common': 5.14.2 + dev: true + + /@algolia/transporter@4.22.0: + resolution: {integrity: sha512-ieO1k8x2o77GNvOoC+vAkFKppydQSVfbjM3YrSjLmgywiBejPTvU1R1nEvG59JIIUvtSLrZsLGPkd6vL14zopA==} + dependencies: + '@algolia/cache-common': 4.22.0 + '@algolia/logger-common': 4.22.0 + '@algolia/requester-common': 4.22.0 + dev: true + + /@babel/helper-string-parser@7.25.9: + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.25.9: + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/parser@7.26.2: + resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.26.0 + dev: true + + /@babel/types@7.26.0: + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + dev: true + + /@docsearch/css@3.8.0: + resolution: {integrity: sha512-pieeipSOW4sQ0+bE5UFC51AOZp9NGxg89wAlZ1BAQFaiRAGK1IKUaPQ0UGZeNctJXyqZ1UvBtOQh2HH+U5GtmA==} + dev: true + + /@docsearch/js@3.8.0(@algolia/client-search@4.22.0)(search-insights@2.13.0): + resolution: {integrity: sha512-PVuV629f5UcYRtBWqK7ID6vNL5647+2ADJypwTjfeBIrJfwPuHtzLy39hMGMfFK+0xgRyhTR0FZ83EkdEraBlg==} + dependencies: + '@docsearch/react': 3.8.0(@algolia/client-search@4.22.0)(search-insights@2.13.0) + preact: 10.19.3 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/react' + - react + - react-dom + - search-insights + dev: true + + /@docsearch/react@3.8.0(@algolia/client-search@4.22.0)(search-insights@2.13.0): + resolution: {integrity: sha512-WnFK720+iwTVt94CxY3u+FgX6exb3BfN5kE9xUY6uuAH/9W/UFboBZFLlrw/zxFRHoHZCOXRtOylsXF+6LHI+Q==} + peerDependencies: + '@types/react': '>= 16.8.0 < 19.0.0' + react: '>= 16.8.0 < 19.0.0' + react-dom: '>= 16.8.0 < 19.0.0' + search-insights: '>= 1 < 3' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + react-dom: + optional: true + search-insights: + optional: true + dependencies: + '@algolia/autocomplete-core': 1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2)(search-insights@2.13.0) + '@algolia/autocomplete-preset-algolia': 1.17.7(@algolia/client-search@4.22.0)(algoliasearch@5.14.2) + '@docsearch/css': 3.8.0 + algoliasearch: 5.14.2 + search-insights: 2.13.0 + transitivePeerDependencies: + - '@algolia/client-search' + dev: true + + /@esbuild/aix-ppc64@0.21.5: + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.21.5: + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.21.5: + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.21.5: + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.21.5: + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.21.5: + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.21.5: + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.21.5: + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.21.5: + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.21.5: + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.21.5: + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.21.5: + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.21.5: + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.21.5: + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.21.5: + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.21.5: + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.21.5: + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.21.5: + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.21.5: + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.21.5: + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.21.5: + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.21.5: + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.21.5: + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@iconify-json/simple-icons@1.2.11: + resolution: {integrity: sha512-AHCGDtBRqP+JzAbBzgO8uN/08CXxEmuaC6lQQZ3b5burKhRU12AJnJczwbUw2K5Mb/U85EpSUNhYMG3F28b8NA==} + dependencies: + '@iconify/types': 2.0.0 + dev: true + + /@iconify/types@2.0.0: + resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} + dev: true + + /@jridgewell/sourcemap-codec@1.5.0: + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + dev: true + + /@rollup/rollup-android-arm-eabi@4.27.2: + resolution: {integrity: sha512-Tj+j7Pyzd15wAdSJswvs5CJzJNV+qqSUcr/aCD+jpQSBtXvGnV0pnrjoc8zFTe9fcKCatkpFpOO7yAzpO998HA==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.27.2: + resolution: {integrity: sha512-xsPeJgh2ThBpUqlLgRfiVYBEf/P1nWlWvReG+aBWfNv3XEBpa6ZCmxSVnxJgLgkNz4IbxpLy64h2gCmAAQLneQ==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.27.2: + resolution: {integrity: sha512-KnXU4m9MywuZFedL35Z3PuwiTSn/yqRIhrEA9j+7OSkji39NzVkgxuxTYg5F8ryGysq4iFADaU5osSizMXhU2A==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.27.2: + resolution: {integrity: sha512-Hj77A3yTvUeCIx/Vi+4d4IbYhyTwtHj07lVzUgpUq9YpJSEiGJj4vXMKwzJ3w5zp5v3PFvpJNgc/J31smZey6g==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-freebsd-arm64@4.27.2: + resolution: {integrity: sha512-RjgKf5C3xbn8gxvCm5VgKZ4nn0pRAIe90J0/fdHUsgztd3+Zesb2lm2+r6uX4prV2eUByuxJNdt647/1KPRq5g==} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-freebsd-x64@4.27.2: + resolution: {integrity: sha512-duq21FoXwQtuws+V9H6UZ+eCBc7fxSpMK1GQINKn3fAyd9DFYKPJNcUhdIKOrMFjLEJgQskoMoiuizMt+dl20g==} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.27.2: + resolution: {integrity: sha512-6npqOKEPRZkLrMcvyC/32OzJ2srdPzCylJjiTJT2c0bwwSGm7nz2F9mNQ1WrAqCBZROcQn91Fno+khFhVijmFA==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-musleabihf@4.27.2: + resolution: {integrity: sha512-V9Xg6eXtgBtHq2jnuQwM/jr2mwe2EycnopO8cbOvpzFuySCGtKlPCI3Hj9xup/pJK5Q0388qfZZy2DqV2J8ftw==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.27.2: + resolution: {integrity: sha512-uCFX9gtZJoQl2xDTpRdseYuNqyKkuMDtH6zSrBTA28yTfKyjN9hQ2B04N5ynR8ILCoSDOrG/Eg+J2TtJ1e/CSA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.27.2: + resolution: {integrity: sha512-/PU9P+7Rkz8JFYDHIi+xzHabOu9qEWR07L5nWLIUsvserrxegZExKCi2jhMZRd0ATdboKylu/K5yAXbp7fYFvA==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-powerpc64le-gnu@4.27.2: + resolution: {integrity: sha512-eCHmol/dT5odMYi/N0R0HC8V8QE40rEpkyje/ZAXJYNNoSfrObOvG/Mn+s1F/FJyB7co7UQZZf6FuWnN6a7f4g==} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-riscv64-gnu@4.27.2: + resolution: {integrity: sha512-DEP3Njr9/ADDln3kNi76PXonLMSSMiCir0VHXxmGSHxCxDfQ70oWjHcJGfiBugzaqmYdTC7Y+8Int6qbnxPBIQ==} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-s390x-gnu@4.27.2: + resolution: {integrity: sha512-NHGo5i6IE/PtEPh5m0yw5OmPMpesFnzMIS/lzvN5vknnC1sXM5Z/id5VgcNPgpD+wHmIcuYYgW+Q53v+9s96lQ==} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.27.2: + resolution: {integrity: sha512-PaW2DY5Tan+IFvNJGHDmUrORadbe/Ceh8tQxi8cmdQVCCYsLoQo2cuaSj+AU+YRX8M4ivS2vJ9UGaxfuNN7gmg==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.27.2: + resolution: {integrity: sha512-dOlWEMg2gI91Qx5I/HYqOD6iqlJspxLcS4Zlg3vjk1srE67z5T2Uz91yg/qA8sY0XcwQrFzWWiZhMNERylLrpQ==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.27.2: + resolution: {integrity: sha512-euMIv/4x5Y2/ImlbGl88mwKNXDsvzbWUlT7DFky76z2keajCtcbAsN9LUdmk31hAoVmJJYSThgdA0EsPeTr1+w==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.27.2: + resolution: {integrity: sha512-RsnE6LQkUHlkC10RKngtHNLxb7scFykEbEwOFDjr3CeCMG+Rr+cKqlkKc2/wJ1u4u990urRHCbjz31x84PBrSQ==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.27.2: + resolution: {integrity: sha512-foJM5vv+z2KQmn7emYdDLyTbkoO5bkHZE1oth2tWbQNGW7mX32d46Hz6T0MqXdWS2vBZhaEtHqdy9WYwGfiliA==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@shikijs/core@1.23.0: + resolution: {integrity: sha512-J4Fo22oBlfRHAXec+1AEzcowv+Qdf4ZQkuP/X/UHYH9+KA9LvyFXSXyS+HxuBRFfon+u7bsmKdRBjoZlbDVRkQ==} + dependencies: + '@shikijs/engine-javascript': 1.23.0 + '@shikijs/engine-oniguruma': 1.23.0 + '@shikijs/types': 1.23.0 + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.3 + dev: true + + /@shikijs/engine-javascript@1.23.0: + resolution: {integrity: sha512-CcrppseWShG+8Efp1iil9divltuXVdCaU4iu+CKvzTGZO5RmXyAiSx668M7VbX8+s/vt1ZKu75Vn/jWi8O3G/Q==} + dependencies: + '@shikijs/types': 1.23.0 + '@shikijs/vscode-textmate': 9.3.0 + oniguruma-to-es: 0.1.2 + dev: true + + /@shikijs/engine-oniguruma@1.23.0: + resolution: {integrity: sha512-gS8bZLqVvmZXX+E5JUMJICsBp+kx6gj79MH/UEpKHKIqnUzppgbmEn6zLa6mB5D+sHse2gFei3YYJxQe1EzZXQ==} + dependencies: + '@shikijs/types': 1.23.0 + '@shikijs/vscode-textmate': 9.3.0 + dev: true + + /@shikijs/transformers@1.23.0: + resolution: {integrity: sha512-YzQN+m8nXNZjI7ZRk+8IdFa13qiOqIqjcm4jIQ31RzgMoHtpd9Ruma1hssnt2ETH3ixr8HEh+0zAuB9w/OBfnw==} + dependencies: + shiki: 1.23.0 + dev: true + + /@shikijs/types@1.23.0: + resolution: {integrity: sha512-HiwzsihRao+IbPk7FER/EQT/D0dEEK3n5LAtHDzL5iRT+JMblA7y9uitUnjEnHeLkKigNM+ZplrP7MuEyyc5kA==} + dependencies: + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + dev: true + + /@shikijs/vscode-textmate@9.3.0: + resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} + dev: true + + /@types/estree@1.0.6: + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + dev: true + + /@types/hast@3.0.4: + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + dependencies: + '@types/unist': 3.0.2 + dev: true + + /@types/linkify-it@5.0.0: + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + dev: true + + /@types/markdown-it@14.1.2: + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + dev: true + + /@types/mdast@4.0.3: + resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + dependencies: + '@types/unist': 3.0.2 + dev: true + + /@types/mdurl@2.0.0: + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + dev: true + + /@types/unist@3.0.2: + resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + dev: true + + /@types/web-bluetooth@0.0.20: + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@vitejs/plugin-vue@5.2.0(vite@5.4.11)(vue@3.5.13): + resolution: {integrity: sha512-7n7KdUEtx/7Yl7I/WVAMZ1bEb0eVvXF3ummWTeLcs/9gvo9pJhuLdouSXGjdZ/MKD1acf1I272+X0RMua4/R3g==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 + vue: ^3.2.25 + dependencies: + vite: 5.4.11 + vue: 3.5.13 + dev: true + + /@vue/compiler-core@3.5.13: + resolution: {integrity: sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==} + dependencies: + '@babel/parser': 7.26.2 + '@vue/shared': 3.5.13 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.2.1 + dev: true + + /@vue/compiler-dom@3.5.13: + resolution: {integrity: sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==} + dependencies: + '@vue/compiler-core': 3.5.13 + '@vue/shared': 3.5.13 + dev: true + + /@vue/compiler-sfc@3.5.13: + resolution: {integrity: sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==} + dependencies: + '@babel/parser': 7.26.2 + '@vue/compiler-core': 3.5.13 + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + estree-walker: 2.0.2 + magic-string: 0.30.12 + postcss: 8.4.49 + source-map-js: 1.2.1 + dev: true + + /@vue/compiler-ssr@3.5.13: + resolution: {integrity: sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==} + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/shared': 3.5.13 + dev: true + + /@vue/devtools-api@7.6.4: + resolution: {integrity: sha512-5AaJ5ELBIuevmFMZYYLuOO9HUuY/6OlkOELHE7oeDhy4XD/hSODIzktlsvBOsn+bto3aD0psj36LGzwVu5Ip8w==} + dependencies: + '@vue/devtools-kit': 7.6.4 + dev: true + + /@vue/devtools-kit@7.6.4: + resolution: {integrity: sha512-Zs86qIXXM9icU0PiGY09PQCle4TI750IPLmAJzW5Kf9n9t5HzSYf6Rz6fyzSwmfMPiR51SUKJh9sXVZu78h2QA==} + dependencies: + '@vue/devtools-shared': 7.6.4 + birpc: 0.2.19 + hookable: 5.5.3 + mitt: 3.0.1 + perfect-debounce: 1.0.0 + speakingurl: 14.0.1 + superjson: 2.2.1 + dev: true + + /@vue/devtools-shared@7.6.4: + resolution: {integrity: sha512-nD6CUvBEel+y7zpyorjiUocy0nh77DThZJ0k1GRnJeOmY3ATq2fWijEp7wk37gb023Cb0R396uYh5qMSBQ5WFg==} + dependencies: + rfdc: 1.4.1 + dev: true + + /@vue/reactivity@3.5.13: + resolution: {integrity: sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==} + dependencies: + '@vue/shared': 3.5.13 + dev: true + + /@vue/runtime-core@3.5.13: + resolution: {integrity: sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==} + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/shared': 3.5.13 + dev: true + + /@vue/runtime-dom@3.5.13: + resolution: {integrity: sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==} + dependencies: + '@vue/reactivity': 3.5.13 + '@vue/runtime-core': 3.5.13 + '@vue/shared': 3.5.13 + csstype: 3.1.3 + dev: true + + /@vue/server-renderer@3.5.13(vue@3.5.13): + resolution: {integrity: sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==} + peerDependencies: + vue: 3.5.13 + dependencies: + '@vue/compiler-ssr': 3.5.13 + '@vue/shared': 3.5.13 + vue: 3.5.13 + dev: true + + /@vue/shared@3.5.13: + resolution: {integrity: sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==} + dev: true + + /@vueuse/core@11.2.0(vue@3.5.13): + resolution: {integrity: sha512-JIUwRcOqOWzcdu1dGlfW04kaJhW3EXnnjJJfLTtddJanymTL7lF1C0+dVVZ/siLfc73mWn+cGP1PE1PKPruRSA==} + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 11.2.0 + '@vueuse/shared': 11.2.0(vue@3.5.13) + vue-demi: 0.14.10(vue@3.5.13) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@vueuse/integrations@11.2.0(focus-trap@7.6.2)(vue@3.5.13): + resolution: {integrity: sha512-zGXz3dsxNHKwiD9jPMvR3DAxQEOV6VWIEYTGVSB9PNpk4pTWR+pXrHz9gvXWcP2sTk3W2oqqS6KwWDdntUvNVA==} + peerDependencies: + async-validator: ^4 + axios: ^1 + change-case: ^5 + drauu: ^0.4 + focus-trap: ^7 + fuse.js: ^7 + idb-keyval: ^6 + jwt-decode: ^4 + nprogress: ^0.2 + qrcode: ^1.5 + sortablejs: ^1 + universal-cookie: ^7 + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + dependencies: + '@vueuse/core': 11.2.0(vue@3.5.13) + '@vueuse/shared': 11.2.0(vue@3.5.13) + focus-trap: 7.6.2 + vue-demi: 0.14.10(vue@3.5.13) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /@vueuse/metadata@11.2.0: + resolution: {integrity: sha512-L0ZmtRmNx+ZW95DmrgD6vn484gSpVeRbgpWevFKXwqqQxW9hnSi2Ppuh2BzMjnbv4aJRiIw8tQatXT9uOB23dQ==} + dev: true + + /@vueuse/shared@11.2.0(vue@3.5.13): + resolution: {integrity: sha512-VxFjie0EanOudYSgMErxXfq6fo8vhr5ICI+BuE3I9FnX7ePllEsVrRQ7O6Q1TLgApeLuPKcHQxAXpP+KnlrJsg==} + dependencies: + vue-demi: 0.14.10(vue@3.5.13) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: true + + /algoliasearch@5.14.2: + resolution: {integrity: sha512-aYjI4WLamMxbhdJ2QAA99VbDCJOGzMOdT2agh57bi40n86ufkhZSIAf6mkocr7NmtBLtwCnSHvD5NJ+Ky5elWw==} + engines: {node: '>= 14.0.0'} + dependencies: + '@algolia/client-abtesting': 5.14.2 + '@algolia/client-analytics': 5.14.2 + '@algolia/client-common': 5.14.2 + '@algolia/client-insights': 5.14.2 + '@algolia/client-personalization': 5.14.2 + '@algolia/client-query-suggestions': 5.14.2 + '@algolia/client-search': 5.14.2 + '@algolia/ingestion': 1.14.2 + '@algolia/monitoring': 1.14.2 + '@algolia/recommend': 5.14.2 + '@algolia/requester-browser-xhr': 5.14.2 + '@algolia/requester-fetch': 5.14.2 + '@algolia/requester-node-http': 5.14.2 + dev: true + + /birpc@0.2.19: + resolution: {integrity: sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==} + dev: true + + /ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + dev: true + + /character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + dev: true + + /character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + dev: true + + /comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + dev: true + + /copy-anything@3.0.5: + resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.16 + dev: true + + /csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + dev: true + + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: true + + /devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + dependencies: + dequal: 2.0.3 + dev: true + + /emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + + /esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + dev: true + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /focus-trap@7.6.2: + resolution: {integrity: sha512-9FhUxK1hVju2+AiQIDJ5Dd//9R2n2RAfJ0qfhF4IHGHgcoEUTMpbTeG/zbEuwaiYXfuAH6XE0/aCyxDdRM+W5w==} + dependencies: + tabbable: 6.2.0 + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /hast-util-to-html@9.0.3: + resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.2 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.0.2 + property-information: 6.4.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.3 + zwitch: 2.0.4 + dev: true + + /hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + dependencies: + '@types/hast': 3.0.4 + dev: true + + /hookable@5.5.3: + resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} + dev: true + + /html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + dev: true + + /is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + dev: true + + /magic-string@0.30.12: + resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + dev: true + + /mark.js@8.11.1: + resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} + dev: true + + /mdast-util-to-hast@13.0.2: + resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==} + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + '@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 + dev: true + + /micromark-util-character@2.0.1: + resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==} + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: true + + /micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + dev: true + + /micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + dependencies: + micromark-util-character: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + dev: true + + /micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + dev: true + + /micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + dev: true + + /minisearch@7.1.0: + resolution: {integrity: sha512-tv7c/uefWdEhcu6hvrfTihflgeEi2tN6VV7HJnCjK6VxM75QQJh4t9FwJCsA2EsRS8LCnu3W87CuGPWMocOLCA==} + dev: true + + /mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + dev: true + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /oniguruma-to-es@0.1.2: + resolution: {integrity: sha512-sBYKVJlIMB0WPO+tSu/NNB1ytSFeHyyJZ3Ayxfx3f/QUuXu0lvZk0VB4K7npmdlHSC0ldqanzh/sUSlAbgCTfw==} + dependencies: + emoji-regex-xs: 1.0.0 + regex: 4.4.0 + regex-recursion: 4.2.1 + dev: true + + /perfect-debounce@1.0.0: + resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} + dev: true + + /picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + dev: true + + /postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + dev: true + + /preact@10.19.3: + resolution: {integrity: sha512-nHHTeFVBTHRGxJXKkKu5hT8C/YWBkPso4/Gad6xuj5dbptt9iF9NZr9pHbPhBrnT2klheu7mHTxTZ/LjwJiEiQ==} + dev: true + + /property-information@6.4.0: + resolution: {integrity: sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==} + dev: true + + /regex-recursion@4.2.1: + resolution: {integrity: sha512-QHNZyZAeKdndD1G3bKAbBEKOSSK4KOHQrAJ01N1LJeb0SoH4DJIeFhp0uUpETgONifS4+P3sOgoA1dhzgrQvhA==} + dependencies: + regex-utilities: 2.3.0 + dev: true + + /regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + dev: true + + /regex@4.4.0: + resolution: {integrity: sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==} + dev: true + + /rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + dev: true + + /rollup@4.27.2: + resolution: {integrity: sha512-KreA+PzWmk2yaFmZVwe6GB2uBD86nXl86OsDkt1bJS9p3vqWuEQ6HnJJ+j/mZi/q0920P99/MVRlB4L3crpF5w==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.27.2 + '@rollup/rollup-android-arm64': 4.27.2 + '@rollup/rollup-darwin-arm64': 4.27.2 + '@rollup/rollup-darwin-x64': 4.27.2 + '@rollup/rollup-freebsd-arm64': 4.27.2 + '@rollup/rollup-freebsd-x64': 4.27.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.27.2 + '@rollup/rollup-linux-arm-musleabihf': 4.27.2 + '@rollup/rollup-linux-arm64-gnu': 4.27.2 + '@rollup/rollup-linux-arm64-musl': 4.27.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.27.2 + '@rollup/rollup-linux-riscv64-gnu': 4.27.2 + '@rollup/rollup-linux-s390x-gnu': 4.27.2 + '@rollup/rollup-linux-x64-gnu': 4.27.2 + '@rollup/rollup-linux-x64-musl': 4.27.2 + '@rollup/rollup-win32-arm64-msvc': 4.27.2 + '@rollup/rollup-win32-ia32-msvc': 4.27.2 + '@rollup/rollup-win32-x64-msvc': 4.27.2 + fsevents: 2.3.3 + dev: true + + /search-insights@2.13.0: + resolution: {integrity: sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==} + dev: true + + /shiki@1.23.0: + resolution: {integrity: sha512-xfdu9DqPkIpExH29cmiTlgo0/jBki5la1Tkfhsv+Wu5TT3APLNHslR1acxuKJOCWqVdSc+pIbs/2ozjVRGppdg==} + dependencies: + '@shikijs/core': 1.23.0 + '@shikijs/engine-javascript': 1.23.0 + '@shikijs/engine-oniguruma': 1.23.0 + '@shikijs/types': 1.23.0 + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + dev: true + + /source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + dev: true + + /space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + dev: true + + /speakingurl@14.0.1: + resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} + engines: {node: '>=0.10.0'} + dev: true + + /stringify-entities@4.0.3: + resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + dev: true + + /superjson@2.2.1: + resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==} + engines: {node: '>=16'} + dependencies: + copy-anything: 3.0.5 + dev: true + + /tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + dev: true + + /trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + dev: true + + /unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + dependencies: + '@types/unist': 3.0.2 + dev: true + + /unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + dependencies: + '@types/unist': 3.0.2 + dev: true + + /unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + dev: true + + /unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: true + + /vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + esbuild: 0.21.5 + postcss: 8.4.49 + rollup: 4.27.2 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vitepress@1.5.0(@algolia/client-search@4.22.0)(search-insights@2.13.0): + resolution: {integrity: sha512-q4Q/G2zjvynvizdB3/bupdYkCJe2umSAMv9Ju4d92E6/NXJ59z70xB0q5p/4lpRyAwflDsbwy1mLV9Q5+nlB+g==} + hasBin: true + peerDependencies: + markdown-it-mathjax3: ^4 + postcss: ^8 + peerDependenciesMeta: + markdown-it-mathjax3: + optional: true + postcss: + optional: true + dependencies: + '@docsearch/css': 3.8.0 + '@docsearch/js': 3.8.0(@algolia/client-search@4.22.0)(search-insights@2.13.0) + '@iconify-json/simple-icons': 1.2.11 + '@shikijs/core': 1.23.0 + '@shikijs/transformers': 1.23.0 + '@shikijs/types': 1.23.0 + '@types/markdown-it': 14.1.2 + '@vitejs/plugin-vue': 5.2.0(vite@5.4.11)(vue@3.5.13) + '@vue/devtools-api': 7.6.4 + '@vue/shared': 3.5.13 + '@vueuse/core': 11.2.0(vue@3.5.13) + '@vueuse/integrations': 11.2.0(focus-trap@7.6.2)(vue@3.5.13) + focus-trap: 7.6.2 + mark.js: 8.11.1 + minisearch: 7.1.0 + shiki: 1.23.0 + vite: 5.4.11 + vue: 3.5.13 + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/node' + - '@types/react' + - '@vue/composition-api' + - async-validator + - axios + - change-case + - drauu + - fuse.js + - idb-keyval + - jwt-decode + - less + - lightningcss + - nprogress + - qrcode + - react + - react-dom + - sass + - sass-embedded + - search-insights + - sortablejs + - stylus + - sugarss + - terser + - typescript + - universal-cookie + dev: true + + /vue-demi@0.14.10(vue@3.5.13): + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dependencies: + vue: 3.5.13 + dev: true + + /vue@3.5.13: + resolution: {integrity: sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@vue/compiler-dom': 3.5.13 + '@vue/compiler-sfc': 3.5.13 + '@vue/runtime-dom': 3.5.13 + '@vue/server-renderer': 3.5.13(vue@3.5.13) + '@vue/shared': 3.5.13 + dev: true + + /zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + dev: true diff --git a/docs/public/img/eslint-plugin-cdk.png b/docs/public/img/eslint-plugin-cdk.png new file mode 100644 index 0000000..d03070a Binary files /dev/null and b/docs/public/img/eslint-plugin-cdk.png differ diff --git a/docs/rules/no-class-in-interface.md b/docs/rules/no-class-in-interface.md new file mode 100644 index 0000000..e7910b0 --- /dev/null +++ b/docs/rules/no-class-in-interface.md @@ -0,0 +1,32 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# no-class-in-interface + +This rule disallows using class types in interface properties. + +When class types are used in interface properties, it creates tight coupling between the interface and the class implementation. +Additionally, classes are mutable by nature, which can lead to unexpected behavior when used as interface property types. +So not good. + +#### ✅ Correct Example + +```ts +import { IBucket } from "aws-cdk-lib/aws-s3"; + +interface MyConstructProps { + bucket: IBucket; +} +``` + +#### ❌ Incorrect Example + +```ts +import { Bucket } from "aws-cdk-lib/aws-s3"; + +interface MyConstructProps { + bucket: Bucket; +} +``` diff --git a/docs/rules/no-construct-stack-suffix.md b/docs/rules/no-construct-stack-suffix.md new file mode 100644 index 0000000..f072d4f --- /dev/null +++ b/docs/rules/no-construct-stack-suffix.md @@ -0,0 +1,32 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# no-construct-stack-suffix + +This rule is to disallow using the `Construct` or `Stack` suffix in construct IDs and stack IDs. + +If the Construct ID includes "Construct," the issues that should be stopped in the CDK world will leak into the CloudFormation template and the AWS world, so not good.(the same for Stack ID ) + +#### ✅ Correct Example + +```ts +export class MyConstruct extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + const bucket = new Bucket(this, "MyBucket"); + } +} +``` + +#### ❌ Incorrect Example + +```ts +export class MyConstruct extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + const bucket = new Bucket(this, "BucketConstruct"); + } +} +``` diff --git a/docs/rules/no-import-private.md b/docs/rules/no-import-private.md new file mode 100644 index 0000000..7896f2a --- /dev/null +++ b/docs/rules/no-import-private.md @@ -0,0 +1,46 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +next: false +--- + +# no-import-private + +This rule disallows importing modules from `private` directories at different hierarchical levels. + +Note: This rule is not included in the `recommended` rules. +When setting it, you need to write the following: + +```js +// eslint.config.mjs +import eslintPluginCdk from "@nigg/eslint-plugin-cdk"; +export default [ + { + plugins: { + cdk: eslintPluginCdk, + }, + rules: { + ...cdkPlugin.configs.recommended.rules, + "cdk/no-import-private": "error", + }, + }, +]; +``` + +The private directory is intended to contain internal implementation that should only be used within its parent directory. +By disallowing imports from a different hierarchy, it promotes proper modularization and encapsulation. + +#### ✅ Correct Example + +```ts +// src/constructs/my-construct.ts +import { MyConstruct } from "./private/my-construct"; +``` + +#### ❌ Incorrect Example + +```ts +// src/constructs/my-construct.ts +import { MyConstruct } from "../private/my-construct"; +import { MyConstruct } from "../my-app/private/my-construct"; +``` diff --git a/docs/rules/no-parent-name-construct-id-match.md b/docs/rules/no-parent-name-construct-id-match.md new file mode 100644 index 0000000..ab1e9c0 --- /dev/null +++ b/docs/rules/no-parent-name-construct-id-match.md @@ -0,0 +1,32 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# no-parent-name-construct-id-match + +This rule disallows using the parent class name as the construct IDs. + +It is not good to specify a string that matches the parent class name for construct ID, as it makes the CloudFormation resource hierarchy unclear. + +#### ✅ Correct Example + +```ts +export class MyConstruct extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + const bucket = new Bucket(this, "MyBucket"); + } +} +``` + +#### ❌ Incorrect Example + +```ts +export class MyConstruct extends Construct { + constructor(scope: Construct, id: string) { + super(scope, id); + const bucket = new Bucket(this, "MyConstruct"); + } +} +``` diff --git a/docs/rules/no-public-class-fields.md b/docs/rules/no-public-class-fields.md new file mode 100644 index 0000000..73b2be2 --- /dev/null +++ b/docs/rules/no-public-class-fields.md @@ -0,0 +1,38 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +--- + +# no-public-class-fields + +This rule disallows using class types for public class fields. + +When class types are used in public fields, it creates tight coupling and exposes mutable state, so not good. + +#### ✅ Correct Examples + +```ts +import { IBucket } from "aws-cdk-lib/aws-s3"; + +class MyConstruct extends Construct { + public readonly bucket: IBucket; + constructor(scope: Construct, id: string) { + super(scope, id); + this.bucket = new Bucket(this, "MyBucket"); + } +} +``` + +#### ❌ Incorrect Examples + +```ts +import { Bucket } from "aws-cdk-lib/aws-s3"; + +class MyConstruct extends Construct { + public readonly bucket: Bucket; + constructor(scope: Construct, id: string) { + super(scope, id); + this.bucket = new Bucket(this, "MyBucket"); + } +} +``` diff --git a/docs/rules/pascal-case-construct-id.md b/docs/rules/pascal-case-construct-id.md new file mode 100644 index 0000000..99ff341 --- /dev/null +++ b/docs/rules/pascal-case-construct-id.md @@ -0,0 +1,21 @@ +--- +title: eslint-plugin-cdk - ESLint plugin for AWS CDK +titleTemplate: ":title" +prev: false +--- + +# pascal-case-construct-id + +This rule enforces PascalCase for construct IDs. + +#### ✅ Correct Example + +```ts +const bucket = new Bucket(this, "MyBucket"); +``` + +#### ❌ Incorrect Example + +```ts +const bucket = new Bucket(this, "myBucket"); +``` diff --git a/eslint.config.mjs b/eslint.config.mjs index 879c156..0c6d59e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -71,6 +71,8 @@ export default tsEslint.config( ".vscode", "package.json", "vitest.config.mjs", + "docs", + "examples", ], } ); diff --git a/package.json b/package.json index 031c0a8..95500d3 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,10 @@ "lint": "eslint --fix --config eslint.config.mjs", "release:minor": "standard-version --release-as minor", "release:major": "standard-version --release-as major", - "release:patch": "standard-version --release-as patch" + "release:patch": "standard-version --release-as patch", + "docs:dev": "cd ./docs && pnpm install && pnpm run dev", + "docs:build": "cd ./docs && pnpm install && pnpm run build", + "docs:preview": "cd ./docs && pnpm install && pnpm run preview" }, "devDependencies": { "@eslint/js": "^9.15.0", @@ -28,7 +31,7 @@ "eslint": "9.10.0" }, "volta": { - "node": "20.11.0" + "node": "22.11.0" }, "files": [ "dist",