From b646111b4017cf02cbbeb9a722183fb65b3a82a7 Mon Sep 17 00:00:00 2001 From: Kevin Pfeifer Date: Sat, 4 Apr 2026 21:00:52 +0200 Subject: [PATCH] convert docs to Vitepress --- .github/workflows/deploy_docs_5x.yml | 3 +- .github/workflows/docs-validation.yml | 27 + Dockerfile | 36 + docs.Dockerfile | 26 - docs/.gitignore | 4 + docs/.vitepress/config.js | 64 + docs/.vitepress/theme/index.js | 1 + docs/.vitepress/toc_en.json | 30 + docs/.vitepress/toc_ja.json | 11 + docs/config/__init__.py | 0 docs/config/all.py | 48 - docs/en/3-0-upgrade-guide.md | 22 + docs/en/3-0-upgrade-guide.rst | 31 - docs/en/4-0-upgrade-guide.md | 31 + docs/en/4-0-upgrade-guide.rst | 35 - docs/en/5-0-upgrade-guide.md | 198 ++ docs/en/5-0-upgrade-guide.rst | 215 -- docs/en/conf.py | 10 - docs/en/contents.rst | 11 - docs/en/embedded-documents.md | 40 + docs/en/index.md | 14 + docs/en/index.rst | 423 ---- docs/en/indexes-and-documents.md | 106 + docs/en/installation.md | 92 + docs/en/searching-and-saving.md | 111 + docs/en/testing.md | 74 + docs/ja/conf.py | 10 - docs/ja/contents.rst | 8 - docs/ja/index.md | 224 ++ docs/ja/index.rst | 314 --- docs/package-lock.json | 2104 +++++++++++++++++ docs/package.json | 19 + docs/public/favicon/apple-touch-icon.png | Bin 0 -> 3756 bytes docs/public/favicon/favicon-96x96.png | Bin 0 -> 2228 bytes docs/public/favicon/favicon.ico | Bin 0 -> 15086 bytes docs/public/favicon/favicon.svg | 3 + docs/public/favicon/site.webmanifest | 21 + .../favicon/web-app-manifest-192x192.png | Bin 0 -> 3834 bytes .../favicon/web-app-manifest-512x512.png | Bin 0 -> 15544 bytes docs/public/fonts/cakedingbats-webfont.eot | Bin 0 -> 14117 bytes docs/public/fonts/cakedingbats-webfont.svg | 56 + docs/public/fonts/cakedingbats-webfont.ttf | Bin 0 -> 21792 bytes docs/public/fonts/cakedingbats-webfont.woff | Bin 0 -> 15356 bytes docs/public/fonts/cakedingbats-webfont.woff2 | Bin 0 -> 13380 bytes docs/public/logo.svg | 27 + 45 files changed, 3317 insertions(+), 1132 deletions(-) create mode 100644 .github/workflows/docs-validation.yml create mode 100644 Dockerfile delete mode 100644 docs.Dockerfile create mode 100644 docs/.gitignore create mode 100644 docs/.vitepress/config.js create mode 100644 docs/.vitepress/theme/index.js create mode 100644 docs/.vitepress/toc_en.json create mode 100644 docs/.vitepress/toc_ja.json delete mode 100644 docs/config/__init__.py delete mode 100644 docs/config/all.py create mode 100644 docs/en/3-0-upgrade-guide.md delete mode 100644 docs/en/3-0-upgrade-guide.rst create mode 100644 docs/en/4-0-upgrade-guide.md delete mode 100644 docs/en/4-0-upgrade-guide.rst create mode 100644 docs/en/5-0-upgrade-guide.md delete mode 100644 docs/en/5-0-upgrade-guide.rst delete mode 100644 docs/en/conf.py delete mode 100644 docs/en/contents.rst create mode 100644 docs/en/embedded-documents.md create mode 100644 docs/en/index.md delete mode 100644 docs/en/index.rst create mode 100644 docs/en/indexes-and-documents.md create mode 100644 docs/en/installation.md create mode 100644 docs/en/searching-and-saving.md create mode 100644 docs/en/testing.md delete mode 100644 docs/ja/conf.py delete mode 100644 docs/ja/contents.rst create mode 100644 docs/ja/index.md delete mode 100644 docs/ja/index.rst create mode 100644 docs/package-lock.json create mode 100644 docs/package.json create mode 100644 docs/public/favicon/apple-touch-icon.png create mode 100644 docs/public/favicon/favicon-96x96.png create mode 100644 docs/public/favicon/favicon.ico create mode 100644 docs/public/favicon/favicon.svg create mode 100644 docs/public/favicon/site.webmanifest create mode 100644 docs/public/favicon/web-app-manifest-192x192.png create mode 100644 docs/public/favicon/web-app-manifest-512x512.png create mode 100644 docs/public/fonts/cakedingbats-webfont.eot create mode 100644 docs/public/fonts/cakedingbats-webfont.svg create mode 100644 docs/public/fonts/cakedingbats-webfont.ttf create mode 100644 docs/public/fonts/cakedingbats-webfont.woff create mode 100644 docs/public/fonts/cakedingbats-webfont.woff2 create mode 100644 docs/public/logo.svg diff --git a/.github/workflows/deploy_docs_5x.yml b/.github/workflows/deploy_docs_5x.yml index 699f9cc3..90187f6e 100644 --- a/.github/workflows/deploy_docs_5x.yml +++ b/.github/workflows/deploy_docs_5x.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cloning repo - uses: actions/checkout@v2 + uses: actions/checkout@v6 with: fetch-depth: 0 @@ -20,5 +20,6 @@ jobs: uses: dokku/github-action@master with: git_remote_url: 'ssh://dokku@apps.cakephp.org:22/elasticsearch-docs-5' + git_push_flags: '-f' ssh_private_key: ${{ secrets.DOKKU_SSH_PRIVATE_KEY }} branch: '5.x' diff --git a/.github/workflows/docs-validation.yml b/.github/workflows/docs-validation.yml new file mode 100644 index 00000000..439a52c1 --- /dev/null +++ b/.github/workflows/docs-validation.yml @@ -0,0 +1,27 @@ +name: Documentation Validation + +on: + push: + branches: + - 5.x + paths: + - 'docs/**' + - '.github/**' + pull_request: + paths: + - 'docs/**' + - '.github/**' + +jobs: + validate: + uses: cakephp/.github/.github/workflows/docs-validation.yml@5.x + with: + docs-path: 'docs' + vitepress-path: 'docs/.vitepress' + enable-config-js-check: true + enable-json-lint: true + enable-toc-check: true + enable-spell-check: true + enable-markdown-lint: true + enable-link-check: true + tools-ref: '5.x' diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..d1f12952 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +# ---------------------- +# 1. Build stage +# ---------------------- +FROM node:24-alpine AS builder + +# Git is required because docs/package.json pulls a dependency from GitHub. +RUN apk add --no-cache git openssh-client + +WORKDIR /app/docs + +# Copy dependency manifests first to preserve Docker layer caching. +COPY docs/ ./ +RUN npm ci + +# Increase max-old-space-size to avoid memory issues during build +#ENV NODE_OPTIONS="--max-old-space-size=8192" + +# Build the site. +RUN npm run docs:build + +# ---------------------- +# 2. Runtime stage (angie) +# ---------------------- +FROM docker.angie.software/angie:latest AS runner + +# Copy built files +COPY --from=builder /app/docs/.vitepress/dist /usr/share/angie/html + +# Expose port +EXPOSE 80 + +# Health check (optional) +HEALTHCHECK CMD wget --quiet --tries=1 --spider http://localhost:80/ || exit 1 + +# Start angie +CMD ["angie", "-g", "daemon off;"] diff --git a/docs.Dockerfile b/docs.Dockerfile deleted file mode 100644 index f6345917..00000000 --- a/docs.Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -# Generate the HTML output. -FROM ghcr.io/cakephp/docs-builder as builder - -COPY docs /data/docs -ENV LANGS="en ja" - -# Build docs with sphinx -RUN cd /data/docs-builder && \ - make website LANGS="$LANGS" SOURCE=/data/docs DEST=/data/website/ - - -# Build a small nginx container with just the static site in it. -FROM ghcr.io/cakephp/docs-builder:runtime as runtime - -# Configure search index script -ENV LANGS="en ja" -ENV SEARCH_SOURCE="/usr/share/nginx/html" -ENV SEARCH_URL_PREFIX="/elasticsearch/5" - -COPY --from=builder /data/docs /data/docs -COPY --from=builder /data/website /data/website -COPY --from=builder /data/docs-builder/nginx.conf /etc/nginx/conf.d/default.conf - -# Move build docs in place -RUN cp -R /data/website/html/* /usr/share/nginx/html \ - && rm -rf /data/website/ diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..974d64e4 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,4 @@ +node_modules +*/public/ +.vitepress/cache +.vitepress/dist diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js new file mode 100644 index 00000000..d1ee79cf --- /dev/null +++ b/docs/.vitepress/config.js @@ -0,0 +1,64 @@ +import baseConfig from '@cakephp/docs-skeleton/config' +import { createRequire } from 'module' + +const require = createRequire(import.meta.url) +const tocEn = require('./toc_en.json') +const tocJa = require('./toc_ja.json') + +const versions = { + text: '5.x', + items: [ + { text: '5.x (current)', link: 'https://book.cakephp.org/elasticsearch/5/', target: '_self' }, + { text: '4.x', link: 'https://book.cakephp.org/elasticsearch/4/', target: '_self' }, + { text: '3.x', link: 'https://book.cakephp.org/elasticsearch/3/', target: '_self' }, + ], +} + +export default { + extends: baseConfig, + srcDir: '.', + title: 'ElasticSearch', + description: 'CakePHP ElasticSearch Documentation', + base: '/elasticsearch/5/', + rewrites: { + 'en/:slug*': ':slug*', + 'ja/:slug*': 'ja/:slug*', + }, + sitemap: { + hostname: 'https://book.cakephp.org/elasticsearch/5/', + }, + themeConfig: { + siteTitle: false, + pluginName: 'ElasticSearch', + socialLinks: [ + { icon: 'github', link: 'https://github.com/cakephp/elastic-search' }, + ], + editLink: { + pattern: 'https://github.com/cakephp/elastic-search/edit/5.x/docs/:path', + text: 'Edit this page on GitHub', + }, + sidebar: tocEn, + nav: [ + { text: 'CakePHP', link: 'https://cakephp.org' }, + { text: 'API', link: 'https://api.cakephp.org/elasticsearch/' }, + { ...versions }, + ], + }, + locales: { + root: { + label: 'English', + lang: 'en', + themeConfig: { + sidebar: tocEn, + }, + }, + ja: { + label: 'Japanese', + lang: 'ja', + link: '/ja/', + themeConfig: { + sidebar: tocJa, + }, + }, + }, +} diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js new file mode 100644 index 00000000..e33e19ec --- /dev/null +++ b/docs/.vitepress/theme/index.js @@ -0,0 +1 @@ +export { default } from '@cakephp/docs-skeleton' diff --git a/docs/.vitepress/toc_en.json b/docs/.vitepress/toc_en.json new file mode 100644 index 00000000..3915b418 --- /dev/null +++ b/docs/.vitepress/toc_en.json @@ -0,0 +1,30 @@ +{ + "/": [ + { + "text": "Getting Started", + "collapsed": false, + "items": [ + { "text": "Installation and Configuration", "link": "/installation" }, + { "text": "Indexes and Documents", "link": "/indexes-and-documents" }, + { "text": "Searching and Saving", "link": "/searching-and-saving" } + ] + }, + { + "text": "Advanced Topics", + "collapsed": false, + "items": [ + { "text": "Embedded Documents", "link": "/embedded-documents" }, + { "text": "Testing", "link": "/testing" } + ] + }, + { + "text": "Migration", + "collapsed": false, + "items": [ + { "text": "5.0 Upgrade Guide", "link": "/5-0-upgrade-guide" }, + { "text": "4.0 Upgrade Guide", "link": "/4-0-upgrade-guide" }, + { "text": "3.0 Upgrade Guide", "link": "/3-0-upgrade-guide" } + ] + } + ] +} diff --git a/docs/.vitepress/toc_ja.json b/docs/.vitepress/toc_ja.json new file mode 100644 index 00000000..323b68d9 --- /dev/null +++ b/docs/.vitepress/toc_ja.json @@ -0,0 +1,11 @@ +{ + "/ja/": [ + { + "text": "ドキュメント", + "collapsed": false, + "items": [ + { "text": "ElasticSearch", "link": "/ja/" } + ] + } + ] +} diff --git a/docs/config/__init__.py b/docs/config/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/config/all.py b/docs/config/all.py deleted file mode 100644 index 7b931124..00000000 --- a/docs/config/all.py +++ /dev/null @@ -1,48 +0,0 @@ -# Global configuration information used across all the -# translations of documentation. -# -# Import the base theme configuration -from cakephpsphinx.config.all import * - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# - -# The full version, including alpha/beta/rc tags. -release = '5.x' - -# The search index version. -search_version = 'elasticsearch-5' - -# The marketing display name for the book. -version_name = '' - -# Project name shown in the black header bar -project = 'CakePHP ElasticSearch' - -# Other versions that display in the version picker menu. -version_list = [ - {'name': '5.x', 'number': '/elasticsearch/5', 'title': '5.x', 'current': True}, - {'name': '4.x', 'number': '/elasticsearch/4', 'title': '4.x'}, - {'name': '3.x', 'number': '/elasticsearch/3', 'title': '3.x'}, - {'name': '2.x', 'number': '/elasticsearch/2', 'title': '2.x'}, -] - -# Languages available. -languages = ['en', 'ja'] - -# The GitHub branch name for this version of the docs -# for edit links to point at. -branch = '5.x' - -# Current version being built -version = '5.x' - -show_root_link = True - -repository = 'cakephp/elastic-search' - -source_path = 'docs/' - -hide_page_contents = ('search', '404', 'contents') diff --git a/docs/en/3-0-upgrade-guide.md b/docs/en/3-0-upgrade-guide.md new file mode 100644 index 00000000..cb58fd2f --- /dev/null +++ b/docs/en/3-0-upgrade-guide.md @@ -0,0 +1,22 @@ +# 3.0 Upgrade Guide + +If you are upgrading from an earlier version of this plugin, this page collects the application changes you may need to make. + +## Types Renamed to Indexes + +Because of Elasticsearch 5 and 6 changes, the plugin no longer supports multiple types in the same index. All of your type classes therefore need to be renamed to indexes. + +For example: + +- `App\Model\Type\ArticlesType` becomes `App\Model\Index\ArticlesIndex` +- `Type` base classes become `Index` base classes + +Index classes assume that the mapping type uses the singularized index name. For example, the `articles` index uses the `article` mapping type. + +## Breaking Changes + +- `Index::entityClass()` was removed. Use `getEntityClass()` or `setEntityClass()` instead. +- `ResultSet::hasFacets()` was removed because Elastica no longer exposes this method. +- `ResultSet::getFacets()` was removed because Elastica no longer exposes this method. +- `Type` is now `Index`. +- `TypeRegistry` is now `IndexRegistry`. diff --git a/docs/en/3-0-upgrade-guide.rst b/docs/en/3-0-upgrade-guide.rst deleted file mode 100644 index 39fa7051..00000000 --- a/docs/en/3-0-upgrade-guide.rst +++ /dev/null @@ -1,31 +0,0 @@ -3.0 Upgrade Guide -################# - -If you are upgrading from an earlier version of this plugin, this page aims to -collect all the changes you may need to make to your application while -upgrading. - -Types Renamed to Indexes -======================== - -Because of the changes made in elasticsearch 5 and 6, this plugin no longer -supports multiple types in the same index. The impact of this is that all of -your type classes need to be renamed to indexes. For example -``App\Model\Type\ArticlesType`` needs to become -``App\Model\Index\ArticlesIndex``. Furthermore, Index classes assume that the -type mapping has the singular name of the index. For example the ``articles`` -index has a type mapping of ``article``. - -Breaking Changes -================ - -* ``Index::entityClass()`` was removed. Use ``getEntityClass()`` or - ``setEntityClass()`` instead. -* ``ResultSet::hasFacets()`` was removed as elastica no longer exposes this - method. -* ``ResultSet::getFacets()`` was removed as elastica no longer exposes this - method. -* ``ResultSet::getFacets()`` was removed as elastica no longer exposes this - method. -* The ``Type`` base class is now ``Index``. -* ``TypeRegistry`` is now ``IndexRegistry``. diff --git a/docs/en/4-0-upgrade-guide.md b/docs/en/4-0-upgrade-guide.md new file mode 100644 index 00000000..b811fc5a --- /dev/null +++ b/docs/en/4-0-upgrade-guide.md @@ -0,0 +1,31 @@ +# 4.0 Upgrade Guide + +::: warning Requirements +CakePHP ElasticSearch `4.x` requires CakePHP `5.x`. +::: + +## Breaking Changes + +- Native PHP types were added where possible. This improves type safety but may expose incompatibilities in application code. +- `Query` no longer uses `Cake\ORM\QueryTrait`, which removed several inherited methods that were never used by this plugin. +- `Query::isEagerLoaded()` and `Query::eagerLoaded()` were removed. + +## Indexes + +`IndexRegistry` was deprecated in `4.x`. + +Old code: + +```php +use Cake\ElasticSearch\IndexRegistry; + +$articles = IndexRegistry::get('Articles'); +``` + +New code: + +```php +use Cake\Datasource\FactoryLocator; + +$articles = FactoryLocator::get('ElasticSearch')->get('Articles'); +``` diff --git a/docs/en/4-0-upgrade-guide.rst b/docs/en/4-0-upgrade-guide.rst deleted file mode 100644 index e8535964..00000000 --- a/docs/en/4-0-upgrade-guide.rst +++ /dev/null @@ -1,35 +0,0 @@ -4.0 Upgrade Guide -################# - -.. warning:: - CakePHP ElasticSearch 4.x requires CakePHP 5.x. - -Breaking Changes -================ - -* All methods have had native types added where possible. This improves type - safety within this plugin but may cause errors with application code. -* ``Query`` no longer uses ``Cake\ORM\QueryTrait``. This has allowed several - unused methods to be removed. -* ``Query::isEagerLoaded()``, and ``Query::eagerLoaded()`` were removed. - Previously these methods were inherited from ``QueryTrait`` but served no - purpose here. - - -Indexes -====== - -IndexRegistry has been deprecated. - -Old code example:: - - use Cake\ElasticSearch\IndexRegistry; - - $articles = IndexRegistry::get('Articles'); - - -New code example:: - - use Cake\Datasource\FactoryLocator; - - $articles = FactoryLocator::get('ElasticSearch')->get('Articles'); diff --git a/docs/en/5-0-upgrade-guide.md b/docs/en/5-0-upgrade-guide.md new file mode 100644 index 00000000..d51a3b8a --- /dev/null +++ b/docs/en/5-0-upgrade-guide.md @@ -0,0 +1,198 @@ +# 5.0 Upgrade Guide + +::: warning Requirements +CakePHP ElasticSearch `5.x` requires CakePHP `5.2+`, Elasticsearch `9.x`, Elastica `9.x`, and PHP `8.1+`. +::: + +## Requirements + +- CakePHP `5.2+` +- Elasticsearch `9.x` +- Elastica `9.x` +- PHP `8.1+` + +## Breaking Changes + +Version `5.x` includes the breaking changes required for Elasticsearch `9.x`, the Elastica `9.x` upgrade, and current CakePHP `5.x` compatibility. + +- Connection configuration now prefers a `hosts` array. +- `IndexRegistry` has been removed after being deprecated since `3.4.3`. +- Several deprecated methods have been removed. +- Elastica API updates require modern client initialization. + +## Configuration Changes + +### Connection Configuration Format + +The recommended datasource format now uses `hosts` instead of separate `host` and `port` keys. + +Legacy configuration format: + +```php +'Datasources' => [ + 'elastic' => [ + 'className' => 'Cake\ElasticSearch\Datasource\Connection', + 'driver' => 'Cake\ElasticSearch\Datasource\Connection', + 'host' => '127.0.0.1', + 'port' => 9200, + ], +] +``` + +Recommended configuration format: + +```php +'Datasources' => [ + 'elastic' => [ + 'className' => 'Cake\ElasticSearch\Datasource\Connection', + 'driver' => 'Cake\ElasticSearch\Datasource\Connection', + 'hosts' => ['127.0.0.1:9200'], + ], +] +``` + +For HTTPS endpoints: + +```php +'hosts' => ['https://127.0.0.1:443'] +``` + +For clusters with multiple nodes: + +```php +'hosts' => [ + '127.0.0.1:9200', + '127.0.0.1:9201', + '127.0.0.1:9202', +] +``` + +## Deprecated Method Removals + +### QueryBuilder Methods + +- `QueryBuilder::and_()` -> `QueryBuilder::and()` +- `QueryBuilder::or_()` -> `QueryBuilder::or()` + +Old code: + +```php +$query->where(function ($builder) { + return $builder->and_( + $builder->gt('views', 99), + $builder->term('author.name', 'sally') + ); +}); +``` + +New code: + +```php +$query->where(function ($builder) { + return $builder->and( + $builder->gt('views', 99), + $builder->term('author.name', 'sally') + ); +}); +``` + +### Embedded Association Methods + +- `Embedded::property()` -> `setProperty()` / `getProperty()` +- `Embedded::entityClass()` -> `setEntityClass()` / `getEntityClass()` +- `Embedded::indexClass()` -> `setIndexClass()` / `getIndexClass()` + +Old code: + +```php +$association->property('comments'); +$class = $association->entityClass(); +$association->entityClass('App\Model\Document\Comment'); +``` + +New code: + +```php +$association->setProperty('comments'); +$class = $association->getEntityClass(); +$association->setEntityClass('App\Model\Document\Comment'); +``` + +### Query Methods + +- `Query::repository()` -> `setRepository()` + +Old code: + +```php +$query->repository($index); +``` + +New code: + +```php +$query->setRepository($index); +``` + +::: tip Ordering +`Query::order()` still exists because it is part of `Cake\Datasource\QueryInterface`, but `orderBy()` is preferred. +::: + +## IndexRegistry Removal + +Use `IndexLocator`, `IndexLocatorAwareTrait`, or `FactoryLocator` instead of `IndexRegistry`. + +Old approach: + +```php +use Cake\ElasticSearch\IndexRegistry; + +$articles = IndexRegistry::get('Articles'); +IndexRegistry::flush(); +``` + +New approach with `IndexLocator`: + +```php +use Cake\ElasticSearch\Datasource\IndexLocator; + +$locator = new IndexLocator(); +$articles = $locator->get('Articles'); +$locator->clear(); +``` + +New approach with `IndexLocatorAwareTrait`: + +```php +use Cake\ElasticSearch\Datasource\IndexLocatorAwareTrait; + +class MyController extends Controller +{ + use IndexLocatorAwareTrait; + + public function index() + { + $articles = $this->fetchIndex('Articles'); + } +} +``` + +Alternative with `FactoryLocator`: + +```php +use Cake\Datasource\FactoryLocator; + +$articles = FactoryLocator::get('ElasticSearch')->get('Articles'); +``` + +## Migration Steps + +1. Update dependencies to `cakephp/elastic-search:^5.0`. +2. Move datasource configuration to the `hosts` array format if you still use `host` and `port`. +3. Replace removed APIs such as `IndexRegistry`, `and_()`, `or_()`, embedded association setters/getters, and `repository()`. +4. Verify your Elasticsearch cluster is running `9.x`. +5. Run your application test suite. + +```bash +vendor/bin/phpunit +``` diff --git a/docs/en/5-0-upgrade-guide.rst b/docs/en/5-0-upgrade-guide.rst deleted file mode 100644 index 4de304d3..00000000 --- a/docs/en/5-0-upgrade-guide.rst +++ /dev/null @@ -1,215 +0,0 @@ -5.0 Upgrade Guide -################# - -.. warning:: - CakePHP ElasticSearch 5.x requires CakePHP 5.2+, ElasticSearch 9.x, and PHP 8.1+. - -Requirements -============ - -* CakePHP 5.2+ -* ElasticSearch 9.x -* Elastica 9.x (via ruflin/elastica) -* PHP 8.1+ - -Breaking Changes -================ - -Version 5.x includes several breaking changes to support ElasticSearch 9.x via -the Elastica 9.x library upgrade, along with compatibility updates for the latest -CakePHP 5.x features. - -* Connection configuration format has changed to use ``hosts`` array. -* ``IndexRegistry`` class has been removed (was deprecated since 3.4.3). -* Several deprecated methods have been removed. -* Elastica API changes require updated client initialization. - -Configuration Changes -===================== - -Connection Configuration Format --------------------------------- - -The recommended configuration format now uses a ``hosts`` array instead -of separate ``host`` and ``port`` keys. This aligns with Elastica 9.x -and provides better support for clustering. - -Legacy configuration format (still supported):: - - // in config/app.php - 'Datasources' => [ - 'elastic' => [ - 'className' => 'Cake\ElasticSearch\Datasource\Connection', - 'driver' => 'Cake\ElasticSearch\Datasource\Connection', - 'host' => '127.0.0.1', - 'port' => 9200, - ], - ] - -New configuration format (recommended):: - - // in config/app.php - 'Datasources' => [ - 'elastic' => [ - 'className' => 'Cake\ElasticSearch\Datasource\Connection', - 'driver' => 'Cake\ElasticSearch\Datasource\Connection', - 'hosts' => ['127.0.0.1:9200'], - ], - ] - -For HTTPS endpoints:: - - 'hosts' => ['https://127.0.0.1:443'] - -Multiple hosts can be specified in the array:: - - 'hosts' => [ - '127.0.0.1:9200', - '127.0.0.1:9201', - '127.0.0.1:9202', - ] - -Deprecated Method Removals -=========================== - -Several deprecated methods have been removed in this version. Update your code -to use the replacement methods. - -QueryBuilder Methods --------------------- - -* ``QueryBuilder::and_()`` → use ``QueryBuilder::and()`` -* ``QueryBuilder::or_()`` → use ``QueryBuilder::or()`` - -The underscore suffix is no longer needed as modern PHP allows these method names. - -Old code:: - - $query->where(function ($builder) { - return $builder->and_( - $builder->gt('views', 99), - $builder->term('author.name', 'sally') - ); - }); - -New code:: - - $query->where(function ($builder) { - return $builder->and( - $builder->gt('views', 99), - $builder->term('author.name', 'sally') - ); - }); - -Embedded Association Methods ------------------------------ - -* ``Embedded::property()`` → use ``setProperty()`` / ``getProperty()`` -* ``Embedded::entityClass()`` → use ``setEntityClass()`` / ``getEntityClass()`` -* ``Embedded::indexClass()`` → use ``setIndexClass()`` / ``getIndexClass()`` - -Old code:: - - $association->property('comments'); - $class = $association->entityClass(); - $association->entityClass('App\Model\Document\Comment'); - -New code:: - - $association->setProperty('comments'); - $class = $association->getEntityClass(); - $association->setEntityClass('App\Model\Document\Comment'); - -Query Methods -------------- - -* ``Query::repository()`` → use ``setRepository()`` - -Old code:: - - $query->repository($index); - -New code:: - - $query->setRepository($index); - -.. note:: - ``Query::order()`` remains available as it's required by the - ``Cake\Datasource\QueryInterface`` contract, but ``orderBy()`` is preferred. - -IndexRegistry Removal -===================== - -The deprecated ``IndexRegistry`` class has been completely removed. Use ``IndexLocator`` -or ``IndexLocatorAwareTrait`` instead. - -Old approach (no longer available):: - - use Cake\ElasticSearch\IndexRegistry; - - $articles = IndexRegistry::get('Articles'); - IndexRegistry::flush(); - -New approach using IndexLocator directly:: - - use Cake\ElasticSearch\Datasource\IndexLocator; - - $locator = new IndexLocator(); - $articles = $locator->get('Articles'); - $locator->clear(); - -New approach using IndexLocatorAwareTrait:: - - use Cake\ElasticSearch\Datasource\IndexLocatorAwareTrait; - - class MyController extends Controller - { - use IndexLocatorAwareTrait; - - public function index() - { - $articles = $this->fetchIndex('Articles'); - } - } - -Alternative using FactoryLocator:: - - use Cake\Datasource\FactoryLocator; - - $articles = FactoryLocator::get('ElasticSearch')->get('Articles'); - -Migration Steps -=============== - -1. **Update Dependencies** - - Update your ``composer.json`` to require version 5.x:: - - composer require cakephp/elastic-search:^5.0 - -2. **Update Configuration (Optional but Recommended)** - - Consider updating your datasource configuration in ``config/app.php`` to use - the ``hosts`` array format for better clustering support. The old ``host`` - and ``port`` format still works for backward compatibility. - -3. **Update Code** - - Search your codebase for the deprecated methods and replace them: - - * Replace ``IndexRegistry`` usage with ``IndexLocator`` or ``IndexLocatorAwareTrait`` - * Replace ``and_()`` with ``and()`` - * Replace ``or_()`` with ``or()`` - * Replace getter/setter methods on embedded associations - * Replace ``repository()`` with ``setRepository()`` - -4. **Test ElasticSearch 9.x Compatibility** - - Ensure your ElasticSearch cluster is running version 9.x and test your - application thoroughly. - -5. **Run Tests** - - Run your test suite to catch any compatibility issues:: - - vendor/bin/phpunit diff --git a/docs/en/conf.py b/docs/en/conf.py deleted file mode 100644 index abf3d8d0..00000000 --- a/docs/en/conf.py +++ /dev/null @@ -1,10 +0,0 @@ -import sys, os - -# Append the top level directory of the docs, so we can import from the config dir. -sys.path.insert(0, os.path.abspath('..')) - -# Pull in all the configuration options defined in the global config file.. -from config.all import * - -# Language in use for this directory. -language = 'en' diff --git a/docs/en/contents.rst b/docs/en/contents.rst deleted file mode 100644 index 763631d7..00000000 --- a/docs/en/contents.rst +++ /dev/null @@ -1,11 +0,0 @@ -Contents -######## - -.. toctree:: - :maxdepth: 2 - :caption: CakePHP ElasticSearch - - /index - /3-0-upgrade-guide - /4-0-upgrade-guide - /5-0-upgrade-guide diff --git a/docs/en/embedded-documents.md b/docs/en/embedded-documents.md new file mode 100644 index 00000000..c654a45b --- /dev/null +++ b/docs/en/embedded-documents.md @@ -0,0 +1,40 @@ +# Embedded Documents + +Embedded documents let you attach custom document classes to nested properties in a parent document. + +For example, if articles contain embedded users and comments, you can define those relationships in the index: + +```php +namespace App\Model\Index; + +use Cake\ElasticSearch\Index; + +class ArticlesIndex extends Index +{ + public function initialize(): void + { + $this->embedOne('User'); + $this->embedMany('Comments', [ + 'entityClass' => 'MyComment', + ]); + } +} +``` + +In this example: + +- `embedOne('User')` maps the `user` property to `App\Model\Document\User`. +- `embedMany('Comments')` maps the `comments` property to an array of document objects. +- `entityClass` lets you use a class name that does not match the property name. + +After configuring embedded documents, `find()` and `get()` hydrate the nested properties into the configured document classes: + +```php +$article = $this->Articles->get($id); + +// Instance of App\Model\Document\User +$article->user; + +// Array of App\Model\Document\Comment instances +$article->comments; +``` diff --git a/docs/en/index.md b/docs/en/index.md new file mode 100644 index 00000000..5c56f874 --- /dev/null +++ b/docs/en/index.md @@ -0,0 +1,14 @@ +# ElasticSearch + +The ElasticSearch plugin provides an ORM-like abstraction for working with [Elasticsearch](https://www.elastic.co/products/elasticsearch) indexes in CakePHP. It helps with indexing, searching, validation, embedded documents, and fixture-backed tests. + +Version `5.x` targets CakePHP `5.2+`, Elasticsearch `9.x`, Elastica `9.x`, and PHP `8.1+`. + +## Documentation Map + +- [Installation and Configuration](/installation) covers package installation, plugin loading, and datasource setup. +- [Indexes and Documents](/indexes-and-documents) explains index classes, document classes, connections, and fetching index instances. +- [Searching and Saving](/searching-and-saving) covers finding, validating, saving, updating, bulk operations, and deleting documents. +- [Embedded Documents](/embedded-documents) explains `embedOne()` and `embedMany()` for nested document objects. +- [Testing](/testing) shows how to load mappings and fixtures for integration tests. +- [3.0 Upgrade Guide](/3-0-upgrade-guide), [4.0 Upgrade Guide](/4-0-upgrade-guide), and [5.0 Upgrade Guide](/5-0-upgrade-guide) describe version-specific migration changes. diff --git a/docs/en/index.rst b/docs/en/index.rst deleted file mode 100644 index 81127792..00000000 --- a/docs/en/index.rst +++ /dev/null @@ -1,423 +0,0 @@ -ElasticSearch -############# - -The ElasticSearch plugin provides an ORM-like abstraction on top of -`elasticsearch `_. The plugin -provides features that make testing, indexing documents and searching your -indexes easier. - -Installation -============ - -To install the ElasticSearch plugin, you can use ``composer``. From your -application's ROOT directory (where ``composer.json`` file is located) run the -following:: - - $ composer require cakephp/elastic-search "^5.0" - -You will need to add the following line to your application's -**src/Application.php** file:: - - $this->addPlugin('Cake/ElasticSearch'); - -Additionally, you will need to configure the 'elastic' datasource connection in -your **config/app.php** file. An example configuration would be:: - - // in config/app.php - 'Datasources' => [ - // other datasources - 'elastic' => [ - 'className' => 'Cake\ElasticSearch\Datasource\Connection', - 'driver' => 'Cake\ElasticSearch\Datasource\Connection', - 'hosts' => ['127.0.0.1:9200'], - 'index' => 'my_apps_index', - ], - ] - -The legacy configuration format with separate ``host`` and ``port`` is still supported:: - - 'elastic' => [ - 'className' => 'Cake\ElasticSearch\Datasource\Connection', - 'driver' => 'Cake\ElasticSearch\Datasource\Connection', - 'host' => '127.0.0.1', - 'port' => 9200, - 'index' => 'my_apps_index', - ] - -If your endpoint requires https, use:: - - 'hosts' => ['https://127.0.0.1:443'] - -.. note:: - The ``hosts`` array format is recommended for new applications and provides - better support for multiple hosts and clustering. - -Overview -======== - -The ElasticSearch plugin makes it easier to interact with an elasticsearch index -and provides an interface similar to the `ORM -`__. To get started you should -create an ``Index`` object. ``Index`` objects are the "Repository" or table-like -class in elasticsearch:: - - // in src/Model/Type/ArticlesIndex.php - namespace App\Model\Index; - - use Cake\ElasticSearch\Index; - - class ArticlesIndex extends Index - { - } - -You can then use your index class in your controllers:: - - public function beforeFilter(Event $event) - { - parent::beforeFilter($event); - // Load the Index using the 'Elastic' provider. - $this->loadModel('Articles', 'Elastic'); - } - - public function add() - { - $article = $this->Articles->newEntity(); - if ($this->request->is('post')) { - $article = $this->Articles->patchEntity($article, $this->request->getData()); - if ($this->Articles->save($article)) { - $this->Flash->success('It saved'); - } - } - $this->set(compact('article')); - } - -We would also need to create a basic view for our indexed articles:: - - // in src/Template/Articles/add.ctp - Form->create($article) ?> - Form->control('title') ?> - Form->control('body') ?> - Form->button('Save') ?> - Form->end() ?> - -You should now be able to submit the form and have a new document added to -elasticsearch. - -Document Objects -================ - -Like the ORM, the Elasticsearch ODM uses ORM-like classes. The -base class you should inherit from is ``Cake\ElasticSearch\Document``. Document -classes are found in the ``Model\Document`` namespace in your application or -plugin:: - - namespace App\Model\Document; - - use Cake\ElasticSearch\Document; - - class Article extends Document - { - } - -Outside of constructor logic that makes Documents work with data from -elasticsearch, the interface and functionality provided by ``Document`` are the -same as those in `Entities -`__ - -Searching Indexed Documents -=========================== - -After you've indexed some documents you will want to search through them. The -ElasticSearch plugin provides a query builder that allows you to build search -queries:: - - $query = $this->Articles->find() - ->where([ - 'title' => 'special', - 'or' => [ - 'tags in' => ['cake', 'php'], - 'tags not in' => ['c#', 'java'] - ] - ]); - - foreach ($query as $article) { - echo $article->title; - } - -You can use the ``QueryBuilder`` to add filtering conditions:: - - $query->where(function ($builder) { - return $builder->and( - $builder->gt('views', 99), - $builder->term('author.name', 'sally') - ); - }); - -The `QueryBuilder source -`_ -has the complete list of methods with examples for many commonly used methods. - -Validating Data & Using Application Rules -========================================= - -Like the ORM, the ElasticSearch plugin lets you validate data when marshalling -documents. Validating request data, and applying application rules works the -same as it does with the relational ORM. See the `validating request data -`__ -and `Application Rules -`__ -sections for more information. - -.. Need information on nested validators. - -Saving New Documents -==================== - -When you're ready to index some data into elasticsearch, you'll first need to -convert your data into a ``Document`` that can be indexed:: - - $article = $this->Articles->newEntity($data); - if ($this->Articles->save($article)) { - // Document was indexed - } - -When marshalling a document, you can specify which embedded documents you wish -to marshall using the ``associated`` key:: - - $article = $this->Articles->newEntity($data, ['associated' => ['Comments']]); - -Saving a document will trigger the following events: - -* ``Model.beforeSave`` - Fired before the document is saved. You can prevent the - save operation from happening by stopping this event. -* ``Model.buildRules`` - Fired when the rules checker is built for the first - time. -* ``Model.afterSave`` - Fired after the document is saved. - -.. note:: - There are no events for embedded documents, as the parent document and all - of its embedded documents are saved as one operation. - -Updating Existing Documents -=========================== - -When you need to re-index data, you can patch existing entities and re-save -them:: - - $query = $this->Articles->find()->where(['user.name' => 'jill']); - foreach ($query as $doc) { - $doc->set($newProperties); - $this->Articles->save($doc); - } - -Additionally Elasticsearch ``refresh`` request can be triggered by passing -``'refresh' => true`` in the ``$options`` argument. A refresh makes recent -operations performed on one or more indices available for search:: - - $this->Articles->save($article, ['refresh' => true]); - -Saving Multiple Documents -========================= - -Using this method you can bulk save multiple documents:: - - $result = $this->Articles->saveMany($documents); - -Here ``$documents`` is an array of documents. The result will be ``true`` on success or ``false`` on failure. -``saveMany`` can have second argument with the same options as accepted by ``save()``. - - -Deleting Documents -================== - -After retrieving a document you can delete it:: - - $doc = $this->Articles->get($id); - $this->Articles->delete($doc); - -You can also delete documents matching specific conditions:: - - $this->Articles->deleteAll(['user.name' => 'bob']); - -Embedding Documents -=================== - -By defining embedded documents, you can attach entity classes to specific -property paths in your documents. This allows you to provide custom behavior to -the documents within a parent document. For example, you may want the comments -embedded in an article to have specific application specific methods. You can -use ``embedOne`` and ``embedMany`` to define embedded documents:: - - // in src/Model/Index/ArticlesIndex.php - namespace App\Model\Index; - - use Cake\ElasticSearch\Index; - - class ArticlesIndex extends Index - { - public function initialize() - { - $this->embedOne('User'); - $this->embedMany('Comments', [ - 'entityClass' => 'MyComment' - ]); - } - } - -The above would create two embedded documents on the ``Article`` document. The -``User`` embed will convert the ``user`` property to instances of -``App\Model\Document\User``. To get the Comments embed to use a class name -that does not match the property name, we can use the ``entityClass`` option to -configure a custom class name. - -Once we've setup our embedded documents, the results of ``find()`` and ``get()`` -will return objects with the correct embedded document classes:: - - $article = $this->Articles->get($id); - // Instance of App\Model\Document\User - $article->user; - - // Array of App\Model\Document\Comment instances - $article->comments; - -Configuring Connections -======================= - -By default all index instances use the ``elastic`` connection. If your -application uses multiple connections you will want to configure which -index use which connections. This is the ``defaultConnectionName()`` method:: - - namespace App\Model\Index; - - use Cake\ElasticSearch\Index; - - class ArticlesIndex extends Index - { - public static function defaultConnectionName() { - return 'replica_db'; - } - } - -.. note:: - - The ``defaultConnectionName()`` method **must** be static. - -Getting Index Instances -======================= - -Like the ORM, the ElasticSearch plugin provides a locator for getting -``Index`` instances:: - - use Cake\ElasticSearch\Datasource\IndexLocator; - - $locator = new IndexLocator(); - $articles = $locator->get('Articles'); - -Using IndexLocatorAwareTrait ------------------------------ - -For convenient access to the index locator, you can use the ``IndexLocatorAwareTrait`` -in your classes:: - - use Cake\ElasticSearch\Datasource\IndexLocatorAwareTrait; - - class MyController extends Controller - { - use IndexLocatorAwareTrait; - - public function index() - { - $articles = $this->fetchIndex('Articles'); - } - } - -Flushing the Locator ---------------------- - -During test cases you may want to flush the locator. Doing so is often useful -when you are using mock objects, or modifying an index's dependencies:: - - $locator->clear(); - -Test Fixtures -============= - -The ElasticSearch plugin provides a seamless test suite integration. Just like -database fixtures, you can create test schema and fixture data elasticsearch. -Much like database fixtures we load our Elasticsearch mappings during -``tests/bootstrap.php`` of our application:: - - // In tests/bootstrap.php - use Cake\Elasticsearch\TestSuite\Fixture\MappingGenerator; - - $generator = new MappingGenerator('tests/mappings.php', 'test_elastic'); - $generator->reload(); - -The above will create the indexes and mappings defined in ``tests/mapping.php`` -and insert them into the ``test_elastic`` connection. The mappings in your -``mappings.php`` should return a list of mappings to create:: - - // in tests/mappings.php - return [ - [ - // The name of the index and mapping. - 'name' => 'articles', - // The schema for the mapping. - 'mapping' => [ - 'id' => ['type' => 'integer'], - 'title' => ['type' => 'text'], - 'user_id' => ['type' => 'integer'], - 'body' => ['type' => 'text'], - 'created' => ['type' => 'date'], - ], - // Additional index settings. - 'settings' => [ - 'number_of_shards' => 2, - 'number_of_routing_shards' => 2, - ], - ], - // ... - ]; - -Mappings use the `native elasticsearch mapping format -`_. -You can safely omit the type name and top level ``properties`` key. With our -mappings loaded, we can define a test fixture for our Articles index with the -following:: - - namespace App\Test\Fixture; - - use Cake\ElasticSearch\TestSuite\TestFixture; - - /** - * Articles fixture - */ - class ArticlesFixture extends TestFixture - { - /** - * The table/index for this fixture. - * - * @var string - */ - public $table = 'articles'; - - public $records = [ - [ - 'user' => [ - 'username' => 'billy' - ], - 'title' => 'First Post', - 'body' => 'Some content' - ] - ]; - } - -.. versionchanged:: 3.4.0 - Prior to CakePHP 4.3.0 schema was defined on each fixture in the ``$schema`` - property. - - -Once your fixtures are created you can use them in your test cases by including -them in your test's ``fixtures`` properties:: - - public $fixtures = ['app.Articles']; diff --git a/docs/en/indexes-and-documents.md b/docs/en/indexes-and-documents.md new file mode 100644 index 00000000..a99ea56e --- /dev/null +++ b/docs/en/indexes-and-documents.md @@ -0,0 +1,106 @@ +# Indexes and Documents + +The ElasticSearch plugin uses repository-style `Index` classes and ORM-like `Document` classes. + +## Creating an Index Class + +Create an index class in your application's `Model/Index` namespace: + +```php +namespace App\Model\Index; + +use Cake\ElasticSearch\Index; + +class ArticlesIndex extends Index +{ +} +``` + +`Index` objects are similar to `ORM\Table` instances. Each index class maps to an Elasticsearch index, and by default the plugin infers the index name from the class name. + +If you need to define the Elasticsearch index name explicitly, override `getName()`: + +```php +namespace App\Model\Index; + +use Cake\ElasticSearch\Index; + +class CommentsIndex extends Index +{ + public function getName(): string + { + return 'comments'; + } +} +``` + +## Creating a Document Class + +Document classes belong in `Model/Document`: + +```php +namespace App\Model\Document; + +use Cake\ElasticSearch\Document; + +class Article extends Document +{ +} +``` + +Aside from constructor logic needed to hydrate Elasticsearch data, `Document` behaves like a CakePHP entity. The entity documentation for CakePHP is therefore a good reference for getters, setters, hidden fields, virtual fields, and mass-assignment rules. + +## Fetching Index Instances + +Use `IndexLocatorAwareTrait` when you want convenient access in controllers, commands, and services: + +```php +use Cake\ElasticSearch\Datasource\IndexLocatorAwareTrait; + +class MyController extends Controller +{ + use IndexLocatorAwareTrait; + + public function index() + { + $articles = $this->fetchIndex('Articles'); + } +} +``` + +You can also work with `IndexLocator` directly: + +```php +use Cake\ElasticSearch\Datasource\IndexLocator; + +$locator = new IndexLocator(); +$articles = $locator->get('Articles'); +``` + +Clear the locator during tests when you need fresh instances or mocked dependencies: + +```php +$locator->clear(); +``` + +## Configuring the Connection Per Index + +All indexes use the `elastic` connection by default. Override `defaultConnectionName()` if an index should use a different datasource: + +```php +namespace App\Model\Index; + +use Cake\ElasticSearch\Index; + +class ArticlesIndex extends Index +{ + public static function defaultConnectionName(): string + { + return 'replica_db'; + } +} +``` + +::: warning Static method required +`defaultConnectionName()` must be declared `static`. +::: diff --git a/docs/en/installation.md b/docs/en/installation.md new file mode 100644 index 00000000..55ec6afe --- /dev/null +++ b/docs/en/installation.md @@ -0,0 +1,92 @@ +# Installation and Configuration + +Install the plugin with Composer from your application's root directory: + +```bash +composer require cakephp/elastic-search:^5.0 +``` + +Load the plugin in your application bootstrap: + +```php +use Cake\ElasticSearch\Plugin as ElasticSearchPlugin; + +class Application extends BaseApplication +{ + public function bootstrap(): void + { + parent::bootstrap(); + $this->addPlugin(ElasticSearchPlugin::class); + + // To disable the automatic model provider and FormHelper wiring: + // $this->addPlugin(ElasticSearchPlugin::class, ['bootstrap' => false]); + } +} +``` + +## Datasource Configuration + +Configure an `elastic` datasource in `config/app.php`: + +```php +// in config/app.php +'Datasources' => [ + // other datasources + 'elastic' => [ + 'className' => 'Cake\ElasticSearch\Datasource\Connection', + 'driver' => 'Cake\ElasticSearch\Datasource\Connection', + 'hosts' => ['127.0.0.1:9200'], + 'index' => 'my_apps_index', + ], +] +``` + +The legacy `host` and `port` keys are still supported: + +```php +'elastic' => [ + 'className' => 'Cake\ElasticSearch\Datasource\Connection', + 'driver' => 'Cake\ElasticSearch\Datasource\Connection', + 'host' => '127.0.0.1', + 'port' => 9200, + 'index' => 'my_apps_index', +] +``` + +For HTTPS endpoints, use full URLs in the `hosts` array: + +```php +'hosts' => ['https://127.0.0.1:443'] +``` + +For multi-node clusters, provide multiple hosts: + +```php +'hosts' => [ + '127.0.0.1:9200', + '127.0.0.1:9201', + '127.0.0.1:9202', +] +``` + +You can also configure the connection with a URL, which is useful when values come from environment variables: + +```php +'Datasources' => [ + 'elastic' => [ + 'url' => env('ELASTIC_URL', null), + ], +] +``` + +```text +ELASTIC_URL="Cake\ElasticSearch\Datasource\Connection://127.0.0.1:9200?driver=Cake\ElasticSearch\Datasource\Connection" +``` + +::: tip Recommended format +The `hosts` array is the recommended format for new applications because it aligns with Elastica `9.x` and works better with multiple hosts. +::: + +## Query Logging + +Enable request logging by setting `log` to `true` on the datasource configuration. By default the `debug` log profile is used. You can define an `elasticsearch` log profile in `Cake\Log\Log` if you want query logs written elsewhere. diff --git a/docs/en/searching-and-saving.md b/docs/en/searching-and-saving.md new file mode 100644 index 00000000..aad9609e --- /dev/null +++ b/docs/en/searching-and-saving.md @@ -0,0 +1,111 @@ +# Searching and Saving + +Once you have an index class, you can build queries, validate data, and persist documents through it. + +## Searching Indexed Documents + +Use `find()` to create a query: + +```php +$query = $this->Articles->find() + ->where([ + 'title' => 'special', + 'or' => [ + 'tags in' => ['cake', 'php'], + 'tags not in' => ['c#', 'java'], + ], + ]); + +foreach ($query as $article) { + echo $article->title; +} +``` + +Use the query builder callback for more expressive conditions: + +```php +$query->where(function ($builder) { + return $builder->and( + $builder->gt('views', 99), + $builder->term('author.name', 'sally') + ); +}); +``` + +Refer to the `QueryBuilder` API for the full set of supported methods. + +## Validating and Applying Rules + +Validation and application rules work the same way they do in the relational ORM. Validation runs during marshalling, and rule checks run before a document is persisted. + +## Saving New Documents + +Create and save new documents with `newEntity()` and `save()`: + +```php +$article = $this->Articles->newEntity($data); +if ($this->Articles->save($article)) { + // Document was indexed +} +``` + +To marshal embedded documents, pass the `associated` option: + +```php +$article = $this->Articles->newEntity($data, [ + 'associated' => ['Comments'], +]); +``` + +Saving a document triggers these events: + +- `Model.beforeSave` fires before the document is saved. Stop this event to prevent the save. +- `Model.buildRules` fires when the rules checker is built for the first time. +- `Model.afterSave` fires after the document is saved. + +::: info Embedded documents +Embedded documents do not emit their own save events because the parent document and its embedded records are persisted as one operation. +::: + +## Updating Existing Documents + +Patch or modify documents and save them again: + +```php +$query = $this->Articles->find()->where(['user.name' => 'jill']); +foreach ($query as $doc) { + $doc->set($newProperties); + $this->Articles->save($doc); +} +``` + +Pass `refresh => true` if you need Elasticsearch to refresh the index after a write: + +```php +$this->Articles->save($article, ['refresh' => true]); +``` + +## Saving Multiple Documents + +Use `saveMany()` to bulk save documents: + +```php +$result = $this->Articles->saveMany($documents); +``` + +`$documents` must be an array of document objects. `saveMany()` returns `true` on success or `false` on failure, and it accepts the same options as `save()`. + +## Deleting Documents + +Delete a single document after retrieving it: + +```php +$doc = $this->Articles->get($id); +$this->Articles->delete($doc); +``` + +Delete matching documents in bulk with `deleteAll()`: + +```php +$this->Articles->deleteAll(['user.name' => 'bob']); +``` diff --git a/docs/en/testing.md b/docs/en/testing.md new file mode 100644 index 00000000..19a4bb08 --- /dev/null +++ b/docs/en/testing.md @@ -0,0 +1,74 @@ +# Testing + +The ElasticSearch plugin includes test fixture support for loading mappings and records into a dedicated test connection. + +## Loading Mappings + +Generate and reload test mappings in `tests/bootstrap.php`: + +```php +use Cake\ElasticSearch\TestSuite\Fixture\MappingGenerator; + +$generator = new MappingGenerator('tests/mappings.php', 'test_elastic'); +$generator->reload(); +``` + +This creates the indexes and mappings defined in `tests/mappings.php` on the `test_elastic` connection. + +Your mappings file should return an array of mappings: + +```php +return [ + [ + 'name' => 'articles', + 'mapping' => [ + 'id' => ['type' => 'integer'], + 'title' => ['type' => 'text'], + 'user_id' => ['type' => 'integer'], + 'body' => ['type' => 'text'], + 'created' => ['type' => 'date'], + ], + 'settings' => [ + 'number_of_shards' => 2, + 'number_of_routing_shards' => 2, + ], + ], +]; +``` + +Mappings use the native Elasticsearch mapping format. You can omit the type name and the top-level `properties` key. + +## Defining Fixtures + +Create fixtures by extending `Cake\ElasticSearch\TestSuite\TestFixture`: + +```php +namespace App\Test\Fixture; + +use Cake\ElasticSearch\TestSuite\TestFixture; + +class ArticlesFixture extends TestFixture +{ + public string $table = 'articles'; + + public array $records = [ + [ + 'user' => [ + 'username' => 'billy', + ], + 'title' => 'First Post', + 'body' => 'Some content', + ], + ]; +} +``` + +Use those fixtures in your test case as usual: + +```php +public array $fixtures = ['app.Articles']; +``` + +::: info Schema handling +Before plugin `3.4.0`, schema was typically defined on each fixture using the `$schema` property. Current versions load mappings separately through `MappingGenerator`. +::: diff --git a/docs/ja/conf.py b/docs/ja/conf.py deleted file mode 100644 index 57004407..00000000 --- a/docs/ja/conf.py +++ /dev/null @@ -1,10 +0,0 @@ -import sys, os - -# Append the top level directory of the docs, so we can import from the config dir. -sys.path.insert(0, os.path.abspath('..')) - -# Pull in all the configuration options defined in the global config file.. -from config.all import * - -# Language in use for this directory. -language = 'ja' diff --git a/docs/ja/contents.rst b/docs/ja/contents.rst deleted file mode 100644 index 59461d1f..00000000 --- a/docs/ja/contents.rst +++ /dev/null @@ -1,8 +0,0 @@ -Contents -######## - -.. toctree:: - :maxdepth: 2 - :caption: CakePHP ElasticSearch - - /index diff --git a/docs/ja/index.md b/docs/ja/index.md new file mode 100644 index 00000000..b1fae161 --- /dev/null +++ b/docs/ja/index.md @@ -0,0 +1,224 @@ +# ElasticSearch + +ElasticSearch プラグインは、[Elasticsearch](https://www.elastic.co/products/elasticsearch) の上に ORM のような抽象化を提供します。テストの作成、ドキュメントのインデックス作成、インデックスの検索を CakePHP から扱いやすくします。 + +## インストール + +アプリケーションのルートディレクトリーで Composer を使ってインストールします。 + +```bash +composer require cakephp/elastic-search:^5.0 +``` + +`src/Application.php` でプラグインを読み込みます。 + +```php +use Cake\ElasticSearch\Plugin as ElasticSearchPlugin; + +class Application extends BaseApplication +{ + public function bootstrap(): void + { + parent::bootstrap(); + $this->addPlugin(ElasticSearchPlugin::class); + } +} +``` + +`config/app.php` に `elastic` データソースを追加します。 + +```php +'Datasources' => [ + 'elastic' => [ + 'className' => 'Cake\ElasticSearch\Datasource\Connection', + 'driver' => 'Cake\ElasticSearch\Datasource\Connection', + 'hosts' => ['127.0.0.1:9200'], + 'index' => 'my_apps_index', + ], +] +``` + +以前の `host` と `port` を使う形式も引き続き利用できます。 + +## 概要 + +ElasticSearch プラグインは Elasticsearch のインデックスを CakePHP ORM に近い感覚で扱えるようにします。まず `Index` クラスを作成します。 + +```php +namespace App\Model\Index; + +use Cake\ElasticSearch\Index; + +class ArticlesIndex extends Index +{ +} +``` + +次に `Document` クラスを作成します。 + +```php +namespace App\Model\Document; + +use Cake\ElasticSearch\Document; + +class Article extends Document +{ +} +``` + +## インデックス付きドキュメントの検索 + +`find()` と `where()` で検索クエリーを構築できます。 + +```php +$query = $this->Articles->find() + ->where([ + 'title' => 'special', + 'or' => [ + 'tags in' => ['cake', 'php'], + 'tags not in' => ['c#', 'java'], + ], + ]); + +foreach ($query as $article) { + echo $article->title; +} +``` + +`QueryBuilder` を使えばより細かい条件も組み立てられます。 + +```php +$query->where(function ($builder) { + return $builder->and( + $builder->gt('views', 99), + $builder->term('author.name', 'sally') + ); +}); +``` + +## 新しいドキュメントの保存 + +```php +$article = $this->Articles->newEntity($data); +if ($this->Articles->save($article)) { + // Document はインデックスされました +} +``` + +埋め込みドキュメントをマーシャリングする場合は `associated` を指定します。 + +```php +$article = $this->Articles->newEntity($data, [ + 'associated' => ['Comments'], +]); +``` + +保存時には以下のイベントが発生します。 + +- `Model.beforeSave` +- `Model.buildRules` +- `Model.afterSave` + +## 既存ドキュメントの更新と削除 + +```php +$query = $this->Articles->find()->where(['user.name' => 'jill']); +foreach ($query as $doc) { + $doc->set($newProperties); + $this->Articles->save($doc); +} +``` + +```php +$doc = $this->Articles->get($id); +$this->Articles->delete($doc); +``` + +条件に一致するドキュメントをまとめて削除することもできます。 + +```php +$this->Articles->deleteAll(['user.name' => 'bob']); +``` + +## 埋め込みドキュメント + +`embedOne()` と `embedMany()` を使うと、ネストしたプロパティーに独自のドキュメントクラスを割り当てられます。 + +```php +namespace App\Model\Index; + +use Cake\ElasticSearch\Index; + +class ArticlesIndex extends Index +{ + public function initialize(): void + { + $this->embedOne('User'); + $this->embedMany('Comments', [ + 'entityClass' => 'MyComment', + ]); + } +} +``` + +`find()` や `get()` の結果は、設定した埋め込みドキュメントクラスに変換されます。 + +## インデックスインスタンスの取得 + +`IndexLocatorAwareTrait` を使うとインデックスを簡単に取得できます。 + +```php +use Cake\ElasticSearch\Datasource\IndexLocatorAwareTrait; + +class MyController extends Controller +{ + use IndexLocatorAwareTrait; + + public function index() + { + $articles = $this->fetchIndex('Articles'); + } +} +``` + +または `IndexLocator` を直接使えます。 + +```php +use Cake\ElasticSearch\Datasource\IndexLocator; + +$locator = new IndexLocator(); +$articles = $locator->get('Articles'); +$locator->clear(); +``` + +## テストフィクスチャー + +`MappingGenerator` を使ってテスト用のマッピングを読み込めます。 + +```php +use Cake\ElasticSearch\TestSuite\Fixture\MappingGenerator; + +$generator = new MappingGenerator('tests/mappings.php', 'test_elastic'); +$generator->reload(); +``` + +フィクスチャーは `Cake\ElasticSearch\TestSuite\TestFixture` を継承して作成します。 + +```php +namespace App\Test\Fixture; + +use Cake\ElasticSearch\TestSuite\TestFixture; + +class ArticlesFixture extends TestFixture +{ + public string $table = 'articles'; + + public array $records = [ + [ + 'user' => ['username' => 'billy'], + 'title' => 'First Post', + 'body' => 'Some content', + ], + ]; +} +``` diff --git a/docs/ja/index.rst b/docs/ja/index.rst deleted file mode 100644 index 4ed0b6c1..00000000 --- a/docs/ja/index.rst +++ /dev/null @@ -1,314 +0,0 @@ -ElasticSearch -############# - -ElasticSearch プラグインは、`elasticsearch `_ -の上に ORM のような抽象化を提供します。そのプラグインは、テストの作成、 -ドキュメントのインデックス作成、インデックスをより簡単に検索などの機能を提供します。 - -インストール -============ - -ElasticSearch プラグインをインストールするには、 ``composer`` が利用できます。(composer.json -ファイルが置かれている) アプリケーションの ROOT ディレクトリーから次のコマンドを実行します。 :: - - php composer.phar require cakephp/elastic-search "@stable" - -以下の1行をあなたのアプリケーションの **src/Application.php** ファイルに追加する必要があります。 :: - - $this->addPlugin('Cake/ElasticSearch', ['bootstrap' => true]); - - // 3.6.0 より前は、Plugin::load() を使用する必要があります - -追加で 'elastic' のデータソースの接続を **config/app.php** ファイルに設定する必要があります。 -設定例は以下のようになります。 :: - - // config/app.php の中で - 'Datasources' => [ - // 他のデータソース - 'elastic' => [ - 'className' => 'Cake\ElasticSearch\Datasource\Connection', - 'driver' => 'Cake\ElasticSearch\Datasource\Connection', - 'host' => '127.0.0.1', - 'port' => 9200, - 'index' => 'my_apps_index', - ], - ] - -概要 -==== - -ElasticSearch プラグインは elasticsearch インデックスと作用することを簡単にし、 -`ORM `__ に似たインターフェイスを提供します。まず最初に ``Type`` オブジェクトを -作成しなければいけません。 ``Type`` オブジェクトは elasticsearch 内では "Repository" -もしくは Table のようなクラスです。 :: - - // src/Model/Type/ArticlesType.php の中で - namespace App\Model\Type; - - use Cake\ElasticSearch\Type; - - class ArticlesType extends Type - { - } - -コントローラーで Type クラスを利用できます。 :: - - public function beforeFilter(Event $event) - { - parent::beforeFilter($event); - // 'Elastic' プロバイダーを利用して Type を読み込む - $this->loadModel('Articles', 'Elastic'); - } - - public function add() - { - $article = $this->Articles->newEntity(); - if ($this->request->is('post')) { - $article = $this->Articles->patchEntity($article, $this->request->getData()); - if ($this->Articles->save($article)) { - $this->Flash->success('It saved'); - } - } - $this->set(compact('article')); - } - -インデックスされた articles の基本的なビューを作成する必要があります。 :: - - // src/Template/Articles/add.ctp の中で - Form->create($article) ?> - Form->control('title') ?> - Form->control('body') ?> - Form->button('Save') ?> - Form->end() ?> - -これで、フォームの送信が可能になり、新しいドキュメントが elasticsearch に追加されました。 - -Document オブジェクト -===================== - -ORM と同様に、Elasticsearch ODM は `エンティティー `__ のようなクラスを使用しています。 -継承しなければならない基底クラスは ``Cake\ElasticSearch\Document`` です。 -Document クラスは、アプリケーションやプラグイン内の ``Model\Document`` 名前空間に配置します。 :: - - namespace App\Model\Document; - - use Cake\ElasticSearch\Document; - - class Article extends Document - { - } - -elasticsearch からのデータで Document を動作させるコンストラクターロジックの外側、 -インターフェイスと ``Document`` によって提供される機能は、 `Entities -`__ -内にあるものと同じです。 - -インデックス付きドキュメントの検索 -================================== - -いくつかのドキュメントをインデックスに登録した後、あなたはそれらを検索したいと思うでしょう。 -ElasticSearch プラグインを使用すると、検索クエリーを構築するためのクエリービルダーを提供します。 :: - - $query = $this->Articles->find() - ->where([ - 'title' => 'special', - 'or' => [ - 'tags in' => ['cake', 'php'], - 'tags not in' => ['c#', 'java'] - ] - ]); - - foreach ($query as $article) { - echo $article->title; - } - -フィルタリング条件を追加するために ``QueryBuilder`` を使用することができます。 :: - - $query->where(function ($builder) { - return $builder->and( - $builder->gt('views', 99), - $builder->term('author.name', 'sally') - ); - }); - -`QueryBuilder のソース -`_ -は、多くの一般的に使用されるメソッドの例となるメソッドの完全なリストを持っています。 - -データのバリデーションとアプリケーションルールの使用 -==================================================== - -ORMと同様に、ElasticSearch プラグインは、ドキュメントをマーシャリングするときに -データを検証することができます。リクエストデータのバリデート、およびアプリケーションルールの -適用は、リレーショナルORMと同じ動作をします。詳細については、 `エンティティー構築前のデータ検証 `__ と -`条件付き/動的なエラーメッセージ `__ のセクションをご覧ください。 - -.. ネストされたバリデータに関する情報を必要としています。 - -新しいドキュメントの保存 -======================== - -elasticsearch にいくつかのデータをインデックスする準備ができたら、最初にインデックスが付けられる -``Document`` にデータを変換する必要があります。 :: - - $article = $this->Articles->newEntity($data); - if ($this->Articles->save($article)) { - // Document はインデックスされました - } - -ドキュメントをマーシャリングするとき、 ``associated`` キーを使用してマーシャリングしたい -埋め込みドキュメントを指定することができます。 :: - - $article = $this->Articles->newEntity($data, ['associated' => ['Comments']]); - -ドキュメントを保存すると、次のイベントがトリガーされます: - -* ``Model.beforeSave`` - ドキュメントが保存される前に発生します。 - このイベントを停止することによって保存操作を防ぐことができます。 -* ``Model.buildRules`` - ルールチェッカーが最初に構築されているときに発生します。 -* ``Model.afterSave`` - ドキュメントが保存された後に発生します。 - -.. note:: - 親ドキュメントとすべての埋め込みドキュメントを1つの操作で保存するため、 - 埋め込みドキュメントのためのイベントはありません。 - -既存ドキュメントの更新 -====================== - -データの再インデックスが必要な場合、既存のエンティティーにパッチを適用すると再保存できます。 :: - - $query = $this->Articles->find()->where(['user.name' => 'jill']); - foreach ($query as $doc) { - $doc->set($newProperties); - $this->Articles->save($doc); - } - -ドキュメントの削除 -================== - -ドキュメントを検索した後、それを削除することができます。 :: - - $doc = $this->Articles->get($id); - $this->Articles->delete($doc); - -また、特定の条件に一致するドキュメントを削除することができます。 :: - - $this->Articles->deleteAll(['user.name' => 'bob']); - -埋め込みドキュメント -==================== - -埋め込みドキュメントを定義することで、ドキュメント内の特定のプロパティーのパスに -エンティティークラスを添付することができます。これは、親ドキュメント内のドキュメントに -独自の振る舞いを提供することができます。たとえば、あなたが記事に埋め込まれたコメントは、 -特定のアプリケーション固有のメソッドを持っている場合があります。あなたが埋め込みドキュメントを -定義するために ``embedOne`` と ``embedMany`` を使用することができます。 :: - - // in src/Model/Type/ArticlesType.php - namespace App\Model\Type; - - use Cake\ElasticSearch\Type; - - class ArticlesType extends Type - { - public function initialize() - { - $this->embedOne('User'); - $this->embedMany('Comments', [ - 'entityClass' => 'MyComment' - ]); - } - } - -上記の ``Article`` ドキュメント上の2つの埋め込みドキュメントを作成します。 -``User`` 埋め込みは ``App\Model\Document\User`` のインスタンスに ``user`` プロパティーを変換します。 -プロパティー名と一致していないクラス名を使用する埋め込みコメントを得るためには、カスタムクラス名を -設定するための ``entityClass`` オプションを使用することができます。 - -埋め込みドキュメントをセットアップしたら、 ``find()`` と ``get`` の結果は -正しい埋め込みドキュメントクラスのオブジェクトを返します。 :: - - $article = $this->Articles->get($id); - // App\Model\Document\User のインスタンス - $article->user; - - // App\Model\Document\Comment インスタンスの配列 - $article->comments; - -Type インスタンスの取得 -======================= - -ORM と同様に、ElasticSearch プラグインは ``Type`` のインスタンスを取得するための -ファクトリー/レジストリーを提供します。 :: - - use Cake\ElasticSearch\TypeRegistry; - - $articles = TypeRegistry::get('Articles'); - -レジストリーのフラッシュ ------------------------- - -テストケースの中で、レジストリーをフラッシュすることができます。 -そうすることでモックオブジェクトを使用したり、Type の依存関係を変更する際に便利です。 :: - - TypeRegistry::flush(); - -テストフィクスチャー -==================== - -ElasticSearch プラグインは、シームレスなテストスイートの統合を提供します。ちょうどデータベースの -フィクスチャーのように、elasticsearch のためのテストフィクスチャーを作成することができます。 -次のように Articles タイプのテストフィクスチャーを定義することができます。 :: - - namespace App\Test\Fixture; - - use Cake\ElasticSearch\TestSuite\TestFixture; - - /** - * Articles fixture - */ - class ArticlesFixture extends TestFixture - { - /** - * The table/type for this fixture. - * - * @var string - */ - public $table = 'articles'; - - /** - * The mapping data. - * - * @var array - */ - public $schema = [ - 'id' => ['type' => 'integer'], - 'user' => [ - 'type' => 'nested', - 'properties' => [ - 'username' => ['type' => 'string'], - ] - ], - 'title' => ['type' => 'string'], - 'body' => ['type' => 'string'], - ]; - - public $records = [ - [ - 'user' => [ - 'username' => 'billy' - ], - 'title' => 'First Post', - 'body' => 'Some content' - ] - ]; - } - -``schema`` プロパティーは `ネイティブ elasticsearch マッピングフォーマット -`_ を使用します。 -安全にタイプ名およびトップレベルの ``properties`` キーを省略することができます。 -フィクスチャーが作成されたら、あなたのテストの ``fixtures`` プロパティーに含めることによって、 -あなたのテストケースで使用することができます。 :: - - public $fixtures = ['app.Articles']; - diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 00000000..7a760b05 --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,2104 @@ +{ + "name": "docs", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "docs", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@cakephp/docs-skeleton": "git+ssh://git@github.com:cakephp/docs-skeleton.git#node-package", + "vitepress": "^2.0.0-alpha.16" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cakephp/docs-skeleton": { + "version": "1.0.0", + "resolved": "git+ssh://git@github.com/cakephp/docs-skeleton.git#9501c6d47a80645604fceb31328368eeb6a21bc6", + "bin": { + "cakedocs": "bin/cakedocs.js" + }, + "peerDependencies": { + "vitepress": "^2.0.0-alpha.15" + } + }, + "node_modules/@docsearch/css": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.2.tgz", + "integrity": "sha512-fH/cn8BjEEdM2nJdjNMHIvOVYupG6AIDtFVDgIZrNzdCSj4KXr9kd+hsehqsNGYjpUjObeKYKvgy/IwCb1jZYQ==", + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-4.6.2.tgz", + "integrity": "sha512-qj1yoxl3y4GKoK7+VM6fq/rQqPnvUmg3IKzJ9x0VzN14QVzdB/SG/J6VfV1BWT5RcPUFxIcVwoY1fwHM2fSRRw==", + "license": "MIT" + }, + "node_modules/@docsearch/sidepanel-js": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@docsearch/sidepanel-js/-/sidepanel-js-4.6.2.tgz", + "integrity": "sha512-Pni85AP/GwRj7fFg8cBJp0U04tzbueBvWSd3gysgnOsVnQVSZwSYncfErUScLE1CAtR+qocPDFjmYR9AMRNJtQ==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.76", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.76.tgz", + "integrity": "sha512-lLRlA8yaf+1L5VCPRvR9lynoSklsddKHEylchmZJKdj/q2xVQ1ZAEJ8SCQlv9cbgtMefnlyM98U+8Si2aoFZPA==", + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.2", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz", + "integrity": "sha512-izyXV/v+cHiRfozX62W9htOAvwMo4/bXKDrQ+vom1L1qRuexPock/7VZDAhnpHCLNejd3NJ6hiab+tO0D44Rgw==", + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.23.0.tgz", + "integrity": "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.23.0.tgz", + "integrity": "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.4" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.23.0.tgz", + "integrity": "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.23.0.tgz", + "integrity": "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.23.0.tgz", + "integrity": "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-3.23.0.tgz", + "integrity": "sha512-F9msZVxdF+krQNSdQ4V+Ja5QemeAoTQ2jxt7nJCwhDsdF1JWS3KxIQXA3lQbyKwS3J61oHRUSv4jYWv3CkaKTQ==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.23.0", + "@shikijs/types": "3.23.0" + } + }, + "node_modules/@shikijs/types": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.23.0.tgz", + "integrity": "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==", + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.5.tgz", + "integrity": "sha512-bL3AxKuQySfk1iGcBsQnoRVexTPJq0Z/ixFVM8OhVJAP6ZXXXLtM7NFKWhLl30Kg7uTBqIaPXbh+nuQCuBDedg==", + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-rc.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz", + "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@vue/shared": "3.5.32", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz", + "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", + "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@vue/compiler-core": "3.5.32", + "@vue/compiler-dom": "3.5.32", + "@vue/compiler-ssr": "3.5.32", + "@vue/shared": "3.5.32", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.8", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz", + "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/devtools-api": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.1.1.tgz", + "integrity": "sha512-bsDMJ07b3GN1puVwJb/fyFnj/U2imyswK5UQVLZwVl7O05jDrt6BHxeG5XffmOOdasOj/bOmIjxJvGPxU7pcqw==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^8.1.1" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.1.1.tgz", + "integrity": "sha512-gVBaBv++i+adg4JpH71k9ppl4soyR7Y2McEqO5YNgv0BI1kMZ7BDX5gnwkZ5COYgiCyhejZG+yGNrBAjj6Coqg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.1.1", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "perfect-debounce": "^2.0.0" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.1.1.tgz", + "integrity": "sha512-+h4ttmJYl/txpxHKaoZcaKpC+pvckgLzIDiSQlaQ7kKthKh8KuwoLW2D8hPJEnqKzXOvu15UHEoGyngAXCz0EQ==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.32.tgz", + "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.32.tgz", + "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz", + "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.32", + "@vue/runtime-core": "3.5.32", + "@vue/shared": "3.5.32", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.32.tgz", + "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.32", + "@vue/shared": "3.5.32" + }, + "peerDependencies": { + "vue": "3.5.32" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz", + "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==", + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.1.tgz", + "integrity": "sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "14.2.1", + "@vueuse/shared": "14.2.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/integrations": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-14.2.1.tgz", + "integrity": "sha512-2LIUpBi/67PoXJGqSDQUF0pgQWpNHh7beiA+KG2AbybcNm+pTGWT6oPGlBgUoDWmYwfeQqM/uzOHqcILpKL7nA==", + "license": "MIT", + "dependencies": { + "@vueuse/core": "14.2.1", + "@vueuse/shared": "14.2.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7 || ^8", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7 || ^8", + "vue": "^3.5.0" + }, + "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 + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-14.2.1.tgz", + "integrity": "sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-14.2.1.tgz", + "integrity": "sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/focus-trap": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-8.0.1.tgz", + "integrity": "sha512-9ptSG6z51YQOstI/oN4XuVGP/03u2nh0g//qz7L6zX0i6PZiPnkcf3GenXq7N2hZnASXaMxTPpbKwdI+PFvxlw==", + "license": "MIT", + "peer": true, + "dependencies": { + "tabbable": "^6.4.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "license": "MIT" + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/oniguruma-parser": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "license": "MIT" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.5.tgz", + "integrity": "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==", + "license": "MIT", + "dependencies": { + "oniguruma-parser": "^0.12.1", + "regex": "^6.1.0", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/shiki": { + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.23.0.tgz", + "integrity": "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==", + "license": "MIT", + "dependencies": { + "@shikijs/core": "3.23.0", + "@shikijs/engine-javascript": "3.23.0", + "@shikijs/engine-oniguruma": "3.23.0", + "@shikijs/langs": "3.23.0", + "@shikijs/themes": "3.23.0", + "@shikijs/types": "3.23.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "2.0.0-alpha.17", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-2.0.0-alpha.17.tgz", + "integrity": "sha512-Z3VPUpwk/bHYqt1uMVOOK1/4xFiWQov1GNc2FvMdz6kvje4JRXEOngVI9C+bi5jeedMSHiA4dwKkff1NCvbZ9Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "@docsearch/css": "^4.5.3", + "@docsearch/js": "^4.5.3", + "@docsearch/sidepanel-js": "^4.5.3", + "@iconify-json/simple-icons": "^1.2.69", + "@shikijs/core": "^3.22.0", + "@shikijs/transformers": "^3.22.0", + "@shikijs/types": "^3.22.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^6.0.4", + "@vue/devtools-api": "^8.0.5", + "@vue/shared": "^3.5.27", + "@vueuse/core": "^14.2.0", + "@vueuse/integrations": "^14.2.0", + "focus-trap": "^8.0.0", + "mark.js": "8.11.1", + "minisearch": "^7.2.0", + "shiki": "^3.22.0", + "vite": "^7.3.1", + "vue": "^3.5.27" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "oxc-minify": "*", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "oxc-minify": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", + "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.5.32", + "@vue/compiler-sfc": "3.5.32", + "@vue/runtime-dom": "3.5.32", + "@vue/server-renderer": "3.5.32", + "@vue/shared": "3.5.32" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 00000000..f1407730 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,19 @@ +{ + "name": "docs", + "version": "1.0.0", + "description": "", + "main": "config.js", + "scripts": { + "docs:dev": "vitepress dev", + "docs:build": "vitepress build", + "docs:preview": "vitepress preview" + }, + "keywords": [], + "author": "", + "license": "ISC", + "type": "module", + "dependencies": { + "@cakephp/docs-skeleton": "git+ssh://git@github.com:cakephp/docs-skeleton.git#node-package", + "vitepress": "^2.0.0-alpha.16" + } +} diff --git a/docs/public/favicon/apple-touch-icon.png b/docs/public/favicon/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c6d073d7b90df354bf3f850d31823b3f71425aa9 GIT binary patch literal 3756 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 Yei$bomA;yTHxw|rdc&~ditFQl0flquUH||9 literal 0 HcmV?d00001 diff --git a/docs/public/favicon/favicon-96x96.png b/docs/public/favicon/favicon-96x96.png new file mode 100644 index 0000000000000000000000000000000000000000..6642e0cdac521bc20349a06ef18076a2ee71f5a4 GIT binary patch literal 2228 zcmai$XE@sn8^-@pl*DeW9MbUGL}Qn#hDMEQtX66}QEEi2;7}z|G)7fx)TmLT;}uHc zh`ncN&C9H+9W_r=9BQ2QdcVEzhxfyCKi73%_w(ubeYg{>FeYFq7ytlXGgGw9&+YbW zxHy06LRQ!%0N{!=LmS@u!)4RS4{v*0ENZX`59f+OFP>$Wls2_LP_G;osV`40JlXkI zj#rUkarf1eokwyqMG0z9cU*FUT=(DC7O_R0S(FRZxDZDjts>e7KX5M=kX8C7b!I$& zVpT-Dp`w(*Xxb+R5NJg2!SI6M{ME))R+C9;RJuAmy~sCUgiV3K?f@W2IL`AOzWhUM z3Z5vn#=ZYGUc)M{3?Z?pZv>4744dvPzKg%(WZXGQ>C{w#T-=Z4f7L<`XU{S*-PxA$ z7KMEF23OhgKpR$~XBs=wf`Cq8(B8y^YtUHMogQ?E3>qk4frw4m3?&HPC?>sO!VSY^ znAeP^maBx)lhch!vq|l?mKY&rTbXvRSrD^+;BmVWqi^hEj8LaK!LCo+^+tb!P5+W9 zX?A`mHqA^!B|(~Ll=HSq-S}5T&<{pxyeCp_2A9_Eb2Wm)V zAz1))K`xEy=X!rbxgi9h(3)b!Oa$2jg&ZQQY|^4y<_jAoBdsILtvB0R7vbh)~Y0HhBE_3__hk_I)9t79^|9}4v z06z^>0uORtA{RSv;cl0ZnSQs2Y*E55-@!^Rd=9FvxsqcrvBghqmg@_W{aAxteA57P zoxR1$BIGjZm`)eey8X8HGv&R&SJ+&Ncpcu~wQ9wD)Kpt7>9znn%qILX58~d#N+W*D zzP~P8w<=boF42ai_!Zbk8C35G8kpRPHf%gcvQ%rag6Tx}s4Wo;JjY(mGL*#h+Cik^NM zDLr=zjkXtP)GUOM;eXSAAWzBqgNNs;bm;UYeoM80WkFidE{q2Z3pYnC}_BcgOp zNY9;W`g9o11D+2XsJU)1exEJA@VRJp&*$Er8*QSR)Z{B|y=R`SnSFl(X_TuK$X5ad zWt1sbM`XBNf8Lc8dwv_iq!3hYMLDwZh_99VIz3bGau(CuqEfhRHOg?;AYx69u;Wvph@XL0n(+;52fAQNm(dpgys4b-qTI)wOuf*1$%GK_`D+ zMsLK$nDQd-ju0yzN9_>@NA|^~THowsu+%U5hb+X5)VX|%@MMyq75nBZJ(jSCu#KQ75QNf=6NiYN%;$gqp?8auu z=NKc_iHNuO^W(PHnzfx5uz%4p_&8f>DtON#t4`dd^12841#U*zZETY4Y&L*$*g3Yl z1}$$+St)pt`EoLH?QwI7I3v{Q^lJLOL)?O5y+1WP#ugL=ZXfHGsfo#|nMSkryM%n@ zo3#4i`8yn*_e1Os1+4|gSDyBDOS;r>UXC+x%?aX0LLUZ-rcxk%<+Yiwc_(;?nGWL> zho*?^@AfOpw{<&gDoGJIL+L}GwXt#bQu83Tr9g4FVE<(*InP)$MQgjOUGQ?xYBU&}nk|Vt zB5ipWXKNblee-OKynSg-uh6PXd3nExy;o=vTRSJ0w#Filn#>SB*Z2*sn>&xO-Q~5G zAG+xmx2~ljpWE~cs&D(e(Z&4eFxjZ~Y~~Yb#UCFG>-@KBGOzY;%4TSCUV5AR3oNmk zGZ-9*CK|r~^2hWOQ}Xdn&aqt514XDl@-b#RZ)!@{D%lT#Qo~P~LabA8CM>|N3m5%#0He%2Ad%ou~NFmj9e2dBOq=Kufz literal 0 HcmV?d00001 diff --git a/docs/public/favicon/favicon.ico b/docs/public/favicon/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..405aa94ce7a1aab55f757e5c6ee36308fa0facc0 GIT binary patch literal 15086 zcmeI3eT-aH6~G^DV*`G)VrmouyW(PC`RKy5JMU}v&HGs4ABj|h-?2gvMFDAPP$2FY z5Gg8BiHRUo0tk&QRY2=km2D^}((cT>H`5KZ#iiJ$sB0ThD6-x0ci!xFk{Rp06m+kv1PJ`JbDkC^u8! zG|Es#Sqeyc`)Ny{ErI_}38?C>V+XY4JFRG4^^nNW^>}dW6T`hC5tNY6wJ$a+8 zrS5R`)N0@%TTiWbjo|0N(2O+oSl5Lqb5$Yjm#M_HDNft>266YZqrg8pW`l0 zz7M{ax_aw~{tsB= z*R#eyVw--XZ&7ekcX#?tg>$6%y;fdYRc?~!QTY9XW27E%wd9pvZ%Xaz+CI0Kw_3hi z!52I+?jpzFUuD}f{8uQG5uP0*d5NPwdtxp8RV!1LUWGkS_yk^H&ZXgLGx%;tOI?K? zy>~KgntrG3Ue@0lbgf;DpL+9a;XlW(zZ*S}A^QBzmN5JXSMRp z5%S0#!tcXgSH;5aH9TzyLj6>>Zez_MnC&t>741Qx<2w&&q$vvc1g@kMq^rV9_#4~ zo}RuDUHW}&=JjHuAlJln@DtL<>8%}}ueSZ1J0mnB?Y8|~`#GzWo|Lpo@^9PEt+AiW z$zIZrCi}S(pXKt<{YT7xF2_?ly?MRRmSJ0l?KyyLZUo~qRSxLpan3J$W-9;qzMg~s zRrF)pd3YxD2cBQz%<(ncKiFU@P#T+yfNzUHr{C`)t<6Rh+rkGq3(gy&b?9 z@2|bl{ejMFGMB-B0`RZ;+(!kUul1~6+?RpgWb0_bM`O`sR8<@I1vT5RcKx;l+7dYY63B*+qEy9kDWWLjVNpdH1y67z69=@ zZ(JIppQD25KP)Rs2Yd?VC%a$z1P-6-SmLxgff&$^(?SR{?6Iu$TU?Xa2{m=D+)c3` zFJb?^j6138*?Z%8Xl1v=_GEw8uw^d62Kg57Bj`K=aE~9_A!5_KZoh~f(+c`xAJDf8 zp?3>5#4mwec^j!3u0~((q2(S(?jUVqJg~LCj2*osZ^%T}`^c}v(=*Pp@ve#m_ zzF+PRrzli@t45QyUj@XDmo>Cn#)p2b6Pi*NJW5R0m2x(!OsRBkF@2FCZOVPDtRrIE z{I6h>e=^h|%ypTco|-y~{w@Qa7hAn_%eAF4Cy1X4QjFJQ!1qLk%<+pPu0~?6%C%xy zkI!+m^tI*gU5oV}ZKEIj&&nA&KlcQ4_PClpERnbq)7-wG9KBNMTG1V9TmRMXJ1&;% z|BC)AURUM5TdDub(P*dFKQCvD%vum{*l1tb8}^{DiPQ8C`&|Jv@qMMfCb8q}`NT6e zW`8x(cW8;va%FyhDzrb@XMVvx^L!)iR;mNdKcg!)h(DS*_zS$qmP6vXM0du_OcdTO zW)CGEHMASW{@zF$F+jw!Rq*{v9%aQpEM+&cH~$oTUuY8&gYBs4-t%jWca#_vY@zoO z%YP1gZeK30U-sYNI%vFp{wRExJnXegr7Sj%NsQ$=(uVY_c%Nv09~~0N`4e)#<9HWF zfw+>z6M@4a|KN|9%}K8V7|bf;Hz@NaN|wu)FM;E@Ax80R;ODUlX^Nj>KF|rg@qUUQ z&o<5B1$J++(9tt}%-vWXAYbuuRo_E5Y(zImEGa(y={hrC*;<&GA2WT6wSEO4=a_Y} z?!dAp4~mZ9eH?fe+6i>uGn8A4PFTTzP&jWBR~ynG&Ng>vaDaTyR>639#v&FxrX|l4 zdsku_<=haiQ@L-z_Rs4e^tzloo(9Xk#6fhyZMHGY8A@#O?5sS$c^uZ$!@CQKU0-f% zNk`5J;r|Hq^xgTmV~Oj8pHGBm$AY+YZ21rKzm!GraEfXAZ-)kRDEC;=kxqA!e+stx z9h^m;fR~-n;4Vh)JaW+0wSifdd*t3u#)p{vFS1A6Aa*)5H=q;czZw(yJ{Dq$;Y1EA zX#ZZyY^L1+cmY~_?eNZ`^8Fum+gUvgH3*60aM^@P~6!WXbozFirP2Grsqr%dfT=)4Z=lMn}fh)-oOa%niBQ waiddfNZut)=8Tk)wJ \ No newline at end of file diff --git a/docs/public/favicon/site.webmanifest b/docs/public/favicon/site.webmanifest new file mode 100644 index 00000000..4f23fb31 --- /dev/null +++ b/docs/public/favicon/site.webmanifest @@ -0,0 +1,21 @@ +{ + "name": "CakePHP", + "short_name": "CakePHP", + "icons": [ + { + "src": "/favicon/web-app-manifest-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "/favicon/web-app-manifest-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} \ No newline at end of file diff --git a/docs/public/favicon/web-app-manifest-192x192.png b/docs/public/favicon/web-app-manifest-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..b5df2990b8e405b96289c93536cb92bf71c3c49f GIT binary patch literal 3834 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 OwLn8v2T`tU8~h&>G1^1` literal 0 HcmV?d00001 diff --git a/docs/public/favicon/web-app-manifest-512x512.png b/docs/public/favicon/web-app-manifest-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..6a522de3520f9a4740a379cca62afe75ff91a97f GIT binary patch literal 15544 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 literal 0 HcmV?d00001 diff --git a/docs/public/fonts/cakedingbats-webfont.eot b/docs/public/fonts/cakedingbats-webfont.eot new file mode 100644 index 0000000000000000000000000000000000000000..0800d1e7def65757de80ea51112af9929664e7b0 GIT binary patch literal 14117 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�M7B)ZD0hK8i9R2c@+ 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/public/fonts/cakedingbats-webfont.ttf b/docs/public/fonts/cakedingbats-webfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..78ad6c8840a2e758532b358027c16f52c4e00bf6 GIT binary patch literal 21792 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 literal 0 HcmV?d00001 diff --git a/docs/public/fonts/cakedingbats-webfont.woff b/docs/public/fonts/cakedingbats-webfont.woff new file mode 100644 index 0000000000000000000000000000000000000000..a95e1b38b405a4f576421e0c69f575b526e07e89 GIT binary patch literal 15356 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 aR26z@9E{Q#m>c6I;}A^)n6$T#zXJdOPrH@? literal 0 HcmV?d00001 diff --git a/docs/public/logo.svg b/docs/public/logo.svg new file mode 100644 index 00000000..829c8e98 --- /dev/null +++ b/docs/public/logo.svg @@ -0,0 +1,27 @@ + + + +