#
tokens: 29122/50000 1/252 files (page 6/10)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 6 of 10. Use http://codebase.md/jakedismo/master-mcp-server?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .env.example
├── .eslintignore
├── .eslintrc.cjs
├── .eslintrc.js
├── .gitignore
├── .prettierignore
├── .prettierrc
├── .prettierrc.json
├── CHANGELOG.md
├── config
│   ├── default.json
│   ├── development.json
│   ├── production.json
│   └── schema.json
├── config.json
├── CONTRIBUTING.md
├── debug-stdio.cjs
├── debug-stdio.js
├── deploy
│   ├── cloudflare
│   │   ├── .gitkeep
│   │   ├── README.md
│   │   └── wrangler.toml
│   ├── docker
│   │   ├── .gitkeep
│   │   ├── docker-compose.yml
│   │   ├── Dockerfile
│   │   └── entrypoint.sh
│   ├── koyeb
│   │   ├── .gitkeep
│   │   └── koyeb.yaml
│   └── README.md
├── docker-compose.yml
├── Dockerfile
├── docs
│   ├── .DS_Store
│   ├── .vitepress
│   │   ├── cache
│   │   │   └── deps
│   │   │       ├── _metadata.json
│   │   │       ├── chunk-HVR2FF6M.js
│   │   │       ├── chunk-HVR2FF6M.js.map
│   │   │       ├── chunk-P2XGSYO7.js
│   │   │       ├── chunk-P2XGSYO7.js.map
│   │   │       ├── package.json
│   │   │       ├── vitepress___@vue_devtools-api.js
│   │   │       ├── vitepress___@vue_devtools-api.js.map
│   │   │       ├── vitepress___@vueuse_core.js
│   │   │       ├── vitepress___@vueuse_core.js.map
│   │   │       ├── vitepress___@vueuse_integrations_useFocusTrap.js
│   │   │       ├── vitepress___@vueuse_integrations_useFocusTrap.js.map
│   │   │       ├── vitepress___mark__js_src_vanilla__js.js
│   │   │       ├── vitepress___mark__js_src_vanilla__js.js.map
│   │   │       ├── vitepress___minisearch.js
│   │   │       ├── vitepress___minisearch.js.map
│   │   │       ├── vue.js
│   │   │       └── vue.js.map
│   │   ├── config.ts
│   │   ├── dist
│   │   │   ├── 404.html
│   │   │   ├── advanced
│   │   │   │   ├── extensibility.html
│   │   │   │   ├── index.html
│   │   │   │   ├── monitoring.html
│   │   │   │   ├── performance.html
│   │   │   │   └── security.html
│   │   │   ├── api
│   │   │   │   ├── index.html
│   │   │   │   └── README.html
│   │   │   ├── assets
│   │   │   │   ├── advanced_extensibility.md.TrXUn5w5.js
│   │   │   │   ├── advanced_extensibility.md.TrXUn5w5.lean.js
│   │   │   │   ├── advanced_index.md.CPcpUlw_.js
│   │   │   │   ├── advanced_index.md.CPcpUlw_.lean.js
│   │   │   │   ├── advanced_monitoring.md.DTybdNg-.js
│   │   │   │   ├── advanced_monitoring.md.DTybdNg-.lean.js
│   │   │   │   ├── advanced_performance.md.DKmzK0ia.js
│   │   │   │   ├── advanced_performance.md.DKmzK0ia.lean.js
│   │   │   │   ├── advanced_security.md.B-oBD7IB.js
│   │   │   │   ├── advanced_security.md.B-oBD7IB.lean.js
│   │   │   │   ├── api_index.md.Dl1JB08_.js
│   │   │   │   ├── api_index.md.Dl1JB08_.lean.js
│   │   │   │   ├── chunks
│   │   │   │   │   └── framework.CHl2ywxc.js
│   │   │   │   ├── configuration_environment-variables.md.Ddy3P_Wz.js
│   │   │   │   ├── configuration_environment-variables.md.Ddy3P_Wz.lean.js
│   │   │   │   ├── configuration_environment.md.DxcTQ623.js
│   │   │   │   ├── configuration_environment.md.DxcTQ623.lean.js
│   │   │   │   ├── configuration_overview.md.DIkVDv7V.js
│   │   │   │   ├── configuration_overview.md.DIkVDv7V.lean.js
│   │   │   │   ├── configuration_performance.md.DbJdmLrW.js
│   │   │   │   ├── configuration_performance.md.DbJdmLrW.lean.js
│   │   │   │   ├── configuration_reference.md.27IKWqtk.js
│   │   │   │   ├── configuration_reference.md.27IKWqtk.lean.js
│   │   │   │   ├── configuration_security.md.-OOlkzN4.js
│   │   │   │   ├── configuration_security.md.-OOlkzN4.lean.js
│   │   │   │   ├── contributing_dev-setup.md.Ceqh4w-R.js
│   │   │   │   ├── contributing_dev-setup.md.Ceqh4w-R.lean.js
│   │   │   │   ├── contributing_guidelines.md.ZEAX2yVh.js
│   │   │   │   ├── contributing_guidelines.md.ZEAX2yVh.lean.js
│   │   │   │   ├── contributing_index.md.DYq9R6wr.js
│   │   │   │   ├── contributing_index.md.DYq9R6wr.lean.js
│   │   │   │   ├── contributing_maintenance.md.k2bR0IaR.js
│   │   │   │   ├── contributing_maintenance.md.k2bR0IaR.lean.js
│   │   │   │   ├── deployment_cicd.md.Ci2T0UYC.js
│   │   │   │   ├── deployment_cicd.md.Ci2T0UYC.lean.js
│   │   │   │   ├── deployment_cloudflare-workers.md.D2WHsfep.js
│   │   │   │   ├── deployment_cloudflare-workers.md.D2WHsfep.lean.js
│   │   │   │   ├── deployment_docker.md.B8bQDQTo.js
│   │   │   │   ├── deployment_docker.md.B8bQDQTo.lean.js
│   │   │   │   ├── deployment_index.md.ClYeOkpy.js
│   │   │   │   ├── deployment_index.md.ClYeOkpy.lean.js
│   │   │   │   ├── deployment_koyeb.md.B_wJhvF7.js
│   │   │   │   ├── deployment_koyeb.md.B_wJhvF7.lean.js
│   │   │   │   ├── examples_advanced-routing.md.B3CqhLZ7.js
│   │   │   │   ├── examples_advanced-routing.md.B3CqhLZ7.lean.js
│   │   │   │   ├── examples_basic-node.md.CaDZzGlO.js
│   │   │   │   ├── examples_basic-node.md.CaDZzGlO.lean.js
│   │   │   │   ├── examples_cloudflare-worker.md.DwVSz-c7.js
│   │   │   │   ├── examples_cloudflare-worker.md.DwVSz-c7.lean.js
│   │   │   │   ├── examples_index.md.CBF_BLkl.js
│   │   │   │   ├── examples_index.md.CBF_BLkl.lean.js
│   │   │   │   ├── examples_oauth-delegation.md.1hZxoqDl.js
│   │   │   │   ├── examples_oauth-delegation.md.1hZxoqDl.lean.js
│   │   │   │   ├── examples_overview.md.CZN0JbZ7.js
│   │   │   │   ├── examples_overview.md.CZN0JbZ7.lean.js
│   │   │   │   ├── examples_testing.md.Dek4GpNs.js
│   │   │   │   ├── examples_testing.md.Dek4GpNs.lean.js
│   │   │   │   ├── getting-started_concepts.md.D7ON9iGB.js
│   │   │   │   ├── getting-started_concepts.md.D7ON9iGB.lean.js
│   │   │   │   ├── getting-started_installation.md.BKnVqAGg.js
│   │   │   │   ├── getting-started_installation.md.BKnVqAGg.lean.js
│   │   │   │   ├── getting-started_overview.md.DvJDFL2N.js
│   │   │   │   ├── getting-started_overview.md.DvJDFL2N.lean.js
│   │   │   │   ├── getting-started_quickstart-node.md.GOO4aGas.js
│   │   │   │   ├── getting-started_quickstart-node.md.GOO4aGas.lean.js
│   │   │   │   ├── getting-started_quickstart-workers.md.Cpofh8Mj.js
│   │   │   │   ├── getting-started_quickstart-workers.md.Cpofh8Mj.lean.js
│   │   │   │   ├── getting-started.md.DG9ndneo.js
│   │   │   │   ├── getting-started.md.DG9ndneo.lean.js
│   │   │   │   ├── guides_configuration-management.md.B-jwYMbA.js
│   │   │   │   ├── guides_configuration-management.md.B-jwYMbA.lean.js
│   │   │   │   ├── guides_configuration.md.Ci3zYDFA.js
│   │   │   │   ├── guides_configuration.md.Ci3zYDFA.lean.js
│   │   │   │   ├── guides_index.md.CIlq2fmx.js
│   │   │   │   ├── guides_index.md.CIlq2fmx.lean.js
│   │   │   │   ├── guides_module-loading.md.BkJvuRnQ.js
│   │   │   │   ├── guides_module-loading.md.BkJvuRnQ.lean.js
│   │   │   │   ├── guides_oauth-delegation.md.DEOZ-_G0.js
│   │   │   │   ├── guides_oauth-delegation.md.DEOZ-_G0.lean.js
│   │   │   │   ├── guides_request-routing.md.Bdzf0VLg.js
│   │   │   │   ├── guides_request-routing.md.Bdzf0VLg.lean.js
│   │   │   │   ├── guides_testing.md.kYfHqJLu.js
│   │   │   │   ├── guides_testing.md.kYfHqJLu.lean.js
│   │   │   │   ├── inter-italic-cyrillic-ext.r48I6akx.woff2
│   │   │   │   ├── inter-italic-cyrillic.By2_1cv3.woff2
│   │   │   │   ├── inter-italic-greek-ext.1u6EdAuj.woff2
│   │   │   │   ├── inter-italic-greek.DJ8dCoTZ.woff2
│   │   │   │   ├── inter-italic-latin-ext.CN1xVJS-.woff2
│   │   │   │   ├── inter-italic-latin.C2AdPX0b.woff2
│   │   │   │   ├── inter-italic-vietnamese.BSbpV94h.woff2
│   │   │   │   ├── inter-roman-cyrillic-ext.BBPuwvHQ.woff2
│   │   │   │   ├── inter-roman-cyrillic.C5lxZ8CY.woff2
│   │   │   │   ├── inter-roman-greek-ext.CqjqNYQ-.woff2
│   │   │   │   ├── inter-roman-greek.BBVDIX6e.woff2
│   │   │   │   ├── inter-roman-latin-ext.4ZJIpNVo.woff2
│   │   │   │   ├── inter-roman-latin.Di8DUHzh.woff2
│   │   │   │   ├── inter-roman-vietnamese.BjW4sHH5.woff2
│   │   │   │   ├── README.md.BO5r5M9u.js
│   │   │   │   ├── README.md.BO5r5M9u.lean.js
│   │   │   │   ├── style.BQrfSMzK.css
│   │   │   │   ├── troubleshooting_common-issues.md.CScvzWM1.js
│   │   │   │   ├── troubleshooting_common-issues.md.CScvzWM1.lean.js
│   │   │   │   ├── troubleshooting_deployment.md.DUhpqnLE.js
│   │   │   │   ├── troubleshooting_deployment.md.DUhpqnLE.lean.js
│   │   │   │   ├── troubleshooting_errors.md.BSCsEmGc.js
│   │   │   │   ├── troubleshooting_errors.md.BSCsEmGc.lean.js
│   │   │   │   ├── troubleshooting_oauth.md.Cw60Eka3.js
│   │   │   │   ├── troubleshooting_oauth.md.Cw60Eka3.lean.js
│   │   │   │   ├── troubleshooting_performance.md.DxY6LJcT.js
│   │   │   │   ├── troubleshooting_performance.md.DxY6LJcT.lean.js
│   │   │   │   ├── troubleshooting_routing.md.BHN-MDhs.js
│   │   │   │   ├── troubleshooting_routing.md.BHN-MDhs.lean.js
│   │   │   │   ├── troubleshooting_security-best-practices.md.Yiu8E-zt.js
│   │   │   │   ├── troubleshooting_security-best-practices.md.Yiu8E-zt.lean.js
│   │   │   │   ├── tutorials_beginner-getting-started.md.BXObgobW.js
│   │   │   │   ├── tutorials_beginner-getting-started.md.BXObgobW.lean.js
│   │   │   │   ├── tutorials_cloudflare-workers-tutorial.md.MPHsc0aT.js
│   │   │   │   ├── tutorials_cloudflare-workers-tutorial.md.MPHsc0aT.lean.js
│   │   │   │   ├── tutorials_load-balancing-and-resilience.md.Dv9r9jyW.js
│   │   │   │   ├── tutorials_load-balancing-and-resilience.md.Dv9r9jyW.lean.js
│   │   │   │   ├── tutorials_oauth-delegation-github.md.Nq4glqCe.js
│   │   │   │   └── tutorials_oauth-delegation-github.md.Nq4glqCe.lean.js
│   │   │   ├── configuration
│   │   │   │   ├── environment-variables.html
│   │   │   │   ├── environment.html
│   │   │   │   ├── examples.html
│   │   │   │   ├── overview.html
│   │   │   │   ├── performance.html
│   │   │   │   ├── reference.html
│   │   │   │   └── security.html
│   │   │   ├── contributing
│   │   │   │   ├── dev-setup.html
│   │   │   │   ├── guidelines.html
│   │   │   │   ├── index.html
│   │   │   │   └── maintenance.html
│   │   │   ├── deployment
│   │   │   │   ├── cicd.html
│   │   │   │   ├── cloudflare-workers.html
│   │   │   │   ├── docker.html
│   │   │   │   ├── index.html
│   │   │   │   └── koyeb.html
│   │   │   ├── diagrams
│   │   │   │   └── architecture.svg
│   │   │   ├── examples
│   │   │   │   ├── advanced-routing.html
│   │   │   │   ├── basic-node.html
│   │   │   │   ├── cloudflare-worker.html
│   │   │   │   ├── index.html
│   │   │   │   ├── oauth-delegation.html
│   │   │   │   ├── overview.html
│   │   │   │   └── testing.html
│   │   │   ├── getting-started
│   │   │   │   ├── concepts.html
│   │   │   │   ├── installation.html
│   │   │   │   ├── overview.html
│   │   │   │   ├── quick-start.html
│   │   │   │   ├── quickstart-node.html
│   │   │   │   └── quickstart-workers.html
│   │   │   ├── getting-started.html
│   │   │   ├── guides
│   │   │   │   ├── authentication.html
│   │   │   │   ├── client-integration.html
│   │   │   │   ├── configuration-management.html
│   │   │   │   ├── configuration.html
│   │   │   │   ├── index.html
│   │   │   │   ├── module-loading.html
│   │   │   │   ├── oauth-delegation.html
│   │   │   │   ├── request-routing.html
│   │   │   │   ├── server-management.html
│   │   │   │   ├── server-sharing.html
│   │   │   │   └── testing.html
│   │   │   ├── hashmap.json
│   │   │   ├── index.html
│   │   │   ├── logo.svg
│   │   │   ├── README.html
│   │   │   ├── reports
│   │   │   │   └── mcp-compliance-audit.html
│   │   │   ├── troubleshooting
│   │   │   │   ├── common-issues.html
│   │   │   │   ├── deployment.html
│   │   │   │   ├── errors.html
│   │   │   │   ├── index.html
│   │   │   │   ├── oauth.html
│   │   │   │   ├── performance.html
│   │   │   │   ├── routing.html
│   │   │   │   └── security-best-practices.html
│   │   │   ├── tutorials
│   │   │   │   ├── beginner-getting-started.html
│   │   │   │   ├── cloudflare-workers-tutorial.html
│   │   │   │   ├── load-balancing-and-resilience.html
│   │   │   │   └── oauth-delegation-github.html
│   │   │   └── vp-icons.css
│   │   └── theme
│   │       ├── components
│   │       │   ├── ApiPlayground.vue
│   │       │   ├── AuthFlowDemo.vue
│   │       │   ├── CodeTabs.vue
│   │       │   └── ConfigGenerator.vue
│   │       ├── index.ts
│   │       └── style.css
│   ├── advanced
│   │   ├── extensibility.md
│   │   ├── index.md
│   │   ├── monitoring.md
│   │   ├── performance.md
│   │   └── security.md
│   ├── api
│   │   ├── functions
│   │   │   └── createServer.md
│   │   ├── index.md
│   │   ├── interfaces
│   │   │   └── RunningServer.md
│   │   └── README.md
│   ├── architecture
│   │   └── images
│   │       └── mcp_master_architecture.svg
│   ├── configuration
│   │   ├── environment-variables.md
│   │   ├── environment.md
│   │   ├── examples.md
│   │   ├── overview.md
│   │   ├── performance.md
│   │   ├── reference.md
│   │   └── security.md
│   ├── contributing
│   │   ├── dev-setup.md
│   │   ├── guidelines.md
│   │   ├── index.md
│   │   └── maintenance.md
│   ├── deployment
│   │   ├── cicd.md
│   │   ├── cloudflare-workers.md
│   │   ├── docker.md
│   │   ├── docs-site.md
│   │   ├── index.md
│   │   └── koyeb.md
│   ├── examples
│   │   ├── advanced-routing.md
│   │   ├── basic-node.md
│   │   ├── cloudflare-worker.md
│   │   ├── index.md
│   │   ├── oauth-delegation.md
│   │   ├── overview.md
│   │   └── testing.md
│   ├── getting-started
│   │   ├── concepts.md
│   │   ├── installation.md
│   │   ├── overview.md
│   │   ├── quick-start.md
│   │   ├── quickstart-node.md
│   │   └── quickstart-workers.md
│   ├── getting-started.md
│   ├── guides
│   │   ├── authentication.md
│   │   ├── client-integration.md
│   │   ├── configuration-management.md
│   │   ├── configuration.md
│   │   ├── index.md
│   │   ├── module-loading.md
│   │   ├── oauth-delegation.md
│   │   ├── request-routing.md
│   │   ├── server-management.md
│   │   ├── server-sharing.md
│   │   └── testing.md
│   ├── index.html
│   ├── public
│   │   ├── diagrams
│   │   │   └── architecture.svg
│   │   ├── github-social.png
│   │   │   └── image.png
│   │   ├── logo.png
│   │   └── logo.svg
│   ├── README.md
│   ├── stdio-servers.md
│   ├── testing
│   │   └── phase-9-testing-architecture.md
│   ├── troubleshooting
│   │   ├── common-issues.md
│   │   ├── deployment.md
│   │   ├── errors.md
│   │   ├── index.md
│   │   ├── oauth.md
│   │   ├── performance.md
│   │   ├── routing.md
│   │   └── security-best-practices.md
│   └── tutorials
│       ├── beginner-getting-started.md
│       ├── cloudflare-workers-tutorial.md
│       ├── load-balancing-and-resilience.md
│       └── oauth-delegation-github.md
├── examples
│   ├── advanced-routing
│   │   ├── config.yaml
│   │   └── README.md
│   ├── basic-node
│   │   ├── config.yaml
│   │   ├── README.md
│   │   └── server.ts
│   ├── cloudflare-worker
│   │   ├── README.md
│   │   └── worker.ts
│   ├── custom-auth
│   │   ├── config.yaml
│   │   ├── index.ts
│   │   └── README.md
│   ├── multi-server
│   │   ├── config.yaml
│   │   └── README.md
│   ├── oauth-delegation
│   │   └── README.md
│   ├── oauth-node
│   │   ├── config.yaml
│   │   └── README.md
│   ├── performance
│   │   ├── config.yaml
│   │   └── README.md
│   ├── sample-configs
│   │   ├── basic.yaml
│   │   └── simple-setup.yaml
│   ├── security-hardening
│   │   └── README.md
│   ├── stdio-mcp-server.cjs
│   ├── test-mcp-server.js
│   └── test-stdio-server.js
├── LICENSE
├── master-mcp-definition.md
├── package-lock.json
├── package.json
├── README.md
├── reports
│   └── claude_report_20250815_222153.html
├── scripts
│   └── generate-config-docs.ts
├── src
│   ├── auth
│   │   ├── multi-auth-manager.ts
│   │   ├── oauth-providers.ts
│   │   └── token-manager.ts
│   ├── config
│   │   ├── config-loader.ts
│   │   ├── environment-manager.ts
│   │   ├── schema-validator.ts
│   │   └── secret-manager.ts
│   ├── index.ts
│   ├── mcp-server.ts
│   ├── modules
│   │   ├── capability-aggregator.ts
│   │   ├── module-loader.ts
│   │   ├── request-router.ts
│   │   ├── stdio-capability-discovery.ts
│   │   └── stdio-manager.ts
│   ├── oauth
│   │   ├── callback-handler.ts
│   │   ├── flow-controller.ts
│   │   ├── flow-validator.ts
│   │   ├── pkce-manager.ts
│   │   ├── state-manager.ts
│   │   └── web-interface.ts
│   ├── routing
│   │   ├── circuit-breaker.ts
│   │   ├── load-balancer.ts
│   │   ├── retry-handler.ts
│   │   └── route-registry.ts
│   ├── runtime
│   │   ├── node.ts
│   │   └── worker.ts
│   ├── server
│   │   ├── config-manager.ts
│   │   ├── dependency-container.ts
│   │   ├── master-server.ts
│   │   └── protocol-handler.ts
│   ├── types
│   │   ├── auth.ts
│   │   ├── config.ts
│   │   ├── jose-shim.d.ts
│   │   ├── mcp.ts
│   │   └── server.ts
│   └── utils
│       ├── cache.ts
│       ├── crypto.ts
│       ├── dev.ts
│       ├── errors.ts
│       ├── http.ts
│       ├── logger.ts
│       ├── monitoring.ts
│       ├── string.ts
│       ├── time.ts
│       ├── validation.ts
│       └── validators.ts
├── static
│   └── oauth
│       ├── consent.html
│       ├── error.html
│       ├── script.js
│       ├── style.css
│       └── success.html
├── tests
│   ├── _setup
│   │   ├── miniflare.setup.ts
│   │   └── vitest.setup.ts
│   ├── _utils
│   │   ├── log-capture.ts
│   │   ├── mock-fetch.ts
│   │   └── test-server.ts
│   ├── .gitkeep
│   ├── e2e
│   │   ├── flow-controller.express.test.ts
│   │   └── flow-controller.worker.test.ts
│   ├── factories
│   │   ├── configFactory.ts
│   │   ├── mcpFactory.ts
│   │   └── oauthFactory.ts
│   ├── fixtures
│   │   ├── capabilities.json
│   │   └── stdio-server.js
│   ├── integration
│   │   ├── modules.capability-aggregator.test.ts
│   │   ├── modules.module-loader-health.test.ts
│   │   ├── oauth.callback-handler.test.ts
│   │   └── request-router.test.ts
│   ├── mocks
│   │   ├── mcp
│   │   │   └── fake-backend.ts
│   │   └── oauth
│   │       └── mock-oidc-provider.ts
│   ├── perf
│   │   ├── artillery
│   │   │   └── auth-routing.yaml
│   │   └── perf.auth-and-routing.test.ts
│   ├── security
│   │   └── security.oauth-and-input.test.ts
│   ├── servers
│   │   ├── test-auth-simple.js
│   │   ├── test-debug.js
│   │   ├── test-master-mcp.js
│   │   ├── test-mcp-client.js
│   │   ├── test-streaming-both-complete.js
│   │   ├── test-streaming-both-full.js
│   │   ├── test-streaming-both-simple.js
│   │   ├── test-streaming-both.js
│   │   └── test-streaming.js
│   ├── setup
│   │   └── test-setup.ts
│   ├── unit
│   │   ├── auth.multi-auth-manager.test.ts
│   │   ├── auth.token-manager.test.ts
│   │   ├── config.environment-manager.test.ts
│   │   ├── config.schema-validator.test.ts
│   │   ├── config.secret-manager.test.ts
│   │   ├── modules
│   │   │   ├── stdio-capability-discovery.test.ts
│   │   │   └── stdio-manager.test.ts
│   │   ├── modules.route-registry.test.ts
│   │   ├── oauth.pkce-state.test.ts
│   │   ├── routing
│   │   │   └── circuit-breaker.test.ts
│   │   ├── routing.core.test.ts
│   │   ├── stdio-capability-discovery.test.ts
│   │   ├── utils.crypto.test.ts
│   │   ├── utils.logger.test.ts
│   │   └── utils.monitoring.test.ts
│   └── utils
│       ├── fake-express.ts
│       ├── mock-http.ts
│       ├── oauth-mocks.ts
│       └── token-storages.ts
├── tsconfig.base.json
├── tsconfig.json
├── tsconfig.node.json
├── tsconfig.worker.json
├── typedoc.json
├── vitest.config.ts
└── vitest.worker.config.ts
```

# Files

--------------------------------------------------------------------------------
/docs/.vitepress/cache/deps/vitepress___minisearch.js:
--------------------------------------------------------------------------------

```javascript
   1 | // node_modules/minisearch/dist/es/index.js
   2 | var ENTRIES = "ENTRIES";
   3 | var KEYS = "KEYS";
   4 | var VALUES = "VALUES";
   5 | var LEAF = "";
   6 | var TreeIterator = class {
   7 |   constructor(set, type) {
   8 |     const node = set._tree;
   9 |     const keys = Array.from(node.keys());
  10 |     this.set = set;
  11 |     this._type = type;
  12 |     this._path = keys.length > 0 ? [{ node, keys }] : [];
  13 |   }
  14 |   next() {
  15 |     const value = this.dive();
  16 |     this.backtrack();
  17 |     return value;
  18 |   }
  19 |   dive() {
  20 |     if (this._path.length === 0) {
  21 |       return { done: true, value: void 0 };
  22 |     }
  23 |     const { node, keys } = last$1(this._path);
  24 |     if (last$1(keys) === LEAF) {
  25 |       return { done: false, value: this.result() };
  26 |     }
  27 |     const child = node.get(last$1(keys));
  28 |     this._path.push({ node: child, keys: Array.from(child.keys()) });
  29 |     return this.dive();
  30 |   }
  31 |   backtrack() {
  32 |     if (this._path.length === 0) {
  33 |       return;
  34 |     }
  35 |     const keys = last$1(this._path).keys;
  36 |     keys.pop();
  37 |     if (keys.length > 0) {
  38 |       return;
  39 |     }
  40 |     this._path.pop();
  41 |     this.backtrack();
  42 |   }
  43 |   key() {
  44 |     return this.set._prefix + this._path.map(({ keys }) => last$1(keys)).filter((key) => key !== LEAF).join("");
  45 |   }
  46 |   value() {
  47 |     return last$1(this._path).node.get(LEAF);
  48 |   }
  49 |   result() {
  50 |     switch (this._type) {
  51 |       case VALUES:
  52 |         return this.value();
  53 |       case KEYS:
  54 |         return this.key();
  55 |       default:
  56 |         return [this.key(), this.value()];
  57 |     }
  58 |   }
  59 |   [Symbol.iterator]() {
  60 |     return this;
  61 |   }
  62 | };
  63 | var last$1 = (array) => {
  64 |   return array[array.length - 1];
  65 | };
  66 | var fuzzySearch = (node, query, maxDistance) => {
  67 |   const results = /* @__PURE__ */ new Map();
  68 |   if (query === void 0)
  69 |     return results;
  70 |   const n = query.length + 1;
  71 |   const m = n + maxDistance;
  72 |   const matrix = new Uint8Array(m * n).fill(maxDistance + 1);
  73 |   for (let j = 0; j < n; ++j)
  74 |     matrix[j] = j;
  75 |   for (let i = 1; i < m; ++i)
  76 |     matrix[i * n] = i;
  77 |   recurse(node, query, maxDistance, results, matrix, 1, n, "");
  78 |   return results;
  79 | };
  80 | var recurse = (node, query, maxDistance, results, matrix, m, n, prefix) => {
  81 |   const offset = m * n;
  82 |   key: for (const key of node.keys()) {
  83 |     if (key === LEAF) {
  84 |       const distance = matrix[offset - 1];
  85 |       if (distance <= maxDistance) {
  86 |         results.set(prefix, [node.get(key), distance]);
  87 |       }
  88 |     } else {
  89 |       let i = m;
  90 |       for (let pos = 0; pos < key.length; ++pos, ++i) {
  91 |         const char = key[pos];
  92 |         const thisRowOffset = n * i;
  93 |         const prevRowOffset = thisRowOffset - n;
  94 |         let minDistance = matrix[thisRowOffset];
  95 |         const jmin = Math.max(0, i - maxDistance - 1);
  96 |         const jmax = Math.min(n - 1, i + maxDistance);
  97 |         for (let j = jmin; j < jmax; ++j) {
  98 |           const different = char !== query[j];
  99 |           const rpl = matrix[prevRowOffset + j] + +different;
 100 |           const del = matrix[prevRowOffset + j + 1] + 1;
 101 |           const ins = matrix[thisRowOffset + j] + 1;
 102 |           const dist = matrix[thisRowOffset + j + 1] = Math.min(rpl, del, ins);
 103 |           if (dist < minDistance)
 104 |             minDistance = dist;
 105 |         }
 106 |         if (minDistance > maxDistance) {
 107 |           continue key;
 108 |         }
 109 |       }
 110 |       recurse(node.get(key), query, maxDistance, results, matrix, i, n, prefix + key);
 111 |     }
 112 |   }
 113 | };
 114 | var SearchableMap = class _SearchableMap {
 115 |   /**
 116 |    * The constructor is normally called without arguments, creating an empty
 117 |    * map. In order to create a {@link SearchableMap} from an iterable or from an
 118 |    * object, check {@link SearchableMap.from} and {@link
 119 |    * SearchableMap.fromObject}.
 120 |    *
 121 |    * The constructor arguments are for internal use, when creating derived
 122 |    * mutable views of a map at a prefix.
 123 |    */
 124 |   constructor(tree = /* @__PURE__ */ new Map(), prefix = "") {
 125 |     this._size = void 0;
 126 |     this._tree = tree;
 127 |     this._prefix = prefix;
 128 |   }
 129 |   /**
 130 |    * Creates and returns a mutable view of this {@link SearchableMap},
 131 |    * containing only entries that share the given prefix.
 132 |    *
 133 |    * ### Usage:
 134 |    *
 135 |    * ```javascript
 136 |    * let map = new SearchableMap()
 137 |    * map.set("unicorn", 1)
 138 |    * map.set("universe", 2)
 139 |    * map.set("university", 3)
 140 |    * map.set("unique", 4)
 141 |    * map.set("hello", 5)
 142 |    *
 143 |    * let uni = map.atPrefix("uni")
 144 |    * uni.get("unique") // => 4
 145 |    * uni.get("unicorn") // => 1
 146 |    * uni.get("hello") // => undefined
 147 |    *
 148 |    * let univer = map.atPrefix("univer")
 149 |    * univer.get("unique") // => undefined
 150 |    * univer.get("universe") // => 2
 151 |    * univer.get("university") // => 3
 152 |    * ```
 153 |    *
 154 |    * @param prefix  The prefix
 155 |    * @return A {@link SearchableMap} representing a mutable view of the original
 156 |    * Map at the given prefix
 157 |    */
 158 |   atPrefix(prefix) {
 159 |     if (!prefix.startsWith(this._prefix)) {
 160 |       throw new Error("Mismatched prefix");
 161 |     }
 162 |     const [node, path] = trackDown(this._tree, prefix.slice(this._prefix.length));
 163 |     if (node === void 0) {
 164 |       const [parentNode, key] = last(path);
 165 |       for (const k of parentNode.keys()) {
 166 |         if (k !== LEAF && k.startsWith(key)) {
 167 |           const node2 = /* @__PURE__ */ new Map();
 168 |           node2.set(k.slice(key.length), parentNode.get(k));
 169 |           return new _SearchableMap(node2, prefix);
 170 |         }
 171 |       }
 172 |     }
 173 |     return new _SearchableMap(node, prefix);
 174 |   }
 175 |   /**
 176 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear
 177 |    */
 178 |   clear() {
 179 |     this._size = void 0;
 180 |     this._tree.clear();
 181 |   }
 182 |   /**
 183 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete
 184 |    * @param key  Key to delete
 185 |    */
 186 |   delete(key) {
 187 |     this._size = void 0;
 188 |     return remove(this._tree, key);
 189 |   }
 190 |   /**
 191 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries
 192 |    * @return An iterator iterating through `[key, value]` entries.
 193 |    */
 194 |   entries() {
 195 |     return new TreeIterator(this, ENTRIES);
 196 |   }
 197 |   /**
 198 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach
 199 |    * @param fn  Iteration function
 200 |    */
 201 |   forEach(fn) {
 202 |     for (const [key, value] of this) {
 203 |       fn(key, value, this);
 204 |     }
 205 |   }
 206 |   /**
 207 |    * Returns a Map of all the entries that have a key within the given edit
 208 |    * distance from the search key. The keys of the returned Map are the matching
 209 |    * keys, while the values are two-element arrays where the first element is
 210 |    * the value associated to the key, and the second is the edit distance of the
 211 |    * key to the search key.
 212 |    *
 213 |    * ### Usage:
 214 |    *
 215 |    * ```javascript
 216 |    * let map = new SearchableMap()
 217 |    * map.set('hello', 'world')
 218 |    * map.set('hell', 'yeah')
 219 |    * map.set('ciao', 'mondo')
 220 |    *
 221 |    * // Get all entries that match the key 'hallo' with a maximum edit distance of 2
 222 |    * map.fuzzyGet('hallo', 2)
 223 |    * // => Map(2) { 'hello' => ['world', 1], 'hell' => ['yeah', 2] }
 224 |    *
 225 |    * // In the example, the "hello" key has value "world" and edit distance of 1
 226 |    * // (change "e" to "a"), the key "hell" has value "yeah" and edit distance of 2
 227 |    * // (change "e" to "a", delete "o")
 228 |    * ```
 229 |    *
 230 |    * @param key  The search key
 231 |    * @param maxEditDistance  The maximum edit distance (Levenshtein)
 232 |    * @return A Map of the matching keys to their value and edit distance
 233 |    */
 234 |   fuzzyGet(key, maxEditDistance) {
 235 |     return fuzzySearch(this._tree, key, maxEditDistance);
 236 |   }
 237 |   /**
 238 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get
 239 |    * @param key  Key to get
 240 |    * @return Value associated to the key, or `undefined` if the key is not
 241 |    * found.
 242 |    */
 243 |   get(key) {
 244 |     const node = lookup(this._tree, key);
 245 |     return node !== void 0 ? node.get(LEAF) : void 0;
 246 |   }
 247 |   /**
 248 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has
 249 |    * @param key  Key
 250 |    * @return True if the key is in the map, false otherwise
 251 |    */
 252 |   has(key) {
 253 |     const node = lookup(this._tree, key);
 254 |     return node !== void 0 && node.has(LEAF);
 255 |   }
 256 |   /**
 257 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys
 258 |    * @return An `Iterable` iterating through keys
 259 |    */
 260 |   keys() {
 261 |     return new TreeIterator(this, KEYS);
 262 |   }
 263 |   /**
 264 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set
 265 |    * @param key  Key to set
 266 |    * @param value  Value to associate to the key
 267 |    * @return The {@link SearchableMap} itself, to allow chaining
 268 |    */
 269 |   set(key, value) {
 270 |     if (typeof key !== "string") {
 271 |       throw new Error("key must be a string");
 272 |     }
 273 |     this._size = void 0;
 274 |     const node = createPath(this._tree, key);
 275 |     node.set(LEAF, value);
 276 |     return this;
 277 |   }
 278 |   /**
 279 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size
 280 |    */
 281 |   get size() {
 282 |     if (this._size) {
 283 |       return this._size;
 284 |     }
 285 |     this._size = 0;
 286 |     const iter = this.entries();
 287 |     while (!iter.next().done)
 288 |       this._size += 1;
 289 |     return this._size;
 290 |   }
 291 |   /**
 292 |    * Updates the value at the given key using the provided function. The function
 293 |    * is called with the current value at the key, and its return value is used as
 294 |    * the new value to be set.
 295 |    *
 296 |    * ### Example:
 297 |    *
 298 |    * ```javascript
 299 |    * // Increment the current value by one
 300 |    * searchableMap.update('somekey', (currentValue) => currentValue == null ? 0 : currentValue + 1)
 301 |    * ```
 302 |    *
 303 |    * If the value at the given key is or will be an object, it might not require
 304 |    * re-assignment. In that case it is better to use `fetch()`, because it is
 305 |    * faster.
 306 |    *
 307 |    * @param key  The key to update
 308 |    * @param fn  The function used to compute the new value from the current one
 309 |    * @return The {@link SearchableMap} itself, to allow chaining
 310 |    */
 311 |   update(key, fn) {
 312 |     if (typeof key !== "string") {
 313 |       throw new Error("key must be a string");
 314 |     }
 315 |     this._size = void 0;
 316 |     const node = createPath(this._tree, key);
 317 |     node.set(LEAF, fn(node.get(LEAF)));
 318 |     return this;
 319 |   }
 320 |   /**
 321 |    * Fetches the value of the given key. If the value does not exist, calls the
 322 |    * given function to create a new value, which is inserted at the given key
 323 |    * and subsequently returned.
 324 |    *
 325 |    * ### Example:
 326 |    *
 327 |    * ```javascript
 328 |    * const map = searchableMap.fetch('somekey', () => new Map())
 329 |    * map.set('foo', 'bar')
 330 |    * ```
 331 |    *
 332 |    * @param key  The key to update
 333 |    * @param initial  A function that creates a new value if the key does not exist
 334 |    * @return The existing or new value at the given key
 335 |    */
 336 |   fetch(key, initial) {
 337 |     if (typeof key !== "string") {
 338 |       throw new Error("key must be a string");
 339 |     }
 340 |     this._size = void 0;
 341 |     const node = createPath(this._tree, key);
 342 |     let value = node.get(LEAF);
 343 |     if (value === void 0) {
 344 |       node.set(LEAF, value = initial());
 345 |     }
 346 |     return value;
 347 |   }
 348 |   /**
 349 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values
 350 |    * @return An `Iterable` iterating through values.
 351 |    */
 352 |   values() {
 353 |     return new TreeIterator(this, VALUES);
 354 |   }
 355 |   /**
 356 |    * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@iterator
 357 |    */
 358 |   [Symbol.iterator]() {
 359 |     return this.entries();
 360 |   }
 361 |   /**
 362 |    * Creates a {@link SearchableMap} from an `Iterable` of entries
 363 |    *
 364 |    * @param entries  Entries to be inserted in the {@link SearchableMap}
 365 |    * @return A new {@link SearchableMap} with the given entries
 366 |    */
 367 |   static from(entries) {
 368 |     const tree = new _SearchableMap();
 369 |     for (const [key, value] of entries) {
 370 |       tree.set(key, value);
 371 |     }
 372 |     return tree;
 373 |   }
 374 |   /**
 375 |    * Creates a {@link SearchableMap} from the iterable properties of a JavaScript object
 376 |    *
 377 |    * @param object  Object of entries for the {@link SearchableMap}
 378 |    * @return A new {@link SearchableMap} with the given entries
 379 |    */
 380 |   static fromObject(object) {
 381 |     return _SearchableMap.from(Object.entries(object));
 382 |   }
 383 | };
 384 | var trackDown = (tree, key, path = []) => {
 385 |   if (key.length === 0 || tree == null) {
 386 |     return [tree, path];
 387 |   }
 388 |   for (const k of tree.keys()) {
 389 |     if (k !== LEAF && key.startsWith(k)) {
 390 |       path.push([tree, k]);
 391 |       return trackDown(tree.get(k), key.slice(k.length), path);
 392 |     }
 393 |   }
 394 |   path.push([tree, key]);
 395 |   return trackDown(void 0, "", path);
 396 | };
 397 | var lookup = (tree, key) => {
 398 |   if (key.length === 0 || tree == null) {
 399 |     return tree;
 400 |   }
 401 |   for (const k of tree.keys()) {
 402 |     if (k !== LEAF && key.startsWith(k)) {
 403 |       return lookup(tree.get(k), key.slice(k.length));
 404 |     }
 405 |   }
 406 | };
 407 | var createPath = (node, key) => {
 408 |   const keyLength = key.length;
 409 |   outer: for (let pos = 0; node && pos < keyLength; ) {
 410 |     for (const k of node.keys()) {
 411 |       if (k !== LEAF && key[pos] === k[0]) {
 412 |         const len = Math.min(keyLength - pos, k.length);
 413 |         let offset = 1;
 414 |         while (offset < len && key[pos + offset] === k[offset])
 415 |           ++offset;
 416 |         const child2 = node.get(k);
 417 |         if (offset === k.length) {
 418 |           node = child2;
 419 |         } else {
 420 |           const intermediate = /* @__PURE__ */ new Map();
 421 |           intermediate.set(k.slice(offset), child2);
 422 |           node.set(key.slice(pos, pos + offset), intermediate);
 423 |           node.delete(k);
 424 |           node = intermediate;
 425 |         }
 426 |         pos += offset;
 427 |         continue outer;
 428 |       }
 429 |     }
 430 |     const child = /* @__PURE__ */ new Map();
 431 |     node.set(key.slice(pos), child);
 432 |     return child;
 433 |   }
 434 |   return node;
 435 | };
 436 | var remove = (tree, key) => {
 437 |   const [node, path] = trackDown(tree, key);
 438 |   if (node === void 0) {
 439 |     return;
 440 |   }
 441 |   node.delete(LEAF);
 442 |   if (node.size === 0) {
 443 |     cleanup(path);
 444 |   } else if (node.size === 1) {
 445 |     const [key2, value] = node.entries().next().value;
 446 |     merge(path, key2, value);
 447 |   }
 448 | };
 449 | var cleanup = (path) => {
 450 |   if (path.length === 0) {
 451 |     return;
 452 |   }
 453 |   const [node, key] = last(path);
 454 |   node.delete(key);
 455 |   if (node.size === 0) {
 456 |     cleanup(path.slice(0, -1));
 457 |   } else if (node.size === 1) {
 458 |     const [key2, value] = node.entries().next().value;
 459 |     if (key2 !== LEAF) {
 460 |       merge(path.slice(0, -1), key2, value);
 461 |     }
 462 |   }
 463 | };
 464 | var merge = (path, key, value) => {
 465 |   if (path.length === 0) {
 466 |     return;
 467 |   }
 468 |   const [node, nodeKey] = last(path);
 469 |   node.set(nodeKey + key, value);
 470 |   node.delete(nodeKey);
 471 | };
 472 | var last = (array) => {
 473 |   return array[array.length - 1];
 474 | };
 475 | var OR = "or";
 476 | var AND = "and";
 477 | var AND_NOT = "and_not";
 478 | var MiniSearch = class _MiniSearch {
 479 |   /**
 480 |    * @param options  Configuration options
 481 |    *
 482 |    * ### Examples:
 483 |    *
 484 |    * ```javascript
 485 |    * // Create a search engine that indexes the 'title' and 'text' fields of your
 486 |    * // documents:
 487 |    * const miniSearch = new MiniSearch({ fields: ['title', 'text'] })
 488 |    * ```
 489 |    *
 490 |    * ### ID Field:
 491 |    *
 492 |    * ```javascript
 493 |    * // Your documents are assumed to include a unique 'id' field, but if you want
 494 |    * // to use a different field for document identification, you can set the
 495 |    * // 'idField' option:
 496 |    * const miniSearch = new MiniSearch({ idField: 'key', fields: ['title', 'text'] })
 497 |    * ```
 498 |    *
 499 |    * ### Options and defaults:
 500 |    *
 501 |    * ```javascript
 502 |    * // The full set of options (here with their default value) is:
 503 |    * const miniSearch = new MiniSearch({
 504 |    *   // idField: field that uniquely identifies a document
 505 |    *   idField: 'id',
 506 |    *
 507 |    *   // extractField: function used to get the value of a field in a document.
 508 |    *   // By default, it assumes the document is a flat object with field names as
 509 |    *   // property keys and field values as string property values, but custom logic
 510 |    *   // can be implemented by setting this option to a custom extractor function.
 511 |    *   extractField: (document, fieldName) => document[fieldName],
 512 |    *
 513 |    *   // tokenize: function used to split fields into individual terms. By
 514 |    *   // default, it is also used to tokenize search queries, unless a specific
 515 |    *   // `tokenize` search option is supplied. When tokenizing an indexed field,
 516 |    *   // the field name is passed as the second argument.
 517 |    *   tokenize: (string, _fieldName) => string.split(SPACE_OR_PUNCTUATION),
 518 |    *
 519 |    *   // processTerm: function used to process each tokenized term before
 520 |    *   // indexing. It can be used for stemming and normalization. Return a falsy
 521 |    *   // value in order to discard a term. By default, it is also used to process
 522 |    *   // search queries, unless a specific `processTerm` option is supplied as a
 523 |    *   // search option. When processing a term from a indexed field, the field
 524 |    *   // name is passed as the second argument.
 525 |    *   processTerm: (term, _fieldName) => term.toLowerCase(),
 526 |    *
 527 |    *   // searchOptions: default search options, see the `search` method for
 528 |    *   // details
 529 |    *   searchOptions: undefined,
 530 |    *
 531 |    *   // fields: document fields to be indexed. Mandatory, but not set by default
 532 |    *   fields: undefined
 533 |    *
 534 |    *   // storeFields: document fields to be stored and returned as part of the
 535 |    *   // search results.
 536 |    *   storeFields: []
 537 |    * })
 538 |    * ```
 539 |    */
 540 |   constructor(options) {
 541 |     if ((options === null || options === void 0 ? void 0 : options.fields) == null) {
 542 |       throw new Error('MiniSearch: option "fields" must be provided');
 543 |     }
 544 |     const autoVacuum = options.autoVacuum == null || options.autoVacuum === true ? defaultAutoVacuumOptions : options.autoVacuum;
 545 |     this._options = {
 546 |       ...defaultOptions,
 547 |       ...options,
 548 |       autoVacuum,
 549 |       searchOptions: { ...defaultSearchOptions, ...options.searchOptions || {} },
 550 |       autoSuggestOptions: { ...defaultAutoSuggestOptions, ...options.autoSuggestOptions || {} }
 551 |     };
 552 |     this._index = new SearchableMap();
 553 |     this._documentCount = 0;
 554 |     this._documentIds = /* @__PURE__ */ new Map();
 555 |     this._idToShortId = /* @__PURE__ */ new Map();
 556 |     this._fieldIds = {};
 557 |     this._fieldLength = /* @__PURE__ */ new Map();
 558 |     this._avgFieldLength = [];
 559 |     this._nextId = 0;
 560 |     this._storedFields = /* @__PURE__ */ new Map();
 561 |     this._dirtCount = 0;
 562 |     this._currentVacuum = null;
 563 |     this._enqueuedVacuum = null;
 564 |     this._enqueuedVacuumConditions = defaultVacuumConditions;
 565 |     this.addFields(this._options.fields);
 566 |   }
 567 |   /**
 568 |    * Adds a document to the index
 569 |    *
 570 |    * @param document  The document to be indexed
 571 |    */
 572 |   add(document) {
 573 |     const { extractField, tokenize, processTerm, fields, idField } = this._options;
 574 |     const id = extractField(document, idField);
 575 |     if (id == null) {
 576 |       throw new Error(`MiniSearch: document does not have ID field "${idField}"`);
 577 |     }
 578 |     if (this._idToShortId.has(id)) {
 579 |       throw new Error(`MiniSearch: duplicate ID ${id}`);
 580 |     }
 581 |     const shortDocumentId = this.addDocumentId(id);
 582 |     this.saveStoredFields(shortDocumentId, document);
 583 |     for (const field of fields) {
 584 |       const fieldValue = extractField(document, field);
 585 |       if (fieldValue == null)
 586 |         continue;
 587 |       const tokens = tokenize(fieldValue.toString(), field);
 588 |       const fieldId = this._fieldIds[field];
 589 |       const uniqueTerms = new Set(tokens).size;
 590 |       this.addFieldLength(shortDocumentId, fieldId, this._documentCount - 1, uniqueTerms);
 591 |       for (const term of tokens) {
 592 |         const processedTerm = processTerm(term, field);
 593 |         if (Array.isArray(processedTerm)) {
 594 |           for (const t of processedTerm) {
 595 |             this.addTerm(fieldId, shortDocumentId, t);
 596 |           }
 597 |         } else if (processedTerm) {
 598 |           this.addTerm(fieldId, shortDocumentId, processedTerm);
 599 |         }
 600 |       }
 601 |     }
 602 |   }
 603 |   /**
 604 |    * Adds all the given documents to the index
 605 |    *
 606 |    * @param documents  An array of documents to be indexed
 607 |    */
 608 |   addAll(documents) {
 609 |     for (const document of documents)
 610 |       this.add(document);
 611 |   }
 612 |   /**
 613 |    * Adds all the given documents to the index asynchronously.
 614 |    *
 615 |    * Returns a promise that resolves (to `undefined`) when the indexing is done.
 616 |    * This method is useful when index many documents, to avoid blocking the main
 617 |    * thread. The indexing is performed asynchronously and in chunks.
 618 |    *
 619 |    * @param documents  An array of documents to be indexed
 620 |    * @param options  Configuration options
 621 |    * @return A promise resolving to `undefined` when the indexing is done
 622 |    */
 623 |   addAllAsync(documents, options = {}) {
 624 |     const { chunkSize = 10 } = options;
 625 |     const acc = { chunk: [], promise: Promise.resolve() };
 626 |     const { chunk, promise } = documents.reduce(({ chunk: chunk2, promise: promise2 }, document, i) => {
 627 |       chunk2.push(document);
 628 |       if ((i + 1) % chunkSize === 0) {
 629 |         return {
 630 |           chunk: [],
 631 |           promise: promise2.then(() => new Promise((resolve) => setTimeout(resolve, 0))).then(() => this.addAll(chunk2))
 632 |         };
 633 |       } else {
 634 |         return { chunk: chunk2, promise: promise2 };
 635 |       }
 636 |     }, acc);
 637 |     return promise.then(() => this.addAll(chunk));
 638 |   }
 639 |   /**
 640 |    * Removes the given document from the index.
 641 |    *
 642 |    * The document to remove must NOT have changed between indexing and removal,
 643 |    * otherwise the index will be corrupted.
 644 |    *
 645 |    * This method requires passing the full document to be removed (not just the
 646 |    * ID), and immediately removes the document from the inverted index, allowing
 647 |    * memory to be released. A convenient alternative is {@link
 648 |    * MiniSearch#discard}, which needs only the document ID, and has the same
 649 |    * visible effect, but delays cleaning up the index until the next vacuuming.
 650 |    *
 651 |    * @param document  The document to be removed
 652 |    */
 653 |   remove(document) {
 654 |     const { tokenize, processTerm, extractField, fields, idField } = this._options;
 655 |     const id = extractField(document, idField);
 656 |     if (id == null) {
 657 |       throw new Error(`MiniSearch: document does not have ID field "${idField}"`);
 658 |     }
 659 |     const shortId = this._idToShortId.get(id);
 660 |     if (shortId == null) {
 661 |       throw new Error(`MiniSearch: cannot remove document with ID ${id}: it is not in the index`);
 662 |     }
 663 |     for (const field of fields) {
 664 |       const fieldValue = extractField(document, field);
 665 |       if (fieldValue == null)
 666 |         continue;
 667 |       const tokens = tokenize(fieldValue.toString(), field);
 668 |       const fieldId = this._fieldIds[field];
 669 |       const uniqueTerms = new Set(tokens).size;
 670 |       this.removeFieldLength(shortId, fieldId, this._documentCount, uniqueTerms);
 671 |       for (const term of tokens) {
 672 |         const processedTerm = processTerm(term, field);
 673 |         if (Array.isArray(processedTerm)) {
 674 |           for (const t of processedTerm) {
 675 |             this.removeTerm(fieldId, shortId, t);
 676 |           }
 677 |         } else if (processedTerm) {
 678 |           this.removeTerm(fieldId, shortId, processedTerm);
 679 |         }
 680 |       }
 681 |     }
 682 |     this._storedFields.delete(shortId);
 683 |     this._documentIds.delete(shortId);
 684 |     this._idToShortId.delete(id);
 685 |     this._fieldLength.delete(shortId);
 686 |     this._documentCount -= 1;
 687 |   }
 688 |   /**
 689 |    * Removes all the given documents from the index. If called with no arguments,
 690 |    * it removes _all_ documents from the index.
 691 |    *
 692 |    * @param documents  The documents to be removed. If this argument is omitted,
 693 |    * all documents are removed. Note that, for removing all documents, it is
 694 |    * more efficient to call this method with no arguments than to pass all
 695 |    * documents.
 696 |    */
 697 |   removeAll(documents) {
 698 |     if (documents) {
 699 |       for (const document of documents)
 700 |         this.remove(document);
 701 |     } else if (arguments.length > 0) {
 702 |       throw new Error("Expected documents to be present. Omit the argument to remove all documents.");
 703 |     } else {
 704 |       this._index = new SearchableMap();
 705 |       this._documentCount = 0;
 706 |       this._documentIds = /* @__PURE__ */ new Map();
 707 |       this._idToShortId = /* @__PURE__ */ new Map();
 708 |       this._fieldLength = /* @__PURE__ */ new Map();
 709 |       this._avgFieldLength = [];
 710 |       this._storedFields = /* @__PURE__ */ new Map();
 711 |       this._nextId = 0;
 712 |     }
 713 |   }
 714 |   /**
 715 |    * Discards the document with the given ID, so it won't appear in search results
 716 |    *
 717 |    * It has the same visible effect of {@link MiniSearch.remove} (both cause the
 718 |    * document to stop appearing in searches), but a different effect on the
 719 |    * internal data structures:
 720 |    *
 721 |    *   - {@link MiniSearch#remove} requires passing the full document to be
 722 |    *   removed as argument, and removes it from the inverted index immediately.
 723 |    *
 724 |    *   - {@link MiniSearch#discard} instead only needs the document ID, and
 725 |    *   works by marking the current version of the document as discarded, so it
 726 |    *   is immediately ignored by searches. This is faster and more convenient
 727 |    *   than {@link MiniSearch#remove}, but the index is not immediately
 728 |    *   modified. To take care of that, vacuuming is performed after a certain
 729 |    *   number of documents are discarded, cleaning up the index and allowing
 730 |    *   memory to be released.
 731 |    *
 732 |    * After discarding a document, it is possible to re-add a new version, and
 733 |    * only the new version will appear in searches. In other words, discarding
 734 |    * and re-adding a document works exactly like removing and re-adding it. The
 735 |    * {@link MiniSearch.replace} method can also be used to replace a document
 736 |    * with a new version.
 737 |    *
 738 |    * #### Details about vacuuming
 739 |    *
 740 |    * Repetite calls to this method would leave obsolete document references in
 741 |    * the index, invisible to searches. Two mechanisms take care of cleaning up:
 742 |    * clean up during search, and vacuuming.
 743 |    *
 744 |    *   - Upon search, whenever a discarded ID is found (and ignored for the
 745 |    *   results), references to the discarded document are removed from the
 746 |    *   inverted index entries for the search terms. This ensures that subsequent
 747 |    *   searches for the same terms do not need to skip these obsolete references
 748 |    *   again.
 749 |    *
 750 |    *   - In addition, vacuuming is performed automatically by default (see the
 751 |    *   `autoVacuum` field in {@link Options}) after a certain number of
 752 |    *   documents are discarded. Vacuuming traverses all terms in the index,
 753 |    *   cleaning up all references to discarded documents. Vacuuming can also be
 754 |    *   triggered manually by calling {@link MiniSearch#vacuum}.
 755 |    *
 756 |    * @param id  The ID of the document to be discarded
 757 |    */
 758 |   discard(id) {
 759 |     const shortId = this._idToShortId.get(id);
 760 |     if (shortId == null) {
 761 |       throw new Error(`MiniSearch: cannot discard document with ID ${id}: it is not in the index`);
 762 |     }
 763 |     this._idToShortId.delete(id);
 764 |     this._documentIds.delete(shortId);
 765 |     this._storedFields.delete(shortId);
 766 |     (this._fieldLength.get(shortId) || []).forEach((fieldLength, fieldId) => {
 767 |       this.removeFieldLength(shortId, fieldId, this._documentCount, fieldLength);
 768 |     });
 769 |     this._fieldLength.delete(shortId);
 770 |     this._documentCount -= 1;
 771 |     this._dirtCount += 1;
 772 |     this.maybeAutoVacuum();
 773 |   }
 774 |   maybeAutoVacuum() {
 775 |     if (this._options.autoVacuum === false) {
 776 |       return;
 777 |     }
 778 |     const { minDirtFactor, minDirtCount, batchSize, batchWait } = this._options.autoVacuum;
 779 |     this.conditionalVacuum({ batchSize, batchWait }, { minDirtCount, minDirtFactor });
 780 |   }
 781 |   /**
 782 |    * Discards the documents with the given IDs, so they won't appear in search
 783 |    * results
 784 |    *
 785 |    * It is equivalent to calling {@link MiniSearch#discard} for all the given
 786 |    * IDs, but with the optimization of triggering at most one automatic
 787 |    * vacuuming at the end.
 788 |    *
 789 |    * Note: to remove all documents from the index, it is faster and more
 790 |    * convenient to call {@link MiniSearch.removeAll} with no argument, instead
 791 |    * of passing all IDs to this method.
 792 |    */
 793 |   discardAll(ids) {
 794 |     const autoVacuum = this._options.autoVacuum;
 795 |     try {
 796 |       this._options.autoVacuum = false;
 797 |       for (const id of ids) {
 798 |         this.discard(id);
 799 |       }
 800 |     } finally {
 801 |       this._options.autoVacuum = autoVacuum;
 802 |     }
 803 |     this.maybeAutoVacuum();
 804 |   }
 805 |   /**
 806 |    * It replaces an existing document with the given updated version
 807 |    *
 808 |    * It works by discarding the current version and adding the updated one, so
 809 |    * it is functionally equivalent to calling {@link MiniSearch#discard}
 810 |    * followed by {@link MiniSearch#add}. The ID of the updated document should
 811 |    * be the same as the original one.
 812 |    *
 813 |    * Since it uses {@link MiniSearch#discard} internally, this method relies on
 814 |    * vacuuming to clean up obsolete document references from the index, allowing
 815 |    * memory to be released (see {@link MiniSearch#discard}).
 816 |    *
 817 |    * @param updatedDocument  The updated document to replace the old version
 818 |    * with
 819 |    */
 820 |   replace(updatedDocument) {
 821 |     const { idField, extractField } = this._options;
 822 |     const id = extractField(updatedDocument, idField);
 823 |     this.discard(id);
 824 |     this.add(updatedDocument);
 825 |   }
 826 |   /**
 827 |    * Triggers a manual vacuuming, cleaning up references to discarded documents
 828 |    * from the inverted index
 829 |    *
 830 |    * Vacuuming is only useful for applications that use the {@link
 831 |    * MiniSearch#discard} or {@link MiniSearch#replace} methods.
 832 |    *
 833 |    * By default, vacuuming is performed automatically when needed (controlled by
 834 |    * the `autoVacuum` field in {@link Options}), so there is usually no need to
 835 |    * call this method, unless one wants to make sure to perform vacuuming at a
 836 |    * specific moment.
 837 |    *
 838 |    * Vacuuming traverses all terms in the inverted index in batches, and cleans
 839 |    * up references to discarded documents from the posting list, allowing memory
 840 |    * to be released.
 841 |    *
 842 |    * The method takes an optional object as argument with the following keys:
 843 |    *
 844 |    *   - `batchSize`: the size of each batch (1000 by default)
 845 |    *
 846 |    *   - `batchWait`: the number of milliseconds to wait between batches (10 by
 847 |    *   default)
 848 |    *
 849 |    * On large indexes, vacuuming could have a non-negligible cost: batching
 850 |    * avoids blocking the thread for long, diluting this cost so that it is not
 851 |    * negatively affecting the application. Nonetheless, this method should only
 852 |    * be called when necessary, and relying on automatic vacuuming is usually
 853 |    * better.
 854 |    *
 855 |    * It returns a promise that resolves (to undefined) when the clean up is
 856 |    * completed. If vacuuming is already ongoing at the time this method is
 857 |    * called, a new one is enqueued immediately after the ongoing one, and a
 858 |    * corresponding promise is returned. However, no more than one vacuuming is
 859 |    * enqueued on top of the ongoing one, even if this method is called more
 860 |    * times (enqueuing multiple ones would be useless).
 861 |    *
 862 |    * @param options  Configuration options for the batch size and delay. See
 863 |    * {@link VacuumOptions}.
 864 |    */
 865 |   vacuum(options = {}) {
 866 |     return this.conditionalVacuum(options);
 867 |   }
 868 |   conditionalVacuum(options, conditions) {
 869 |     if (this._currentVacuum) {
 870 |       this._enqueuedVacuumConditions = this._enqueuedVacuumConditions && conditions;
 871 |       if (this._enqueuedVacuum != null) {
 872 |         return this._enqueuedVacuum;
 873 |       }
 874 |       this._enqueuedVacuum = this._currentVacuum.then(() => {
 875 |         const conditions2 = this._enqueuedVacuumConditions;
 876 |         this._enqueuedVacuumConditions = defaultVacuumConditions;
 877 |         return this.performVacuuming(options, conditions2);
 878 |       });
 879 |       return this._enqueuedVacuum;
 880 |     }
 881 |     if (this.vacuumConditionsMet(conditions) === false) {
 882 |       return Promise.resolve();
 883 |     }
 884 |     this._currentVacuum = this.performVacuuming(options);
 885 |     return this._currentVacuum;
 886 |   }
 887 |   async performVacuuming(options, conditions) {
 888 |     const initialDirtCount = this._dirtCount;
 889 |     if (this.vacuumConditionsMet(conditions)) {
 890 |       const batchSize = options.batchSize || defaultVacuumOptions.batchSize;
 891 |       const batchWait = options.batchWait || defaultVacuumOptions.batchWait;
 892 |       let i = 1;
 893 |       for (const [term, fieldsData] of this._index) {
 894 |         for (const [fieldId, fieldIndex] of fieldsData) {
 895 |           for (const [shortId] of fieldIndex) {
 896 |             if (this._documentIds.has(shortId)) {
 897 |               continue;
 898 |             }
 899 |             if (fieldIndex.size <= 1) {
 900 |               fieldsData.delete(fieldId);
 901 |             } else {
 902 |               fieldIndex.delete(shortId);
 903 |             }
 904 |           }
 905 |         }
 906 |         if (this._index.get(term).size === 0) {
 907 |           this._index.delete(term);
 908 |         }
 909 |         if (i % batchSize === 0) {
 910 |           await new Promise((resolve) => setTimeout(resolve, batchWait));
 911 |         }
 912 |         i += 1;
 913 |       }
 914 |       this._dirtCount -= initialDirtCount;
 915 |     }
 916 |     await null;
 917 |     this._currentVacuum = this._enqueuedVacuum;
 918 |     this._enqueuedVacuum = null;
 919 |   }
 920 |   vacuumConditionsMet(conditions) {
 921 |     if (conditions == null) {
 922 |       return true;
 923 |     }
 924 |     let { minDirtCount, minDirtFactor } = conditions;
 925 |     minDirtCount = minDirtCount || defaultAutoVacuumOptions.minDirtCount;
 926 |     minDirtFactor = minDirtFactor || defaultAutoVacuumOptions.minDirtFactor;
 927 |     return this.dirtCount >= minDirtCount && this.dirtFactor >= minDirtFactor;
 928 |   }
 929 |   /**
 930 |    * Is `true` if a vacuuming operation is ongoing, `false` otherwise
 931 |    */
 932 |   get isVacuuming() {
 933 |     return this._currentVacuum != null;
 934 |   }
 935 |   /**
 936 |    * The number of documents discarded since the most recent vacuuming
 937 |    */
 938 |   get dirtCount() {
 939 |     return this._dirtCount;
 940 |   }
 941 |   /**
 942 |    * A number between 0 and 1 giving an indication about the proportion of
 943 |    * documents that are discarded, and can therefore be cleaned up by vacuuming.
 944 |    * A value close to 0 means that the index is relatively clean, while a higher
 945 |    * value means that the index is relatively dirty, and vacuuming could release
 946 |    * memory.
 947 |    */
 948 |   get dirtFactor() {
 949 |     return this._dirtCount / (1 + this._documentCount + this._dirtCount);
 950 |   }
 951 |   /**
 952 |    * Returns `true` if a document with the given ID is present in the index and
 953 |    * available for search, `false` otherwise
 954 |    *
 955 |    * @param id  The document ID
 956 |    */
 957 |   has(id) {
 958 |     return this._idToShortId.has(id);
 959 |   }
 960 |   /**
 961 |    * Returns the stored fields (as configured in the `storeFields` constructor
 962 |    * option) for the given document ID. Returns `undefined` if the document is
 963 |    * not present in the index.
 964 |    *
 965 |    * @param id  The document ID
 966 |    */
 967 |   getStoredFields(id) {
 968 |     const shortId = this._idToShortId.get(id);
 969 |     if (shortId == null) {
 970 |       return void 0;
 971 |     }
 972 |     return this._storedFields.get(shortId);
 973 |   }
 974 |   /**
 975 |    * Search for documents matching the given search query.
 976 |    *
 977 |    * The result is a list of scored document IDs matching the query, sorted by
 978 |    * descending score, and each including data about which terms were matched and
 979 |    * in which fields.
 980 |    *
 981 |    * ### Basic usage:
 982 |    *
 983 |    * ```javascript
 984 |    * // Search for "zen art motorcycle" with default options: terms have to match
 985 |    * // exactly, and individual terms are joined with OR
 986 |    * miniSearch.search('zen art motorcycle')
 987 |    * // => [ { id: 2, score: 2.77258, match: { ... } }, { id: 4, score: 1.38629, match: { ... } } ]
 988 |    * ```
 989 |    *
 990 |    * ### Restrict search to specific fields:
 991 |    *
 992 |    * ```javascript
 993 |    * // Search only in the 'title' field
 994 |    * miniSearch.search('zen', { fields: ['title'] })
 995 |    * ```
 996 |    *
 997 |    * ### Field boosting:
 998 |    *
 999 |    * ```javascript
1000 |    * // Boost a field
1001 |    * miniSearch.search('zen', { boost: { title: 2 } })
1002 |    * ```
1003 |    *
1004 |    * ### Prefix search:
1005 |    *
1006 |    * ```javascript
1007 |    * // Search for "moto" with prefix search (it will match documents
1008 |    * // containing terms that start with "moto" or "neuro")
1009 |    * miniSearch.search('moto neuro', { prefix: true })
1010 |    * ```
1011 |    *
1012 |    * ### Fuzzy search:
1013 |    *
1014 |    * ```javascript
1015 |    * // Search for "ismael" with fuzzy search (it will match documents containing
1016 |    * // terms similar to "ismael", with a maximum edit distance of 0.2 term.length
1017 |    * // (rounded to nearest integer)
1018 |    * miniSearch.search('ismael', { fuzzy: 0.2 })
1019 |    * ```
1020 |    *
1021 |    * ### Combining strategies:
1022 |    *
1023 |    * ```javascript
1024 |    * // Mix of exact match, prefix search, and fuzzy search
1025 |    * miniSearch.search('ismael mob', {
1026 |    *  prefix: true,
1027 |    *  fuzzy: 0.2
1028 |    * })
1029 |    * ```
1030 |    *
1031 |    * ### Advanced prefix and fuzzy search:
1032 |    *
1033 |    * ```javascript
1034 |    * // Perform fuzzy and prefix search depending on the search term. Here
1035 |    * // performing prefix and fuzzy search only on terms longer than 3 characters
1036 |    * miniSearch.search('ismael mob', {
1037 |    *  prefix: term => term.length > 3
1038 |    *  fuzzy: term => term.length > 3 ? 0.2 : null
1039 |    * })
1040 |    * ```
1041 |    *
1042 |    * ### Combine with AND:
1043 |    *
1044 |    * ```javascript
1045 |    * // Combine search terms with AND (to match only documents that contain both
1046 |    * // "motorcycle" and "art")
1047 |    * miniSearch.search('motorcycle art', { combineWith: 'AND' })
1048 |    * ```
1049 |    *
1050 |    * ### Combine with AND_NOT:
1051 |    *
1052 |    * There is also an AND_NOT combinator, that finds documents that match the
1053 |    * first term, but do not match any of the other terms. This combinator is
1054 |    * rarely useful with simple queries, and is meant to be used with advanced
1055 |    * query combinations (see later for more details).
1056 |    *
1057 |    * ### Filtering results:
1058 |    *
1059 |    * ```javascript
1060 |    * // Filter only results in the 'fiction' category (assuming that 'category'
1061 |    * // is a stored field)
1062 |    * miniSearch.search('motorcycle art', {
1063 |    *   filter: (result) => result.category === 'fiction'
1064 |    * })
1065 |    * ```
1066 |    *
1067 |    * ### Wildcard query
1068 |    *
1069 |    * Searching for an empty string (assuming the default tokenizer) returns no
1070 |    * results. Sometimes though, one needs to match all documents, like in a
1071 |    * "wildcard" search. This is possible by passing the special value
1072 |    * {@link MiniSearch.wildcard} as the query:
1073 |    *
1074 |    * ```javascript
1075 |    * // Return search results for all documents
1076 |    * miniSearch.search(MiniSearch.wildcard)
1077 |    * ```
1078 |    *
1079 |    * Note that search options such as `filter` and `boostDocument` are still
1080 |    * applied, influencing which results are returned, and their order:
1081 |    *
1082 |    * ```javascript
1083 |    * // Return search results for all documents in the 'fiction' category
1084 |    * miniSearch.search(MiniSearch.wildcard, {
1085 |    *   filter: (result) => result.category === 'fiction'
1086 |    * })
1087 |    * ```
1088 |    *
1089 |    * ### Advanced combination of queries:
1090 |    *
1091 |    * It is possible to combine different subqueries with OR, AND, and AND_NOT,
1092 |    * and even with different search options, by passing a query expression
1093 |    * tree object as the first argument, instead of a string.
1094 |    *
1095 |    * ```javascript
1096 |    * // Search for documents that contain "zen" and ("motorcycle" or "archery")
1097 |    * miniSearch.search({
1098 |    *   combineWith: 'AND',
1099 |    *   queries: [
1100 |    *     'zen',
1101 |    *     {
1102 |    *       combineWith: 'OR',
1103 |    *       queries: ['motorcycle', 'archery']
1104 |    *     }
1105 |    *   ]
1106 |    * })
1107 |    *
1108 |    * // Search for documents that contain ("apple" or "pear") but not "juice" and
1109 |    * // not "tree"
1110 |    * miniSearch.search({
1111 |    *   combineWith: 'AND_NOT',
1112 |    *   queries: [
1113 |    *     {
1114 |    *       combineWith: 'OR',
1115 |    *       queries: ['apple', 'pear']
1116 |    *     },
1117 |    *     'juice',
1118 |    *     'tree'
1119 |    *   ]
1120 |    * })
1121 |    * ```
1122 |    *
1123 |    * Each node in the expression tree can be either a string, or an object that
1124 |    * supports all {@link SearchOptions} fields, plus a `queries` array field for
1125 |    * subqueries.
1126 |    *
1127 |    * Note that, while this can become complicated to do by hand for complex or
1128 |    * deeply nested queries, it provides a formalized expression tree API for
1129 |    * external libraries that implement a parser for custom query languages.
1130 |    *
1131 |    * @param query  Search query
1132 |    * @param searchOptions  Search options. Each option, if not given, defaults to the corresponding value of `searchOptions` given to the constructor, or to the library default.
1133 |    */
1134 |   search(query, searchOptions = {}) {
1135 |     const { searchOptions: globalSearchOptions } = this._options;
1136 |     const searchOptionsWithDefaults = { ...globalSearchOptions, ...searchOptions };
1137 |     const rawResults = this.executeQuery(query, searchOptions);
1138 |     const results = [];
1139 |     for (const [docId, { score, terms, match }] of rawResults) {
1140 |       const quality = terms.length || 1;
1141 |       const result = {
1142 |         id: this._documentIds.get(docId),
1143 |         score: score * quality,
1144 |         terms: Object.keys(match),
1145 |         queryTerms: terms,
1146 |         match
1147 |       };
1148 |       Object.assign(result, this._storedFields.get(docId));
1149 |       if (searchOptionsWithDefaults.filter == null || searchOptionsWithDefaults.filter(result)) {
1150 |         results.push(result);
1151 |       }
1152 |     }
1153 |     if (query === _MiniSearch.wildcard && searchOptionsWithDefaults.boostDocument == null) {
1154 |       return results;
1155 |     }
1156 |     results.sort(byScore);
1157 |     return results;
1158 |   }
1159 |   /**
1160 |    * Provide suggestions for the given search query
1161 |    *
1162 |    * The result is a list of suggested modified search queries, derived from the
1163 |    * given search query, each with a relevance score, sorted by descending score.
1164 |    *
1165 |    * By default, it uses the same options used for search, except that by
1166 |    * default it performs prefix search on the last term of the query, and
1167 |    * combine terms with `'AND'` (requiring all query terms to match). Custom
1168 |    * options can be passed as a second argument. Defaults can be changed upon
1169 |    * calling the {@link MiniSearch} constructor, by passing a
1170 |    * `autoSuggestOptions` option.
1171 |    *
1172 |    * ### Basic usage:
1173 |    *
1174 |    * ```javascript
1175 |    * // Get suggestions for 'neuro':
1176 |    * miniSearch.autoSuggest('neuro')
1177 |    * // => [ { suggestion: 'neuromancer', terms: [ 'neuromancer' ], score: 0.46240 } ]
1178 |    * ```
1179 |    *
1180 |    * ### Multiple words:
1181 |    *
1182 |    * ```javascript
1183 |    * // Get suggestions for 'zen ar':
1184 |    * miniSearch.autoSuggest('zen ar')
1185 |    * // => [
1186 |    * //  { suggestion: 'zen archery art', terms: [ 'zen', 'archery', 'art' ], score: 1.73332 },
1187 |    * //  { suggestion: 'zen art', terms: [ 'zen', 'art' ], score: 1.21313 }
1188 |    * // ]
1189 |    * ```
1190 |    *
1191 |    * ### Fuzzy suggestions:
1192 |    *
1193 |    * ```javascript
1194 |    * // Correct spelling mistakes using fuzzy search:
1195 |    * miniSearch.autoSuggest('neromancer', { fuzzy: 0.2 })
1196 |    * // => [ { suggestion: 'neuromancer', terms: [ 'neuromancer' ], score: 1.03998 } ]
1197 |    * ```
1198 |    *
1199 |    * ### Filtering:
1200 |    *
1201 |    * ```javascript
1202 |    * // Get suggestions for 'zen ar', but only within the 'fiction' category
1203 |    * // (assuming that 'category' is a stored field):
1204 |    * miniSearch.autoSuggest('zen ar', {
1205 |    *   filter: (result) => result.category === 'fiction'
1206 |    * })
1207 |    * // => [
1208 |    * //  { suggestion: 'zen archery art', terms: [ 'zen', 'archery', 'art' ], score: 1.73332 },
1209 |    * //  { suggestion: 'zen art', terms: [ 'zen', 'art' ], score: 1.21313 }
1210 |    * // ]
1211 |    * ```
1212 |    *
1213 |    * @param queryString  Query string to be expanded into suggestions
1214 |    * @param options  Search options. The supported options and default values
1215 |    * are the same as for the {@link MiniSearch#search} method, except that by
1216 |    * default prefix search is performed on the last term in the query, and terms
1217 |    * are combined with `'AND'`.
1218 |    * @return  A sorted array of suggestions sorted by relevance score.
1219 |    */
1220 |   autoSuggest(queryString, options = {}) {
1221 |     options = { ...this._options.autoSuggestOptions, ...options };
1222 |     const suggestions = /* @__PURE__ */ new Map();
1223 |     for (const { score, terms } of this.search(queryString, options)) {
1224 |       const phrase = terms.join(" ");
1225 |       const suggestion = suggestions.get(phrase);
1226 |       if (suggestion != null) {
1227 |         suggestion.score += score;
1228 |         suggestion.count += 1;
1229 |       } else {
1230 |         suggestions.set(phrase, { score, terms, count: 1 });
1231 |       }
1232 |     }
1233 |     const results = [];
1234 |     for (const [suggestion, { score, terms, count }] of suggestions) {
1235 |       results.push({ suggestion, terms, score: score / count });
1236 |     }
1237 |     results.sort(byScore);
1238 |     return results;
1239 |   }
1240 |   /**
1241 |    * Total number of documents available to search
1242 |    */
1243 |   get documentCount() {
1244 |     return this._documentCount;
1245 |   }
1246 |   /**
1247 |    * Number of terms in the index
1248 |    */
1249 |   get termCount() {
1250 |     return this._index.size;
1251 |   }
1252 |   /**
1253 |    * Deserializes a JSON index (serialized with `JSON.stringify(miniSearch)`)
1254 |    * and instantiates a MiniSearch instance. It should be given the same options
1255 |    * originally used when serializing the index.
1256 |    *
1257 |    * ### Usage:
1258 |    *
1259 |    * ```javascript
1260 |    * // If the index was serialized with:
1261 |    * let miniSearch = new MiniSearch({ fields: ['title', 'text'] })
1262 |    * miniSearch.addAll(documents)
1263 |    *
1264 |    * const json = JSON.stringify(miniSearch)
1265 |    * // It can later be deserialized like this:
1266 |    * miniSearch = MiniSearch.loadJSON(json, { fields: ['title', 'text'] })
1267 |    * ```
1268 |    *
1269 |    * @param json  JSON-serialized index
1270 |    * @param options  configuration options, same as the constructor
1271 |    * @return An instance of MiniSearch deserialized from the given JSON.
1272 |    */
1273 |   static loadJSON(json, options) {
1274 |     if (options == null) {
1275 |       throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");
1276 |     }
1277 |     return this.loadJS(JSON.parse(json), options);
1278 |   }
1279 |   /**
1280 |    * Async equivalent of {@link MiniSearch.loadJSON}
1281 |    *
1282 |    * This function is an alternative to {@link MiniSearch.loadJSON} that returns
1283 |    * a promise, and loads the index in batches, leaving pauses between them to avoid
1284 |    * blocking the main thread. It tends to be slower than the synchronous
1285 |    * version, but does not block the main thread, so it can be a better choice
1286 |    * when deserializing very large indexes.
1287 |    *
1288 |    * @param json  JSON-serialized index
1289 |    * @param options  configuration options, same as the constructor
1290 |    * @return A Promise that will resolve to an instance of MiniSearch deserialized from the given JSON.
1291 |    */
1292 |   static async loadJSONAsync(json, options) {
1293 |     if (options == null) {
1294 |       throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");
1295 |     }
1296 |     return this.loadJSAsync(JSON.parse(json), options);
1297 |   }
1298 |   /**
1299 |    * Returns the default value of an option. It will throw an error if no option
1300 |    * with the given name exists.
1301 |    *
1302 |    * @param optionName  Name of the option
1303 |    * @return The default value of the given option
1304 |    *
1305 |    * ### Usage:
1306 |    *
1307 |    * ```javascript
1308 |    * // Get default tokenizer
1309 |    * MiniSearch.getDefault('tokenize')
1310 |    *
1311 |    * // Get default term processor
1312 |    * MiniSearch.getDefault('processTerm')
1313 |    *
1314 |    * // Unknown options will throw an error
1315 |    * MiniSearch.getDefault('notExisting')
1316 |    * // => throws 'MiniSearch: unknown option "notExisting"'
1317 |    * ```
1318 |    */
1319 |   static getDefault(optionName) {
1320 |     if (defaultOptions.hasOwnProperty(optionName)) {
1321 |       return getOwnProperty(defaultOptions, optionName);
1322 |     } else {
1323 |       throw new Error(`MiniSearch: unknown option "${optionName}"`);
1324 |     }
1325 |   }
1326 |   /**
1327 |    * @ignore
1328 |    */
1329 |   static loadJS(js, options) {
1330 |     const { index, documentIds, fieldLength, storedFields, serializationVersion } = js;
1331 |     const miniSearch = this.instantiateMiniSearch(js, options);
1332 |     miniSearch._documentIds = objectToNumericMap(documentIds);
1333 |     miniSearch._fieldLength = objectToNumericMap(fieldLength);
1334 |     miniSearch._storedFields = objectToNumericMap(storedFields);
1335 |     for (const [shortId, id] of miniSearch._documentIds) {
1336 |       miniSearch._idToShortId.set(id, shortId);
1337 |     }
1338 |     for (const [term, data] of index) {
1339 |       const dataMap = /* @__PURE__ */ new Map();
1340 |       for (const fieldId of Object.keys(data)) {
1341 |         let indexEntry = data[fieldId];
1342 |         if (serializationVersion === 1) {
1343 |           indexEntry = indexEntry.ds;
1344 |         }
1345 |         dataMap.set(parseInt(fieldId, 10), objectToNumericMap(indexEntry));
1346 |       }
1347 |       miniSearch._index.set(term, dataMap);
1348 |     }
1349 |     return miniSearch;
1350 |   }
1351 |   /**
1352 |    * @ignore
1353 |    */
1354 |   static async loadJSAsync(js, options) {
1355 |     const { index, documentIds, fieldLength, storedFields, serializationVersion } = js;
1356 |     const miniSearch = this.instantiateMiniSearch(js, options);
1357 |     miniSearch._documentIds = await objectToNumericMapAsync(documentIds);
1358 |     miniSearch._fieldLength = await objectToNumericMapAsync(fieldLength);
1359 |     miniSearch._storedFields = await objectToNumericMapAsync(storedFields);
1360 |     for (const [shortId, id] of miniSearch._documentIds) {
1361 |       miniSearch._idToShortId.set(id, shortId);
1362 |     }
1363 |     let count = 0;
1364 |     for (const [term, data] of index) {
1365 |       const dataMap = /* @__PURE__ */ new Map();
1366 |       for (const fieldId of Object.keys(data)) {
1367 |         let indexEntry = data[fieldId];
1368 |         if (serializationVersion === 1) {
1369 |           indexEntry = indexEntry.ds;
1370 |         }
1371 |         dataMap.set(parseInt(fieldId, 10), await objectToNumericMapAsync(indexEntry));
1372 |       }
1373 |       if (++count % 1e3 === 0)
1374 |         await wait(0);
1375 |       miniSearch._index.set(term, dataMap);
1376 |     }
1377 |     return miniSearch;
1378 |   }
1379 |   /**
1380 |    * @ignore
1381 |    */
1382 |   static instantiateMiniSearch(js, options) {
1383 |     const { documentCount, nextId, fieldIds, averageFieldLength, dirtCount, serializationVersion } = js;
1384 |     if (serializationVersion !== 1 && serializationVersion !== 2) {
1385 |       throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");
1386 |     }
1387 |     const miniSearch = new _MiniSearch(options);
1388 |     miniSearch._documentCount = documentCount;
1389 |     miniSearch._nextId = nextId;
1390 |     miniSearch._idToShortId = /* @__PURE__ */ new Map();
1391 |     miniSearch._fieldIds = fieldIds;
1392 |     miniSearch._avgFieldLength = averageFieldLength;
1393 |     miniSearch._dirtCount = dirtCount || 0;
1394 |     miniSearch._index = new SearchableMap();
1395 |     return miniSearch;
1396 |   }
1397 |   /**
1398 |    * @ignore
1399 |    */
1400 |   executeQuery(query, searchOptions = {}) {
1401 |     if (query === _MiniSearch.wildcard) {
1402 |       return this.executeWildcardQuery(searchOptions);
1403 |     }
1404 |     if (typeof query !== "string") {
1405 |       const options2 = { ...searchOptions, ...query, queries: void 0 };
1406 |       const results2 = query.queries.map((subquery) => this.executeQuery(subquery, options2));
1407 |       return this.combineResults(results2, options2.combineWith);
1408 |     }
1409 |     const { tokenize, processTerm, searchOptions: globalSearchOptions } = this._options;
1410 |     const options = { tokenize, processTerm, ...globalSearchOptions, ...searchOptions };
1411 |     const { tokenize: searchTokenize, processTerm: searchProcessTerm } = options;
1412 |     const terms = searchTokenize(query).flatMap((term) => searchProcessTerm(term)).filter((term) => !!term);
1413 |     const queries = terms.map(termToQuerySpec(options));
1414 |     const results = queries.map((query2) => this.executeQuerySpec(query2, options));
1415 |     return this.combineResults(results, options.combineWith);
1416 |   }
1417 |   /**
1418 |    * @ignore
1419 |    */
1420 |   executeQuerySpec(query, searchOptions) {
1421 |     const options = { ...this._options.searchOptions, ...searchOptions };
1422 |     const boosts = (options.fields || this._options.fields).reduce((boosts2, field) => ({ ...boosts2, [field]: getOwnProperty(options.boost, field) || 1 }), {});
1423 |     const { boostDocument, weights, maxFuzzy, bm25: bm25params } = options;
1424 |     const { fuzzy: fuzzyWeight, prefix: prefixWeight } = { ...defaultSearchOptions.weights, ...weights };
1425 |     const data = this._index.get(query.term);
1426 |     const results = this.termResults(query.term, query.term, 1, query.termBoost, data, boosts, boostDocument, bm25params);
1427 |     let prefixMatches;
1428 |     let fuzzyMatches;
1429 |     if (query.prefix) {
1430 |       prefixMatches = this._index.atPrefix(query.term);
1431 |     }
1432 |     if (query.fuzzy) {
1433 |       const fuzzy = query.fuzzy === true ? 0.2 : query.fuzzy;
1434 |       const maxDistance = fuzzy < 1 ? Math.min(maxFuzzy, Math.round(query.term.length * fuzzy)) : fuzzy;
1435 |       if (maxDistance)
1436 |         fuzzyMatches = this._index.fuzzyGet(query.term, maxDistance);
1437 |     }
1438 |     if (prefixMatches) {
1439 |       for (const [term, data2] of prefixMatches) {
1440 |         const distance = term.length - query.term.length;
1441 |         if (!distance) {
1442 |           continue;
1443 |         }
1444 |         fuzzyMatches === null || fuzzyMatches === void 0 ? void 0 : fuzzyMatches.delete(term);
1445 |         const weight = prefixWeight * term.length / (term.length + 0.3 * distance);
1446 |         this.termResults(query.term, term, weight, query.termBoost, data2, boosts, boostDocument, bm25params, results);
1447 |       }
1448 |     }
1449 |     if (fuzzyMatches) {
1450 |       for (const term of fuzzyMatches.keys()) {
1451 |         const [data2, distance] = fuzzyMatches.get(term);
1452 |         if (!distance) {
1453 |           continue;
1454 |         }
1455 |         const weight = fuzzyWeight * term.length / (term.length + distance);
1456 |         this.termResults(query.term, term, weight, query.termBoost, data2, boosts, boostDocument, bm25params, results);
1457 |       }
1458 |     }
1459 |     return results;
1460 |   }
1461 |   /**
1462 |    * @ignore
1463 |    */
1464 |   executeWildcardQuery(searchOptions) {
1465 |     const results = /* @__PURE__ */ new Map();
1466 |     const options = { ...this._options.searchOptions, ...searchOptions };
1467 |     for (const [shortId, id] of this._documentIds) {
1468 |       const score = options.boostDocument ? options.boostDocument(id, "", this._storedFields.get(shortId)) : 1;
1469 |       results.set(shortId, {
1470 |         score,
1471 |         terms: [],
1472 |         match: {}
1473 |       });
1474 |     }
1475 |     return results;
1476 |   }
1477 |   /**
1478 |    * @ignore
1479 |    */
1480 |   combineResults(results, combineWith = OR) {
1481 |     if (results.length === 0) {
1482 |       return /* @__PURE__ */ new Map();
1483 |     }
1484 |     const operator = combineWith.toLowerCase();
1485 |     const combinator = combinators[operator];
1486 |     if (!combinator) {
1487 |       throw new Error(`Invalid combination operator: ${combineWith}`);
1488 |     }
1489 |     return results.reduce(combinator) || /* @__PURE__ */ new Map();
1490 |   }
1491 |   /**
1492 |    * Allows serialization of the index to JSON, to possibly store it and later
1493 |    * deserialize it with {@link MiniSearch.loadJSON}.
1494 |    *
1495 |    * Normally one does not directly call this method, but rather call the
1496 |    * standard JavaScript `JSON.stringify()` passing the {@link MiniSearch}
1497 |    * instance, and JavaScript will internally call this method. Upon
1498 |    * deserialization, one must pass to {@link MiniSearch.loadJSON} the same
1499 |    * options used to create the original instance that was serialized.
1500 |    *
1501 |    * ### Usage:
1502 |    *
1503 |    * ```javascript
1504 |    * // Serialize the index:
1505 |    * let miniSearch = new MiniSearch({ fields: ['title', 'text'] })
1506 |    * miniSearch.addAll(documents)
1507 |    * const json = JSON.stringify(miniSearch)
1508 |    *
1509 |    * // Later, to deserialize it:
1510 |    * miniSearch = MiniSearch.loadJSON(json, { fields: ['title', 'text'] })
1511 |    * ```
1512 |    *
1513 |    * @return A plain-object serializable representation of the search index.
1514 |    */
1515 |   toJSON() {
1516 |     const index = [];
1517 |     for (const [term, fieldIndex] of this._index) {
1518 |       const data = {};
1519 |       for (const [fieldId, freqs] of fieldIndex) {
1520 |         data[fieldId] = Object.fromEntries(freqs);
1521 |       }
1522 |       index.push([term, data]);
1523 |     }
1524 |     return {
1525 |       documentCount: this._documentCount,
1526 |       nextId: this._nextId,
1527 |       documentIds: Object.fromEntries(this._documentIds),
1528 |       fieldIds: this._fieldIds,
1529 |       fieldLength: Object.fromEntries(this._fieldLength),
1530 |       averageFieldLength: this._avgFieldLength,
1531 |       storedFields: Object.fromEntries(this._storedFields),
1532 |       dirtCount: this._dirtCount,
1533 |       index,
1534 |       serializationVersion: 2
1535 |     };
1536 |   }
1537 |   /**
1538 |    * @ignore
1539 |    */
1540 |   termResults(sourceTerm, derivedTerm, termWeight, termBoost, fieldTermData, fieldBoosts, boostDocumentFn, bm25params, results = /* @__PURE__ */ new Map()) {
1541 |     if (fieldTermData == null)
1542 |       return results;
1543 |     for (const field of Object.keys(fieldBoosts)) {
1544 |       const fieldBoost = fieldBoosts[field];
1545 |       const fieldId = this._fieldIds[field];
1546 |       const fieldTermFreqs = fieldTermData.get(fieldId);
1547 |       if (fieldTermFreqs == null)
1548 |         continue;
1549 |       let matchingFields = fieldTermFreqs.size;
1550 |       const avgFieldLength = this._avgFieldLength[fieldId];
1551 |       for (const docId of fieldTermFreqs.keys()) {
1552 |         if (!this._documentIds.has(docId)) {
1553 |           this.removeTerm(fieldId, docId, derivedTerm);
1554 |           matchingFields -= 1;
1555 |           continue;
1556 |         }
1557 |         const docBoost = boostDocumentFn ? boostDocumentFn(this._documentIds.get(docId), derivedTerm, this._storedFields.get(docId)) : 1;
1558 |         if (!docBoost)
1559 |           continue;
1560 |         const termFreq = fieldTermFreqs.get(docId);
1561 |         const fieldLength = this._fieldLength.get(docId)[fieldId];
1562 |         const rawScore = calcBM25Score(termFreq, matchingFields, this._documentCount, fieldLength, avgFieldLength, bm25params);
1563 |         const weightedScore = termWeight * termBoost * fieldBoost * docBoost * rawScore;
1564 |         const result = results.get(docId);
1565 |         if (result) {
1566 |           result.score += weightedScore;
1567 |           assignUniqueTerm(result.terms, sourceTerm);
1568 |           const match = getOwnProperty(result.match, derivedTerm);
1569 |           if (match) {
1570 |             match.push(field);
1571 |           } else {
1572 |             result.match[derivedTerm] = [field];
1573 |           }
1574 |         } else {
1575 |           results.set(docId, {
1576 |             score: weightedScore,
1577 |             terms: [sourceTerm],
1578 |             match: { [derivedTerm]: [field] }
1579 |           });
1580 |         }
1581 |       }
1582 |     }
1583 |     return results;
1584 |   }
1585 |   /**
1586 |    * @ignore
1587 |    */
1588 |   addTerm(fieldId, documentId, term) {
1589 |     const indexData = this._index.fetch(term, createMap);
1590 |     let fieldIndex = indexData.get(fieldId);
1591 |     if (fieldIndex == null) {
1592 |       fieldIndex = /* @__PURE__ */ new Map();
1593 |       fieldIndex.set(documentId, 1);
1594 |       indexData.set(fieldId, fieldIndex);
1595 |     } else {
1596 |       const docs = fieldIndex.get(documentId);
1597 |       fieldIndex.set(documentId, (docs || 0) + 1);
1598 |     }
1599 |   }
1600 |   /**
1601 |    * @ignore
1602 |    */
1603 |   removeTerm(fieldId, documentId, term) {
1604 |     if (!this._index.has(term)) {
1605 |       this.warnDocumentChanged(documentId, fieldId, term);
1606 |       return;
1607 |     }
1608 |     const indexData = this._index.fetch(term, createMap);
1609 |     const fieldIndex = indexData.get(fieldId);
1610 |     if (fieldIndex == null || fieldIndex.get(documentId) == null) {
1611 |       this.warnDocumentChanged(documentId, fieldId, term);
1612 |     } else if (fieldIndex.get(documentId) <= 1) {
1613 |       if (fieldIndex.size <= 1) {
1614 |         indexData.delete(fieldId);
1615 |       } else {
1616 |         fieldIndex.delete(documentId);
1617 |       }
1618 |     } else {
1619 |       fieldIndex.set(documentId, fieldIndex.get(documentId) - 1);
1620 |     }
1621 |     if (this._index.get(term).size === 0) {
1622 |       this._index.delete(term);
1623 |     }
1624 |   }
1625 |   /**
1626 |    * @ignore
1627 |    */
1628 |   warnDocumentChanged(shortDocumentId, fieldId, term) {
1629 |     for (const fieldName of Object.keys(this._fieldIds)) {
1630 |       if (this._fieldIds[fieldName] === fieldId) {
1631 |         this._options.logger("warn", `MiniSearch: document with ID ${this._documentIds.get(shortDocumentId)} has changed before removal: term "${term}" was not present in field "${fieldName}". Removing a document after it has changed can corrupt the index!`, "version_conflict");
1632 |         return;
1633 |       }
1634 |     }
1635 |   }
1636 |   /**
1637 |    * @ignore
1638 |    */
1639 |   addDocumentId(documentId) {
1640 |     const shortDocumentId = this._nextId;
1641 |     this._idToShortId.set(documentId, shortDocumentId);
1642 |     this._documentIds.set(shortDocumentId, documentId);
1643 |     this._documentCount += 1;
1644 |     this._nextId += 1;
1645 |     return shortDocumentId;
1646 |   }
1647 |   /**
1648 |    * @ignore
1649 |    */
1650 |   addFields(fields) {
1651 |     for (let i = 0; i < fields.length; i++) {
1652 |       this._fieldIds[fields[i]] = i;
1653 |     }
1654 |   }
1655 |   /**
1656 |    * @ignore
1657 |    */
1658 |   addFieldLength(documentId, fieldId, count, length) {
1659 |     let fieldLengths = this._fieldLength.get(documentId);
1660 |     if (fieldLengths == null)
1661 |       this._fieldLength.set(documentId, fieldLengths = []);
1662 |     fieldLengths[fieldId] = length;
1663 |     const averageFieldLength = this._avgFieldLength[fieldId] || 0;
1664 |     const totalFieldLength = averageFieldLength * count + length;
1665 |     this._avgFieldLength[fieldId] = totalFieldLength / (count + 1);
1666 |   }
1667 |   /**
1668 |    * @ignore
1669 |    */
1670 |   removeFieldLength(documentId, fieldId, count, length) {
1671 |     if (count === 1) {
1672 |       this._avgFieldLength[fieldId] = 0;
1673 |       return;
1674 |     }
1675 |     const totalFieldLength = this._avgFieldLength[fieldId] * count - length;
1676 |     this._avgFieldLength[fieldId] = totalFieldLength / (count - 1);
1677 |   }
1678 |   /**
1679 |    * @ignore
1680 |    */
1681 |   saveStoredFields(documentId, doc) {
1682 |     const { storeFields, extractField } = this._options;
1683 |     if (storeFields == null || storeFields.length === 0) {
1684 |       return;
1685 |     }
1686 |     let documentFields = this._storedFields.get(documentId);
1687 |     if (documentFields == null)
1688 |       this._storedFields.set(documentId, documentFields = {});
1689 |     for (const fieldName of storeFields) {
1690 |       const fieldValue = extractField(doc, fieldName);
1691 |       if (fieldValue !== void 0)
1692 |         documentFields[fieldName] = fieldValue;
1693 |     }
1694 |   }
1695 | };
1696 | MiniSearch.wildcard = Symbol("*");
1697 | var getOwnProperty = (object, property) => Object.prototype.hasOwnProperty.call(object, property) ? object[property] : void 0;
1698 | var combinators = {
1699 |   [OR]: (a, b) => {
1700 |     for (const docId of b.keys()) {
1701 |       const existing = a.get(docId);
1702 |       if (existing == null) {
1703 |         a.set(docId, b.get(docId));
1704 |       } else {
1705 |         const { score, terms, match } = b.get(docId);
1706 |         existing.score = existing.score + score;
1707 |         existing.match = Object.assign(existing.match, match);
1708 |         assignUniqueTerms(existing.terms, terms);
1709 |       }
1710 |     }
1711 |     return a;
1712 |   },
1713 |   [AND]: (a, b) => {
1714 |     const combined = /* @__PURE__ */ new Map();
1715 |     for (const docId of b.keys()) {
1716 |       const existing = a.get(docId);
1717 |       if (existing == null)
1718 |         continue;
1719 |       const { score, terms, match } = b.get(docId);
1720 |       assignUniqueTerms(existing.terms, terms);
1721 |       combined.set(docId, {
1722 |         score: existing.score + score,
1723 |         terms: existing.terms,
1724 |         match: Object.assign(existing.match, match)
1725 |       });
1726 |     }
1727 |     return combined;
1728 |   },
1729 |   [AND_NOT]: (a, b) => {
1730 |     for (const docId of b.keys())
1731 |       a.delete(docId);
1732 |     return a;
1733 |   }
1734 | };
1735 | var defaultBM25params = { k: 1.2, b: 0.7, d: 0.5 };
1736 | var calcBM25Score = (termFreq, matchingCount, totalCount, fieldLength, avgFieldLength, bm25params) => {
1737 |   const { k, b, d } = bm25params;
1738 |   const invDocFreq = Math.log(1 + (totalCount - matchingCount + 0.5) / (matchingCount + 0.5));
1739 |   return invDocFreq * (d + termFreq * (k + 1) / (termFreq + k * (1 - b + b * fieldLength / avgFieldLength)));
1740 | };
1741 | var termToQuerySpec = (options) => (term, i, terms) => {
1742 |   const fuzzy = typeof options.fuzzy === "function" ? options.fuzzy(term, i, terms) : options.fuzzy || false;
1743 |   const prefix = typeof options.prefix === "function" ? options.prefix(term, i, terms) : options.prefix === true;
1744 |   const termBoost = typeof options.boostTerm === "function" ? options.boostTerm(term, i, terms) : 1;
1745 |   return { term, fuzzy, prefix, termBoost };
1746 | };
1747 | var defaultOptions = {
1748 |   idField: "id",
1749 |   extractField: (document, fieldName) => document[fieldName],
1750 |   tokenize: (text) => text.split(SPACE_OR_PUNCTUATION),
1751 |   processTerm: (term) => term.toLowerCase(),
1752 |   fields: void 0,
1753 |   searchOptions: void 0,
1754 |   storeFields: [],
1755 |   logger: (level, message) => {
1756 |     if (typeof (console === null || console === void 0 ? void 0 : console[level]) === "function")
1757 |       console[level](message);
1758 |   },
1759 |   autoVacuum: true
1760 | };
1761 | var defaultSearchOptions = {
1762 |   combineWith: OR,
1763 |   prefix: false,
1764 |   fuzzy: false,
1765 |   maxFuzzy: 6,
1766 |   boost: {},
1767 |   weights: { fuzzy: 0.45, prefix: 0.375 },
1768 |   bm25: defaultBM25params
1769 | };
1770 | var defaultAutoSuggestOptions = {
1771 |   combineWith: AND,
1772 |   prefix: (term, i, terms) => i === terms.length - 1
1773 | };
1774 | var defaultVacuumOptions = { batchSize: 1e3, batchWait: 10 };
1775 | var defaultVacuumConditions = { minDirtFactor: 0.1, minDirtCount: 20 };
1776 | var defaultAutoVacuumOptions = { ...defaultVacuumOptions, ...defaultVacuumConditions };
1777 | var assignUniqueTerm = (target, term) => {
1778 |   if (!target.includes(term))
1779 |     target.push(term);
1780 | };
1781 | var assignUniqueTerms = (target, source) => {
1782 |   for (const term of source) {
1783 |     if (!target.includes(term))
1784 |       target.push(term);
1785 |   }
1786 | };
1787 | var byScore = ({ score: a }, { score: b }) => b - a;
1788 | var createMap = () => /* @__PURE__ */ new Map();
1789 | var objectToNumericMap = (object) => {
1790 |   const map = /* @__PURE__ */ new Map();
1791 |   for (const key of Object.keys(object)) {
1792 |     map.set(parseInt(key, 10), object[key]);
1793 |   }
1794 |   return map;
1795 | };
1796 | var objectToNumericMapAsync = async (object) => {
1797 |   const map = /* @__PURE__ */ new Map();
1798 |   let count = 0;
1799 |   for (const key of Object.keys(object)) {
1800 |     map.set(parseInt(key, 10), object[key]);
1801 |     if (++count % 1e3 === 0) {
1802 |       await wait(0);
1803 |     }
1804 |   }
1805 |   return map;
1806 | };
1807 | var wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
1808 | var SPACE_OR_PUNCTUATION = /[\n\r\p{Z}\p{P}]+/u;
1809 | export {
1810 |   MiniSearch as default
1811 | };
1812 | //# sourceMappingURL=vitepress___minisearch.js.map
1813 | 
```
Page 6/10FirstPrevNextLast