diff --git a/.gitignore b/.gitignore index 49a01770..0ab3963d 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ target/ node_modules/ .factorypath +**/.vitepress/dist +**/.vitepress/cache diff --git a/Makefile b/Makefile index 412f898d..bd93cdd0 100644 --- a/Makefile +++ b/Makefile @@ -10,9 +10,9 @@ install: .PHONY: docs watch-docs docs: - mvn asciidoctor:process-asciidoc + npm run docs:build mvn javadoc:javadoc - cp -R target/site/apidocs target/generated-docs/ + cp -R target/site/apidocs xdocs/.vitepress/dist/ npm run deploy-docs watch-docs: diff --git a/examples/myapp/src/main/java/app/MyApp.java b/examples/myapp/src/main/java/app/MyApp.java index 1975e14a..0fd222a6 100644 --- a/examples/myapp/src/main/java/app/MyApp.java +++ b/examples/myapp/src/main/java/app/MyApp.java @@ -6,7 +6,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; -// tag::install[] +// #region install @SpringBootApplication @EnableQueryResponse public class MyApp { @@ -16,4 +16,4 @@ public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } } -// end::install[] +// #endregion install diff --git a/examples/myapp/src/main/java/app/Queries.java b/examples/myapp/src/main/java/app/Queries.java index 97b04d35..3112fd43 100644 --- a/examples/myapp/src/main/java/app/Queries.java +++ b/examples/myapp/src/main/java/app/Queries.java @@ -15,7 +15,7 @@ import java.util.Collection; -// tag::query[] +// #region query @Component public class Queries { @@ -34,4 +34,4 @@ public void query() { polos.stream().map("marco? "::concat).forEach(System.out::println); } } -// end::query[] +// #endregion query diff --git a/examples/myapp/src/main/java/app/Responses.java b/examples/myapp/src/main/java/app/Responses.java index cf139154..3c79fcd2 100644 --- a/examples/myapp/src/main/java/app/Responses.java +++ b/examples/myapp/src/main/java/app/Responses.java @@ -13,7 +13,7 @@ import org.springframework.stereotype.Component; -// tag::response[] +// #region response @Component public class Responses { @@ -29,4 +29,4 @@ public void response() { .from("polo", "yolo"); // <3> } } -// end::response[] +// #endregion response diff --git a/examples/querying/src/main/java/examples/Authors.java b/examples/querying/src/main/java/examples/Authors.java index b250d581..254c1579 100644 --- a/examples/querying/src/main/java/examples/Authors.java +++ b/examples/querying/src/main/java/examples/Authors.java @@ -7,7 +7,7 @@ import java.util.Collection; -//tag::class[] +// #region class @Component public class Authors { @@ -23,4 +23,4 @@ public Collection findAuthors() { .orEmpty(); } } -//end::class[] +// #endregion class diff --git a/examples/responding/src/main/java/examples/OnlyThreeAuthors.java b/examples/responding/src/main/java/examples/OnlyThreeAuthors.java index 0001f26b..9c5bac6b 100644 --- a/examples/responding/src/main/java/examples/OnlyThreeAuthors.java +++ b/examples/responding/src/main/java/examples/OnlyThreeAuthors.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Component; -//tag::class[] +// #region class @Component public class OnlyThreeAuthors { @@ -26,4 +26,4 @@ public void respondWithAuthors() { .from("Tolkien", "Lewis", "Rowling"); } } -//end::class[] +// #endregion class diff --git a/package-lock.json b/package-lock.json index d1afb676..74dc4707 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,804 +1,2129 @@ { "name": "query-response-spring-amqp", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { "devDependencies": { - "gh-pages": "^5.0.0", - "lodash": "^4.17.21" + "gh-pages": "^6.0.0", + "lodash": "^4.17.21", + "vitepress": "^1.2.3" } }, - "node_modules/array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", "dev": true, "dependencies": { - "array-uniq": "^1.0.1" + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "search-insights": ">= 1 < 3" } }, - "node_modules/array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" } }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", - "dev": true + "node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "dev": true, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz", + "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==", + "dev": true, + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz", + "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==", "dev": true }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@algolia/cache-in-memory": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz", + "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@algolia/cache-common": "4.24.0" } }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "node_modules/@algolia/client-account": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz", + "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/transporter": "4.24.0" + } }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true + "node_modules/@algolia/client-analytics": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz", + "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "dev": true, + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } }, - "node_modules/email-addresses": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", - "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", - "dev": true + "node_modules/@algolia/client-personalization": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz", + "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==", + "dev": true, + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", "dev": true, - "engines": { - "node": ">=0.8.0" + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" } }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "node_modules/@algolia/logger-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz", + "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==", + "dev": true + }, + "node_modules/@algolia/logger-console": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz", + "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==", "dev": true, - "engines": { - "node": ">=4" + "dependencies": { + "@algolia/logger-common": "4.24.0" } }, - "node_modules/filenamify": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", + "node_modules/@algolia/recommend": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz", + "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==", "dev": true, "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" } }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", + "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", "dev": true, "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + "@algolia/requester-common": "4.24.0" } }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@algolia/requester-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz", + "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==", + "dev": true + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", + "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", "dev": true, "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@algolia/requester-common": "4.24.0" } }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/@algolia/transporter": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz", + "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==", "dev": true, "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "@algolia/cache-common": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=6.0.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "node_modules/@docsearch/css": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.0.tgz", + "integrity": "sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==", "dev": true }, - "node_modules/gh-pages": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", - "integrity": "sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==", + "node_modules/@docsearch/js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.6.0.tgz", + "integrity": "sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==", "dev": true, "dependencies": { - "async": "^3.2.4", - "commander": "^2.18.0", - "email-addresses": "^5.0.0", - "filenamify": "^4.3.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "^8.1.0", - "globby": "^6.1.0" + "@docsearch/react": "3.6.0", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.0.tgz", + "integrity": "sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.0", + "algoliasearch": "^4.19.1" }, - "bin": { - "gh-pages": "bin/gh-pages.js", - "gh-pages-clean": "bin/gh-pages-clean.js" + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=12" } }, - "node_modules/globby": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.1.tgz", + "integrity": "sha512-qdiJS5a/QGCff7VUFIqd0hDdWly9rDp8lhVmXVrS11aazX8LOTRLHAXkkEeONNsS43EcCd7gax9LLoOz4vlFQA==", + "dev": true + }, + "node_modules/@shikijs/transformers": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.10.1.tgz", + "integrity": "sha512-0gLtcFyi6R6zcUkFajUEp1Qiv7lHBSFgOz4tQvS8nFsYCQSLI1/9pM+Me8jEIPXv7XLKAoUjw6InL+Sv+BHw/A==", + "dev": true, + "dependencies": { + "shiki": "1.10.1" } }, - "node_modules/locate-path": { + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, + "node_modules/@types/linkify-it": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, + "node_modules/@types/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", "dev": true, "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" + "@types/linkify-it": "^5", + "@types/mdurl": "^2" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", "dev": true }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "node_modules/@types/web-bluetooth": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", + "dev": true + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.5.tgz", + "integrity": "sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==", "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, "engines": { - "node": ">=8" + "node": "^18.0.0 || >=20.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/@vue/compiler-core": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.31.tgz", + "integrity": "sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==", "dev": true, "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.31", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "node_modules/@vue/compiler-dom": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.31.tgz", + "integrity": "sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@vue/compiler-core": "3.4.31", + "@vue/shared": "3.4.31" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "node_modules/@vue/compiler-sfc": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.31.tgz", + "integrity": "sha512-einJxqEw8IIJxzmnxmJBuK2usI+lJonl53foq+9etB2HAzlPjAS/wa7r0uUpXw5ByX3/0uswVSrjNb17vJm1kQ==", "dev": true, "dependencies": { - "wrappy": "1" + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.31", + "@vue/compiler-dom": "3.4.31", + "@vue/compiler-ssr": "3.4.31", + "@vue/shared": "3.4.31", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.38", + "source-map-js": "^1.2.0" } }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@vue/compiler-ssr": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.31.tgz", + "integrity": "sha512-RtefmITAje3fJ8FSg1gwgDhdKhZVntIVbwupdyZDSifZTRMiWxWehAOTCc8/KZDnBOcYQ4/9VWxsTbd3wT0hAA==", "dev": true, "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@vue/compiler-dom": "3.4.31", + "@vue/shared": "3.4.31" } }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@vue/devtools-api": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.3.5.tgz", + "integrity": "sha512-BSdBBu5hOIv+gBJC9jzYMh5bC27FQwjWLSb8fVAniqlL9gvsqvK27xTgczMf+hgctlszMYQnRm3bpY/j8vhPqw==", "dev": true, "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "@vue/devtools-kit": "^7.3.5" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "node_modules/@vue/devtools-kit": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.3.5.tgz", + "integrity": "sha512-wwfi10gJ1HMtjzcd8aIOnzBHlIRqsYDgcDyrKvkeyc0Gbcoe7UrkXRVHZUOtcxxoplHA0PwpT6wFg0uUCmi8Ww==", "dev": true, - "engines": { - "node": ">=6" + "dependencies": { + "@vue/devtools-shared": "^7.3.5", + "birpc": "^0.2.17", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.1" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/@vue/devtools-shared": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.3.5.tgz", + "integrity": "sha512-Rqii3VazmWTi67a86rYopi61n5Ved05EybJCwyrfoO9Ok3MaS/4yRFl706ouoISMlyrASJFEzM0/AiDA6w4f9A==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "rfdc": "^1.4.1" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "node_modules/@vue/reactivity": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.31.tgz", + "integrity": "sha512-VGkTani8SOoVkZNds1PfJ/T1SlAIOf8E58PGAhIOUDYPC4GAmFA2u/E14TDAFcf3vVDKunc4QqCe/SHr8xC65Q==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@vue/shared": "3.4.31" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "node_modules/@vue/runtime-core": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.31.tgz", + "integrity": "sha512-LDkztxeUPazxG/p8c5JDDKPfkCDBkkiNLVNf7XZIUnJ+66GVGkP+TIh34+8LtPisZ+HMWl2zqhIw0xN5MwU1cw==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@vue/reactivity": "3.4.31", + "@vue/shared": "3.4.31" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "node_modules/@vue/runtime-dom": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.31.tgz", + "integrity": "sha512-2Auws3mB7+lHhTFCg8E9ZWopA6Q6L455EcU7bzcQ4x6Dn4cCPuqj6S2oBZgN2a8vJRS/LSYYxwFFq2Hlx3Fsaw==", "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@vue/reactivity": "3.4.31", + "@vue/runtime-core": "3.4.31", + "@vue/shared": "3.4.31", + "csstype": "^3.1.3" } }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "node_modules/@vue/server-renderer": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.31.tgz", + "integrity": "sha512-D5BLbdvrlR9PE3by9GaUp1gQXlCNadIZytMIb8H2h3FMWJd4oUfkUTEH2wAr3qxoRz25uxbTcbqd3WKlm9EHQA==", "dev": true, "dependencies": { - "pinkie": "^2.0.0" + "@vue/compiler-ssr": "3.4.31", + "@vue/shared": "3.4.31" }, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "vue": "3.4.31" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "node_modules/@vue/shared": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.31.tgz", + "integrity": "sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==", + "dev": true + }, + "node_modules/@vueuse/core": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.11.0.tgz", + "integrity": "sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==", "dev": true, "dependencies": { - "find-up": "^4.0.0" + "@types/web-bluetooth": "^0.0.20", + "@vueuse/metadata": "10.11.0", + "@vueuse/shared": "10.11.0", + "vue-demi": ">=0.14.8" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", "dev": true, + "hasInstallScript": true, "bin": { - "semver": "bin/semver.js" + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "node_modules/@vueuse/integrations": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.11.0.tgz", + "integrity": "sha512-Pp6MtWEIr+NDOccWd8j59Kpjy5YDXogXI61Kb1JxvSfVBO8NzFQkmrKmSZz47i+ZqHnIzxaT38L358yDHTncZg==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.2" + "@vueuse/core": "10.11.0", + "@vueuse/shared": "10.11.0", + "vue-demi": ">=0.14.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^4", + "drauu": "^0.3", + "focus-trap": "^7", + "fuse.js": "^6", + "idb-keyval": "^6", + "jwt-decode": "^3", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^6" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/integrations/node_modules/vue-demi": { + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" }, "engines": { - "node": ">=0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "node_modules/@vueuse/metadata": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.11.0.tgz", + "integrity": "sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.11.0.tgz", + "integrity": "sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==", "dev": true, "dependencies": { - "escape-string-regexp": "^1.0.2" + "vue-demi": ">=0.14.8" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.8.tgz", + "integrity": "sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==", "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, "engines": { - "node": ">= 4.0.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - } - }, - "dependencies": { - "array-union": { + "node_modules/algoliasearch": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", + "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", + "dev": true, + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-account": "4.24.0", + "@algolia/client-analytics": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-personalization": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/recommend": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", "dev": true, - "requires": { + "dependencies": { "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "array-uniq": { + "node_modules/array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, - "balanced-match": { + "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "brace-expansion": { + "node_modules/birpc": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.17.tgz", + "integrity": "sha512-+hkTxhot+dWsLpp3gia5AkVHIsKlZybNT5gIYiDlNzJrmYPcTM9k5/w2uaj3IPpd7LlEYpmCj4Jj1nC41VhDFg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "requires": { + "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "node_modules/commander": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "dev": true, + "engines": { + "node": ">=16" + } }, - "commondir": { + "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, - "concat-map": { + "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "email-addresses": { + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "dev": true, + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, + "node_modules/email-addresses": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", "dev": true }, - "escape-string-regexp": { + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, - "filename-reserved-regex": { + "node_modules/filename-reserved-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=4" + } }, - "filenamify": { + "node_modules/filenamify": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", "dev": true, - "requires": { + "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "find-cache-dir": { + "node_modules/find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, - "requires": { + "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "find-up": { + "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "requires": { + "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/focus-trap": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz", + "integrity": "sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==", + "dev": true, + "dependencies": { + "tabbable": "^6.2.0" } }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", "dev": true, - "requires": { + "dependencies": { "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" } }, - "fs.realpath": { + "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "gh-pages": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-5.0.0.tgz", - "integrity": "sha512-Nqp1SjkPIB94Xw/3yYNTUL+G2dxlhjvv1zeN/4kMC1jfViTEqhtVz/Ba1zSXHuvXCN9ADNS1dN4r5/J/nZWEQQ==", + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gh-pages": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.1.1.tgz", + "integrity": "sha512-upnohfjBwN5hBP9w2dPE7HO5JJTHzSGMV1JrLrHvNuqmjoYHg6TBrCcnEoorjG/e0ejbuvnwyKMdTyM40PEByw==", "dev": true, - "requires": { + "dependencies": { "async": "^3.2.4", - "commander": "^2.18.0", + "commander": "^11.0.0", "email-addresses": "^5.0.0", "filenamify": "^4.3.0", "find-cache-dir": "^3.3.1", - "fs-extra": "^8.1.0", + "fs-extra": "^11.1.1", "globby": "^6.1.0" + }, + "bin": { + "gh-pages": "bin/gh-pages.js", + "gh-pages-clean": "bin/gh-pages-clean.js" + }, + "engines": { + "node": ">=10" } }, - "glob": { + "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, - "requires": { + "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "globby": { + "node_modules/globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", "integrity": "sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==", "dev": true, - "requires": { + "dependencies": { "array-union": "^1.0.1", "glob": "^7.0.3", "object-assign": "^4.0.1", "pify": "^2.0.0", "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", "dev": true }, - "inflight": { + "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, - "requires": { + "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, - "inherits": { + "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", "dev": true, - "requires": { + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { "graceful-fs": "^4.1.6" } }, - "locate-path": { + "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "requires": { + "dependencies": { "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" } }, - "lodash": { + "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "make-dir": { + "node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, - "requires": { + "dependencies": { "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "minimatch": { + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true + }, + "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "requires": { + "dependencies": { "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minisearch": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.3.0.tgz", + "integrity": "sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ==", + "dev": true + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "object-assign": { + "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "once": { + "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, - "requires": { + "dependencies": { "wrappy": "1" } }, - "p-limit": { + "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "requires": { + "dependencies": { "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "p-locate": { + "node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "requires": { + "dependencies": { "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" } }, - "p-try": { + "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "dev": true, + "engines": { + "node": ">=6" + } }, - "path-exists": { + "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true + "dev": true, + "engines": { + "node": ">=8" + } }, - "path-is-absolute": { + "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, - "pify": { + "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "pinkie": { + "node_modules/pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", - "dev": true + "dev": true, + "engines": { + "node": ">=0.10.0" + } }, - "pinkie-promise": { + "node_modules/pinkie-promise": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", "dev": true, - "requires": { + "dependencies": { "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "pkg-dir": { + "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, - "requires": { + "dependencies": { "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/postcss": { + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.22.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.22.1.tgz", + "integrity": "sha512-jRYbDDgMpIb5LHq3hkI0bbl+l/TQ9UnkdQ0ww+lp+4MMOdqaUYdFc5qeyP+IV8FAd/2Em7drVPeKdQxsiWCf/A==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", "dev": true }, - "strip-outer": { + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/search-insights": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.14.0.tgz", + "integrity": "sha512-OLN6MsPMCghDOqlCtsIsYgtsC0pnwVTyT9Mu6A3ewOj1DxvzZF6COrn2g86E/c05xbktB0XN04m/t1Z+n+fTGw==", + "dev": true, + "peer": true + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shiki": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.1.tgz", + "integrity": "sha512-uafV7WCgN4YYrccH6yxpnps6k38sSTlFRrwc4jycWmhWxJIm9dPrk+XkY1hZ2t0I7jmacMNb15Lf2fspa/Y3lg==", + "dev": true, + "dependencies": { + "@shikijs/core": "1.10.1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-outer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", "dev": true, - "requires": { + "dependencies": { "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "trim-repeated": { + "node_modules/superjson": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.1.tgz", + "integrity": "sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==", + "dev": true, + "dependencies": { + "copy-anything": "^3.0.2" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true + }, + "node_modules/trim-repeated": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", "dev": true, - "requires": { + "dependencies": { "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/vite": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz", + "integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.39", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.2.3.tgz", + "integrity": "sha512-GvEsrEeNLiDE1+fuwDAYJCYLNZDAna+EtnXlPajhv/MYeTjbNK6Bvyg6NoTdO1sbwuQJ0vuJR99bOlH53bo6lg==", + "dev": true, + "dependencies": { + "@docsearch/css": "^3.6.0", + "@docsearch/js": "^3.6.0", + "@shikijs/core": "^1.6.2", + "@shikijs/transformers": "^1.6.2", + "@types/markdown-it": "^14.1.1", + "@vitejs/plugin-vue": "^5.0.5", + "@vue/devtools-api": "^7.2.1", + "@vue/shared": "^3.4.27", + "@vueuse/core": "^10.10.0", + "@vueuse/integrations": "^10.10.0", + "focus-trap": "^7.5.4", + "mark.js": "8.11.1", + "minisearch": "^6.3.0", + "shiki": "^1.6.2", + "vite": "^5.2.12", + "vue": "^3.4.27" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.31", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.31.tgz", + "integrity": "sha512-njqRrOy7W3YLAlVqSKpBebtZpDVg21FPoaq1I7f/+qqBThK9ChAIjkRWgeP6Eat+8C+iia4P3OYqpATP21BCoQ==", + "dev": true, + "dependencies": { + "@vue/compiler-dom": "3.4.31", + "@vue/compiler-sfc": "3.4.31", + "@vue/runtime-dom": "3.4.31", + "@vue/server-renderer": "3.4.31", + "@vue/shared": "3.4.31" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } }, - "wrappy": { + "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", diff --git a/package.json b/package.json index 8cb3a11a..a910434f 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,14 @@ { "private": true, "devDependencies": { - "gh-pages": "^5.0.0", - "lodash": "^4.17.21" + "gh-pages": "^6.0.0", + "lodash": "^4.17.21", + "vitepress": "^1.2.3" }, "scripts": { - "deploy-docs": "gh-pages -d target/generated-docs" + "deploy-docs": "gh-pages -d xdocs/.vitepress/dist", + "docs:dev": "vitepress dev xdocs", + "docs:build": "vitepress build xdocs", + "docs:preview": "vitepress preview xdocs" } } diff --git a/ui-frontend/src/style.css b/ui-frontend/src/style.css index 2a62b510..d943a9b1 100644 --- a/ui-frontend/src/style.css +++ b/ui-frontend/src/style.css @@ -12,81 +12,7 @@ html { /* THEME -------------------------------------------------------------------- */ -:root { - --color-black: rgba(44, 62, 80, 0.9); - - --color-fuchsia-100: hsl(344, 97%, 95%); - --color-fuchsia-200: hsl(344, 97%, 90%); - --color-fuchsia-300: hsl(344, 97%, 85%); - --color-fuchsia-400: hsl(344, 97%, 75%); - --color-fuchsia-500: hsl(344, 97%, 64%); - --color-fuchsia-600: hsl(344, 97%, 54%); - --color-fuchsia-700: hsl(344, 97%, 44%); - --color-fuchsia-800: hsl(344, 97%, 34%); - --color-fuchsia-900: hsl(344, 97%, 20%); - - --color-petrol-100: hsl(157, 30%, 95%); - --color-petrol-200: hsl(157, 30%, 90%); - --color-petrol-300: hsl(157, 30%, 80%); - --color-petrol-400: hsl(157, 30%, 70%); - --color-petrol-500: hsl(157, 30%, 63%); - --color-petrol-600: hsl(157, 30%, 53%); - --color-petrol-700: hsl(157, 30%, 40%); - --color-petrol-800: hsl(157, 30%, 30%); - --color-petrol-900: hsl(157, 30%, 20%); - - --color-blue-100: hsla(209, 58%, 95%); - --color-blue-200: hsla(209, 58%, 80%); - --color-blue-300: hsla(209, 58%, 70%); - --color-blue-400: hsla(209, 58%, 60%); - --color-blue-500: hsla(209, 58%, 50%); - --color-blue-600: hsla(209, 58%, 46%); - --color-blue-700: hsla(209, 58%, 36%); - --color-blue-800: hsla(209, 58%, 30%); - --color-blue-900: hsl(209, 59%, 20%); - - --color-amber: hsl(37, 100%, 55%); - - --bg: #f3f2eb; - --bg-hover: rgba(123, 154, 255, 0.07); - --bg-even: hsla(226, 10%, 50%, 0.07); - --fg: #111; - --fg-light: rgba(0, 0, 0, 0.4); - --link: rgba(50, 121, 187, 0.925); - --link-high-contrast: rgba(50, 121, 187, 1); - --panel: #fff; - --border: 1px solid rgba(182, 182, 182, 0.424); - --border-radius: 5px; - --action: var(--link-high-contrast); - --success: var(--color-petrol-600); - --warning: hsl(37, 100%, 55%); - --error: var(--color-fuchsia-500); - --bold: 600; - --thin: 400; - --bold-letter-spacing: 0.1rem; -} - -[data-theme="dark"] { - --bg: hsl(330, 10%, 23%); - --bg-hover: rgba(212, 222, 255, 0.07); - --bg-even: hsla(225, 10%, 62%, 0.164); - --fg: #fff; - --fg-light: rgba(255, 255, 250, 0.5); - --link: rgba(50, 121, 187, 0.925); - --link-high-contrast: rgb(104, 176, 243); - --panel: hsl(30, 1%, 38%); - --border: 1px solid rgba(0, 0, 0, 0.3); - --success: var(--color-petrol-400); - --warning: #ffba4c; - --error: var(--color-fuchsia-400); - --bold: 500; - --thin: 300; - --bold-letter-spacing: 0.127rem; -} - -[data-theme="dark"] .icon-tabler { - stroke-width: 1.6; -} +@import url("vars.css"); /* Main style --------------------------------------------------------------- */ diff --git a/ui-frontend/src/vars.css b/ui-frontend/src/vars.css new file mode 100644 index 00000000..678f5047 --- /dev/null +++ b/ui-frontend/src/vars.css @@ -0,0 +1,75 @@ +:root { + --color-black: rgba(44, 62, 80, 0.9); + + --color-fuchsia-100: hsl(344, 97%, 95%); + --color-fuchsia-200: hsl(344, 97%, 90%); + --color-fuchsia-300: hsl(344, 97%, 85%); + --color-fuchsia-400: hsl(344, 97%, 75%); + --color-fuchsia-500: hsl(344, 97%, 64%); + --color-fuchsia-600: hsl(344, 97%, 54%); + --color-fuchsia-700: hsl(344, 97%, 44%); + --color-fuchsia-800: hsl(344, 97%, 34%); + --color-fuchsia-900: hsl(344, 97%, 20%); + + --color-petrol-100: hsl(157, 30%, 95%); + --color-petrol-200: hsl(157, 30%, 90%); + --color-petrol-300: hsl(157, 30%, 80%); + --color-petrol-400: hsl(157, 30%, 70%); + --color-petrol-500: hsl(157, 30%, 63%); + --color-petrol-600: hsl(157, 30%, 53%); + --color-petrol-700: hsl(157, 30%, 40%); + --color-petrol-800: hsl(157, 30%, 30%); + --color-petrol-900: hsl(157, 30%, 20%); + + --color-blue-100: hsla(209, 58%, 95%); + --color-blue-200: hsla(209, 58%, 80%); + --color-blue-300: hsla(209, 58%, 70%); + --color-blue-400: hsla(209, 58%, 60%); + --color-blue-500: hsla(209, 58%, 50%); + --color-blue-600: hsla(209, 58%, 46%); + --color-blue-700: hsla(209, 58%, 36%); + --color-blue-800: hsla(209, 58%, 30%); + --color-blue-900: hsl(209, 59%, 20%); + + --color-amber: hsl(37, 100%, 55%); + + --bg: #f3f2eb; + --bg-hover: rgba(123, 154, 255, 0.07); + --bg-even: hsla(226, 10%, 50%, 0.07); + --fg: #111; + --fg-light: rgba(0, 0, 0, 0.4); + --link: rgba(50, 121, 187, 0.925); + --link-high-contrast: rgba(50, 121, 187, 1); + --panel: #fff; + --border: 1px solid rgba(182, 182, 182, 0.424); + --border-radius: 5px; + --action: var(--link-high-contrast); + --success: var(--color-petrol-600); + --warning: hsl(37, 100%, 55%); + --error: var(--color-fuchsia-500); + --bold: 600; + --thin: 400; + --bold-letter-spacing: 0.1rem; +} + +[data-theme="dark"] { + --bg: hsl(330, 10%, 23%); + --bg-hover: rgba(212, 222, 255, 0.07); + --bg-even: hsla(225, 10%, 62%, 0.164); + --fg: #fff; + --fg-light: rgba(255, 255, 250, 0.5); + --link: rgba(50, 121, 187, 0.925); + --link-high-contrast: rgb(104, 176, 243); + --panel: hsl(30, 1%, 38%); + --border: 1px solid rgba(0, 0, 0, 0.3); + --success: var(--color-petrol-400); + --warning: #ffba4c; + --error: var(--color-fuchsia-400); + --bold: 500; + --thin: 300; + --bold-letter-spacing: 0.127rem; +} + +[data-theme="dark"] .icon-tabler { + stroke-width: 1.6; +} diff --git a/xdocs/.vitepress/config.mjs b/xdocs/.vitepress/config.mjs new file mode 100644 index 00000000..f118ae07 --- /dev/null +++ b/xdocs/.vitepress/config.mjs @@ -0,0 +1,59 @@ +import { defineConfig } from "vitepress"; + +export default defineConfig({ + title: "Query/Response", + description: "A VitePress Site", + lastUpdated: true, + footer: true, + ignoreDeadLinks: true, + themeConfig: { + search: { + provider: "local", + }, + nav: [ + { text: "Home", link: "/" }, + { text: "Guide", link: "/guide/what-is-query-response" }, + { text: "Reference", link: "/reference/developers-reference" }, + ], + sidebar: [ + { + text: "Guide", + items: [ + { + text: "What is Query/Response", + link: "/guide/what-is-query-response", + }, + { text: "Getting started", link: "/guide/getting-started" }, + { text: "Example revisited", link: "/guide/the-example-revisited" }, + ], + }, + { + text: "Reference", + items: [ + { + text: "Developers Reference", + link: "/reference/developers-reference", + }, + { + text: "Query/Response Protocol", + link: "/reference/the-query-response-protocol", + }, + { + text: "Maturity Model", + link: "/reference/query-response-maturity-model", + }, + ], + }, + ], + socialLinks: [ + { + icon: "github", + link: "https://github.com/olle/query-response-spring-amqp", + }, + ], + footer: { + message: "Published under the Apache-2.0 license", + copyright: `Copyright © 2019-${new Date().getFullYear()} Olle Törnström and all other contributors.`, + }, + }, +}); diff --git a/xdocs/attributes.js b/xdocs/attributes.js new file mode 100644 index 00000000..36514e49 --- /dev/null +++ b/xdocs/attributes.js @@ -0,0 +1 @@ +export const BRAND = "Query/Response for Spring® AMQP"; diff --git a/xdocs/guide/getting-started.md b/xdocs/guide/getting-started.md new file mode 100644 index 00000000..403c007d --- /dev/null +++ b/xdocs/guide/getting-started.md @@ -0,0 +1,158 @@ + + +# Getting Started + +{{attr.BRAND}} makes it really easy to extend Spring Boot stand-alone, +production-grade applications, that are using Spring AMQP. We have taken +a working pattern for building highly decoupled evolving service architectures, +and wrapped it in a developer friendly library. + +## System Requirements + +{{attr.BRAND}} requires at least **Spring Boot 2.x** and **Java 11**, and should work +for later releases too. We are building and running it successfully with +**Java 11** and the **Spring Boot 3.0.3** version. + +## Installation & Configuration + +It is distributed as a [Maven](https://maven.apache.org) dependency, and is +known to work well with Maven 3.3+. Using the dependency with [Gradle](https://gradle.org) +should work too. Please see the [Quickstart](https://github.com/olle/query-response-spring-amqp#quickstart) +information, available on the project [Github page](https://github.com/olle/query-response-spring-amqp), +for information on how to get the Maven dependency. + +Enabling {{attr.BRAND}} is done by loading the `QueryResponseConfiguration` +class. The most simple way to do this, is by annotating your Spring Boot +application with the `@EnableQueryResponse` annotation. + +<<<@../../examples/myapp/src/main/java/app/MyApp.java#install{java} + +NOTE: This annotation will do nothing more but to import the +`QueryResponseConfiguration` class. + +That's it! There is no more infrastructure code, wiring or setup that needs to +be done. **It's just that easy.** + +### Connecting to an AMQP broker + +Before you can run your application you need to make sure there is an AMQP +broker available. By default {{attr.BRAND}} tries to connect to a +https://www.rabbitmq.com[RabbitMQ], running locally on port `5672`. + +Start an and run RabbitMQ using `docker`: + +```sh +$ docker run -p 5672:5672 -p 15672:15672 rabbitmq:3-management +``` + +NOTE: The `3-management` tag will enable the RabbitMQ Management UI. When the +broker is running, it can be accessed at http://localhost:15672 with +username and password `guest/guest`. + +Now running your application, will enable {{attr.BRAND}}, connect to the broker and +create all the resources necessary on the broker. + +```sh +$ mvn spring-boot:run +``` + +Now is a good time to use the RabbitMQ Management UI, available at +http://localhost:15672, to inspect the exchange, queues and bindings created +by {{attr.BRAND}} by default. + +## Queries + +Publishing **queries** is a way for your application to ask for information that +it may need in order to accomplish tasks. Queries express a _need_, and are not +addressed to any specific service or component. + +{{attr.BRAND}} makes it really really easy, to create and publish a query using +the `QueryBuilder`. + +<<<@../../examples/myapp/src/main/java/app/Queries.java#query{java} + +::: info Note +We are using the `@Order` annotation in our example only to ensure that +responses are built and registered before queries, when they are built +in one and the same app. +::: + +::: tip <1> +Initiates a query for the term `marco`, with any results being consumed as, +or _mapped_ to, the type `String.class`. Returned results are always +gathered in a collection. Either **none, one or many** elements may be +returned. +::: + +::: tip <2> +Queries require a timeout, here we set it to `1000L` milliseconds. This +means that this specific query will **always** block for 1 second. +::: + +::: tip <3> +The query may not receive any responses, so it _always_ needs to specify +how that case should be handled. Default here is an empty collection, of +the declared return type `String.class`. +::: + +_Hopefully this shows, how concise and powerful the `QueryBuilder` is, dealing +with results mapping, fault tolerance and default values in just a couple of +lines of code._ + +If you run the application now, it will publish a **query** to the message +broker, which we can see in the logs. + +```sh +$ mvn spring-boot:run +... +c.s.queryresponse.RabbitFacade : |<-- Published query: marco - (Body:'{}' MessageProperties [headers={x-qr-published=1589642002076}, replyTo=94f0fff4-c4f3-4491-831d-00809edb6f95, contentType=application/json, contentLength=2, deliveryMode=NON_PERSISTENT, priority=0, deliveryTag=0]) +``` + +At the moment there are no responses to be consumed, so after blocking for 1 +second, nothing is printed `STDOUT`. + +## Responses + +Building services, medium, large or _micro_ (who cares), that publish +**responses** to queries is also really easy with {{attr.BRAND}}, using the +`ResponseBuilder`. + +<<<@../../examples/myapp/src/main/java/app/Responses.java#response{java} + +::: tip <1> +Initializes a response to queries for `marco`, providing the type-hint on +how to map entries in the response. Set to `String.class` here. +::: + +::: tip <2> +The response `withAll()` will publish all elements in one single response. +::: + +::: tip <3> +And finally this response is provided the elements `"polo", "yolo"` as the +actual data to publish. _The builder varags method, used here, is mostly +for trying out {qr-name}, or for static responses._ +::: + +_Again, the builder makes it really easy to create a responding service, without +any special setup or complicated configurations._ + +Now if you run the application again, with the response component registered +before the query publisher, it will publish the response. + +```sh +$ mvn spring-boot:run +... +c.s.queryresponse.RabbitFacade : |<-- Published query: marco - (Body:'{}' MessageProperties [headers={x-qr-published=1589642489894}, replyTo=c77a8a1d-c959-4f2a-bd51-85b7e6b5b69b, contentType=application/json, contentLength=2, deliveryMode=NON_PERSISTENT, priority=0, deliveryTag=0]) +c.s.queryresponse.Response : |--> Consumed query: marco +c.s.queryresponse.RabbitFacade : |<-- Published response: c77a8a1d-c959-4f2a-bd51-85b7e6b5b69b - (Body:'{"elements":["polo","yolo"]}' MessageProperties [headers={x-qr-published=1589642489941}, contentType=application/json, contentEncoding=UTF-8, contentLength=28, deliveryMode=NON_PERSISTENT, priority=0, deliveryTag=0]) +c.s.queryresponse.Query : |--> Received response message: MessageProperties [headers={x-qr-published=1589642489941}, contentType=application/json, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=NON_PERSISTENT, priority=0, redelivered=false, receivedExchange=, receivedRoutingKey=c77a8a1d-c959-4f2a-bd51-85b7e6b5b69b, deliveryTag=1, consumerTag=amq.ctag-Q_ghWp4TWU9EYhi_rqErcg, consumerQueue=c77a8a1d-c959-4f2a-bd51-85b7e6b5b69b] +marco? polo +marco? yolo +``` + +Now you can see a full roundtrip of the **query** being published and consumed, +and the **response** being published and also consumed. And the finished output +is "polo" and "yolo" printed on `STDOUT`. diff --git a/xdocs/guide/the-example-revisited.md b/xdocs/guide/the-example-revisited.md new file mode 100644 index 00000000..c0de7da9 --- /dev/null +++ b/xdocs/guide/the-example-revisited.md @@ -0,0 +1,150 @@ +--- +outline: deep +--- + +# The example revisited + +Let's examine one of the most powerful aspects of using the Query/Response +pattern. If we think back to our [initial example](./what-is-query-response.md) +we published a query for books in the sci-fi genre. + +``` +query: books.sci-fi +reply-to: library/books.sci-fi#42 +``` + +We also learned that responses may come from different sources, with different +payloads and we are responsible for dealing with validation and duplicates etc. + +The query in this example uses only some minimal semantics to express the +genre of books requested, the term `sci-fi`. This is part of a contract from +our domain, together with rules on how any result payload should be presented. +The list of strings within quotes are not by accident, it is also by design. + +The Query/Response pattern does not enforce any structural rules for query, +address or response syntax. This must come from designers and developers. _I +would suggest, using [Domain Driven Design](https://en.wikipedia.org/wiki/Domain-driven_design) +to leverage the power of a ubiquitous language in the queries_. + +All this together puts us in a position to allow change and evolution in our +system. + +## A better library protocol + +We have agreed on supporting _stars_ for book ratings, and different teams +scramble to their stations to extend for the new feature. + +We saw earlier that data returned was formed as a list of quoted strings, and +the contract for parsing was: "first quoted string per line is book title". + +``` +body: + "Neuromancer" +``` + +That rule and the capability to extend it, made it possible to agree on a new +optional format: "trailing key-values are properties". For example: + +``` +body: + "Neuromancer" isbn:9780307969958 stars:4 +``` + +This is great. Let's get to work. + +## Top-3 books have stars + +``` +query: books.sci-fi +reply-to: library/books.sci-fi#77 +``` + +At a later time a new query for science fiction books is published. Now, we +still must not assume anything about the service or collaborator publishing +the query. It may be that we have a new service running in our system, not yet +live, or an updated version of the first one - we don't need to know. + +``` +response: library/books.sci-fi#77 +body: + "Neuromancer" stars:3 + "Snow Crash" stars:5 + "I, Robot" stars:4 +``` + +The first response looks great, it's using the new extended protocol and +provides star-ratings with the top-3 sci-fi book list. + +## One of each flavour + +Another response is consumed: + +``` +response: library/books.sci-fi#77 +body: + "I, Robot" + "The Gods Themselves" + "Pebble in the Sky" +``` + +Oh, ok seems that we've received a response with only Asimov books again, and +sadly no stars. Luckily the protocol rules allows us to still use the response +if we choose to. + +``` +response: library/books.sci-fi#77 +body: + "I, Robot" stars:2 + "The Gods Themselves" + "Pebble in the Sky" stars:5 +``` + +And what is this now. We've consumed yet another response and it appears to be +the Asimov list again, but this time with star-ratings, but only for a few +titles. + +This is quite normal and shows us a really important and valuable aspect of +the Query/Response pattern. If we would pull the curtain back a bit, it could +be reasonable to assume that the publisher of Asimov books now exists in 2 +distinct versions. One supports the new updated format, and has a couple of +star-ratings set. The other appears to be the _older_ version. + +We have effectively seen how response publishers can evolve, and even exist +side-by-side, if care is taken to design a suitable payload protocol. + +_The backward compatibility of the payload format is not at all required in the +Query/Response pattern. Implementations could use version tags or classifiers +to check for compatibility at the consumer side._ + +::: warning Important! +The key point here is, the consumer is still responsible for asserting the +usefulness and value of the response information. Parsing, validating or +checking for version compatibility is required. +::: + +## Out with the old + +Let's jump forward and say that at some later time, the query for sci-fi books +is published again. + +``` +query: books.sci-fi +reply-to: library/books.sci-fi#88 +``` + +And this time, the only consumed response with Asimov books is the following: + +``` +response: library/books.sci-fi#88 +body: + "I, Robot" stars:3 + "The Gods Themselves" stars:3 + "Pebble in the Sky" stars:5 +``` + +We can almost certainly conclude that the original version of the Asimov +book service has been shut down. + +Again we can see how the Query/Response pattern helps in coping with a natural +evolution of the system. Services can be added, removed or upgraded at any +time. diff --git a/xdocs/guide/what-is-query-response.md b/xdocs/guide/what-is-query-response.md new file mode 100644 index 00000000..d56f4103 --- /dev/null +++ b/xdocs/guide/what-is-query-response.md @@ -0,0 +1,216 @@ +--- +outline: deep +--- + +# What is Query/Response? + +Query/Response is an asynchronous non-blocking messaging pattern for building +highly decoupled evolving service architectures. + +## A simple example + +Let's learn about the Query/Response pattern by walking through a small +fictional example (no pun intended). The technical context is _messaging_ and +hints at some type of broker-based setup - in theory though, any asynchronous +communication could be used. The examples are only pseudo-code and plain-text +data, to keep things simple. + +### Any good sci-fi books out there? + +Let's publish a query. + +``` +query: books.sci-fi +reply-to: library/books.sci-fi#42 +``` + +The structure above captures all the basic components that a query should +communicate. The term `books.sci-fi` expresses the published _need_, and we +can easily understand that it's a _request_ for science fiction books. + +_The dot-notation is not at all required, the query can use any syntax that +fits the platform or programming language._ + +The query has an address where responses should be sent back to: +`library/books.sci-fi#42`. This is really important, not only in order to +receive responses, but also to avoid coupling the sender to the query. We +don't need to state who's publishing the query. The `reply-to` is just an +address, a location or _mailbox_ that can be used for replies. + +The address is only for this particular query, and it is made to be unique. +In this example `library/books.sci-fi#42` describes a topic `library`, and +then the unique mailbox or queue for the query with a hash-code +`books.sci-fi#42`. + +### The current top-3 books + +``` +response: library/books.sci-fi#42 +body: + "Neuromancer" + "Snow Crash" + "I, Robot" +``` + +We're in luck. We got a response! The information above represents a response +to the query we published. It's sent to the address from the query, and carries +a body or payload of information which may be of interest to us. + +The response does not have to say who it's from. This allows us to think about +exchange of information, without the notion of: _"A sends a request to B, +which responds to A"_. We are making sure that the services are decoupled from +each other, by letting the response be an _optional_ message, sent to the +_address_ instead of a reply to the _sender_. More about this later. + +### The Asimov collection + +Since our query was published as a notification, we're not bound to a single +reply. We can keep on consuming any number of responses that are sent to the +address we published. + +``` +response: library/books.sci-fi#42 +body: + "I, Robot" + "The Gods Themselves" + "Pebble in the Sky" +``` + +In this response we received a list of book titles which all have the same +author. The previous was a list with popular books. This reply even has one +entry which was already in the first response we received. + +This is of course not a problem, and it shows us a couple of important things. +Responses may come from different sources and contexts. This means that the +consumer of a response will have to assert the value or _usefulness_ of the +received information, and decide how to handle it. + +::: warning Important +The structure of a response should of course conform to some common, agreed +upon, format or data-shape. More on this later. +::: + +Considering all this, we need to remember [Postel's Law](https://en.wikipedia.org/wiki/Robustness_principle). Information should be liberally handled (interpreted), but publishing should be +done more conservatively. As a consumer of responses we just can't have a +guarantee that the information received is valid, well formed or not malicious. +We have to consume, convert and validate with great care. The decoupling in +the Query/Response patter has a price, and this is one part of it. + +::: danger Consideration +But is a published REST-endpoint, for POST requests, that much better? I +would argue that we still have the same requirements. To be able to handle +requests liberally, we have to convert and validate, with great care. But +we are coupling the client and server to each other and, what is perhaps +even worse, we're actually allowing the client to control the writing of +information inside the server. We have at least surrendered to that model +of thinking. The POST is a write operation! +::: + +_To really think and reason about who's controlling the write operation, can +be a very powerful concept in my view. And arguably, the further away we +can push this authority from the actual, internal act of writing, the less +we need to think about the complexity of both collaborators at once. This is +of course the essence of messaging. We could still achieve this with the REST +endpoint, but I would say that it is a lot harder to avoid thinking about +the effect of the returned response from the POST request. Even if it is +empty. We are caught in a lock-step or imperative model._ + +### No book lovers out there? + +Let's rewind the scenario a bit. Let's say we've just published the query, +but no responses arrive. What should we do? + +This is not a flaw in the design, but a specific part of the Query/Response +pattern. It is always up to the consumer of responses (the one that sent +the query), to decide _how long_ it will continue to read, or wait for any to +arrive at all. The pattern does not force this or make any promises. + +There might be responses. There may be none, a single one or a huge amount. +This is by design, and it forces us to think about important questions, early +in development. Fallback values, proper defaults, circuit-breakers and how +to deal with a flood of responses. + +::: warning Important +The most commonly asked question, by developers new to the Query/Response +pattern, is: "But what if there are no responses, what do I show the user?". +Exactly! Plan for that. This is something that should be considered early +in design and development. There might very well be a response, eventually, +but how long do you let the user wait for a result? +::: + +### Reprise, surprise + +Back to our original scenario. We've received both the top-3, as well as +a collection of Asimov books. And we're still open for more responses to the +published address. + +``` +response: library/books.sci-fi#42 +body: + "Neuromancer" + "Snow Crash" + "I, Robot" +``` + +Hey, what's this! We now received the same response and body payload, as +before. This is still not a problem, and it's not a flaw in the pattern. It +is not possible to avoid multiple responses, even from the same publisher. As +a consumer, we have to be ready to handle it. There is nothing wrong with this +response at all. + +_The consumer must handle this, and can't keep the entries in a simple list. If +we did, it would contain several duplicate entries. It would be enough to use +a set instead, so any duplicate entries would only be kept once._ + +### So, what's in the library? + +Let's see what we have. + +``` +query: library.sci-fi +reply-to: bookshelf/library.sci-fi#1337 +``` + +A new query is published and we understand the `query` term to mean that +there's an _interest_ in knowing what books are in the library. A successful +scenario could arrive at the following response being consumed. + +``` +response: bookshelf/library.sci-fi#1337 +body: + "Neuromancer" + "Snow Crash" + "I, Robot" + "The Gods Themselves" + "Pebble in the Sky" +``` + +Just as expected. + +### Inversion of flow + +What we've seen in this example scenario is actually an inversion of what +could have been implemented as a tightly coupled, chained set of synchronous +service calls: + +> A user whishes to view a list of science fiction books through the +> `Bookshelf` service, which needs to call the `Library` for the list. The +> `Library` service aggregates all sci-fi books by calls to 2 configured +> services: `Top-3` and `Authors`. Only after both service calls return, can +> the `Library` respond to the `Bookshelf` and the user is presented with +> a list of sci-fi books. + +In this type of system, not only are the calls aggregated in the total time, +effectively forcing the user to wait until all calls return, but also to the +availability of each service. This accumulates at the point of the user, +making it highly probable that viewing the list of books will fail. + +_There are many ways to work towards better and more resilient solutions, also +in the synchronous solution. I'm not trying to say that it is the wrong +model. The point I'm trying to make, is the very different way of thinking +that the Query/Response pattern forces us into from the start. Availability, +fallbacks, resilience and strict timeouts are called out as key-concepts._ + +_I hope this illustrates what's possible using this approach and that I've +sparked at least som interest in the Query/Response pattern. Later I will +extend on some of the features and caveats._ diff --git a/xdocs/index.md b/xdocs/index.md new file mode 100644 index 00000000..dbb23b2c --- /dev/null +++ b/xdocs/index.md @@ -0,0 +1,73 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: "Query/Response" + text: "For Spring® AMQP" + tagline: "A messaging pattern for building highly decoupled evolving service architectures." + + actions: + - theme: brand + text: What is Query/Response? + link: /guide/what-is-query-response + - theme: alt + text: Getting started + link: /guide/getting-started + - theme: alt + text: GitHub + link: https://github.com/olle/query-response-spring-amqp + +features: + - icon: + title: Resilient + details: Build safer and more resilient distributed services. + - icon: + title: Asynchronous + details: Get the benefits of an always async approach to data exchange. + - icon: + title: Decoupled + details: Ensure decoupling of components. Create scalable solutions. + - icon: + title: Evolving + details: Be better prepared for system evolution. +--- + + + +## Change the way you think and design, by using Query/Response for Spring AMQP. + +_Sometime around 2015 I came across a presentation with [Fred George](https://twitter.com/fgeorge52), +about the [Challenges in Implementing Microservices](https://youtu.be/yPf5MfOZPY0). +It's a great talk, with lots of good and relevant information. Experience comes +from learning through failures, and at this point in time I had just learned a +hard lesson about the problems with distributed services and blocking API calls. +I had seen how latencies would go up and availability go down the drain, as +calls from service A to B were actually depending on service B calling service +C, calling service D. It was a mess._ + +_In his talk George lands at the question "Synchronous or Asynchronous?" +and proceeds to describe, what he calls, the "Needs Pattern". Service A would, +instead of calling service B, publish a **query**, and service B would listen +for it and send back a **response**. After hearing this I began to think a lot +about the effects of moving to asynchronous communication between services. +There was clearly a lot more there than just decoupling. Something more +fundamental._ + +_The **Query/Response** pattern, that I arrived at, challenges developers to +really think hard about the responsibilities and autonomy of services. It +provides very few guarantees, which will force decisions around resilience +and availability at a much earlier stage in the design and development process. +It literally turns things around - an inversion of responsibility - which I +truly believe we can benefit from._ + +_Olle Törnström, 2019_ + + diff --git a/xdocs/reference/developers-reference.md b/xdocs/reference/developers-reference.md new file mode 100644 index 00000000..a2e1c2a5 --- /dev/null +++ b/xdocs/reference/developers-reference.md @@ -0,0 +1,326 @@ +--- +outline: deep +--- + + + +# Developers Reference + +## Overview + +The goal of {{attr.BRAND}} is to provide developers with tools that are easy to use +and understand. We believe that a procedural and imperative style of writing +programs, or thinking about tasks in programs, is broadly understood and a +very valuable model. With {{attr.BRAND}} we try to support this, rather than introducing +any new concepts for _streams_, _futures_ or _promises_. + +With {{attr.BRAND}} developers should feel enabled to write code in a _normal_ way. +However, it is our mission to raise awareness of things that are hard to +consider, when building [distributed systems](https://en.wikipedia.org/wiki/Distributed_computing). +The tools try to convey these considerations, by making them transparent and +part of the API. + +In the next couple of sections we'll look closer at the `QueryBuilder` and the +`ResponseBuilder` types. We'll discuss how to use them in detail, and try to +explain the concepts behind them, and the intention of their implementation. + +## `QueryBuilder` + +The `QueryBuilder` class is a central point of entry, and provides a fluent +builder-API, for publishing queries. It's provided as a bean, by enabling +{{attr.BRAND}}, using the `@EnableQueryResponse` annotation. It may be injected +as a dependency to provide access from methods in any Spring component. + +We recommend injecting it via the component constructor, and keeping it as a +private field. The `findAuthors()` method below, shows how to access the +`queryBuilder` field in order to publish a query. + +<<<@../../examples/querying/src/main/java/examples/Authors.java#class{java} + +In the example above, the published query is defined by the string **term** +`"authors"`. This is how the most basic contract of Query/Response is defined. +Any string or text term may be published as a query. + +The second argument is the expected type of any received response elements. It +is not published with the query, but rather used to coerce or interpret any +received responses. This means that regardless of the payload of any response, +in this case {{attr.BRAND}} will attempt to read the response elements as the +declared type `String.class`. + +Queries are built and published using the `queryFor(..)` _initial_ method. +Any following call to one of the _terminal_ methods `orEmpty()`, +`orDefaults(..)` and `orThrows(..)` will build and execute the query, and block +on the calling thread. + +Since the call above to `orEmpty()` blocks the thread, users have to specify +one or more query _conditionals_. In the example above, the call to +`waitingFor(..)` defines that the call will block for around 800 milliseconds. + +Constructing queries with the `QueryBuilder` revolves around creating a +composition of _initial_, _conditional_, an optional _informal_ and +exactly one _terminal_ method call. In the table below is a short review of the +different builder methods and their types. + +### `QueryBuilder` fluid API method types + +| Method | Type | Description | +| ------------------- | ------------- | --------------------------------------------------------------- | +| `queryFor(..)` | _initial_ | Creates a new builder for a query | +| `waitingFor(..)` | _conditional_ | Specifies the waiting/blocking condition | +| `takingAtMost(..)` | _conditional_ | Sets a limit condition, a maximum | +| `takingAtLeast(..)` | _conditional_ | Sets a limit condition, a minimum | +| `orEmpty()` | _terminal_ | Terminates with empty, after conditionals are evaluated | +| `orDefaults(..)` | _terminal_ | Terminates with some defaults, after conditionals are evaluated | +| `orThrow(..)` | _terminal_ | Terminates by throwing, after conditionals are evaluated | +| `onError(..)` | _informal_ | Allows for explicit logging etc. | + +Let's take a closer look at each of the builder method types. + +### _Initial_ methods + +At the moment there's only one _initial_ method and it's declared as: + +```java +public ChainingQueryBuilder queryFor(String term, Class type) +``` + +So we can query for any `String` **term** and given the expected mapped or +coerced **type** as a `Class`. The returned `ChainingQueryBuilder` +provides the capabilities of the fluid API. + +### _Conditional_ methods + +All _conditional_ properties can be composed together by the `QueryResponse` +builder API, to define whether a query is successful or not. If an executing +query is completed in a _successful_ way, fulfilling the _conditionals_, it will +return and not consume any more responses. + +- `waitingFor(..)` - defines a timeout _conditional_. The built query will + evaluate as _successful_ if _any_ responses were consumed after the + (approximate) given time limit has elapsed. There are a few different methods + declared, to specify the timeout: + + - `waitingFor(long millis)` + - `waitingFor(long amount, TemporalUnit timeUnit)` + - `waitingFor(Duration duration)` + +- `takingAtMost(int atMost)` - defines a limiting _conditional_ on the + aggregated number of received elements. The built query evaluates to + _successful_, and returns, when the given amount is reached. + +- `takingAtLeast(int atLeast)` - defines a minimum _conditional_ on the number + of received element. The built query evaluates to _successful_, only if at + least the given number of elements can be consumed. + +### _Terminal_ methods + +Only one _terminal_ method can be invoked on the builder, per query. It +will ensure that the query is built and executed. All _terminal_ methods are +declared to return `Collection` where the type parameter `` is given +in the _initial_ method `type` parameter. + +- `orEmpty()` - defines the query to return an empty `Collection` in case the + _conditionals_ do not evaluate to _successful_. + +- `orDefaults(..)` - defines the query to return with some provided _defaults_ + in case the _conditionals_ do not evaluate to _successful_. There are a couple + different methods declared for defaults: + + - `orDefaults(Collection defaults)` - set at _call-time_. + - `orDefaults(Supplier> defaults)` - supplied lazily at _run-time_. + +- `orThrow(..)` - defines the query to throw an exception in case the + _conditionals_ do not evaluate to _successful_. + +::: warning Careful +Note the difference in _call-time_ and _response-time_ - since the call to the +_terminal_ method is a blocking call, any fetched results as defaults are +prepared as the query is built. In order to dynamically provide better defaults +at _run-time_, use the lazy supplier instead. +::: + +### _Informal_ methods + +Currently there's only one _informal_ builder method, allowing for extended +logging or information capture, in case the query fails or an exception is +thrown. + +```java +public ChainingQueryBuilder onError(Consumer handler) +``` + +::: tip +Try to think more about how the `QueryBuilder` API covers the exceptional +query-cases, as part of the composition of _conditionals_. If clients try +to use _terminals_ that provide sensible defaults, it may not be necessary +to build other types of complex recovery or retries. +::: + +### `QueryBuilder` examples + +Below are some examples of how the different `QueryBuilder` API methods can be +combined. + +Using `takingAtMost(..)`, combined with `waitingFor(..)`, preserves system +resources and the client can be protected from consuming too much data. + +```java +return queryBuilder.queryFor("authors", String.class) + .takingAtMost(10) + .waitingFor(800) + .orDefaults(Authors.defaults()); +``` + +It is possible to express constraints at the integration point, also when using +{{attr.BRAND}}, throwing on an unfulfilled query, as an option to more lenient +handling with defaults. + +```java +return queryBuilder.queryFor("offers/rental", Offer.class) + .takingAtLeast(10) + .takingAtMost(20) + .waitingFor(2, ChronoUnit.SECONDS) + .orThrow(TooFewOffersConstraintException::new); +``` + +The _informal_ builder feature, allows for transparency into queries that may +have to be observed. + +```java +return queryBuilder.queryFor("offers/rental", NewOffer.class) + .takingAtLeast(3) + .waitingFor(400) + .onError(error -> LOG.error("Failure!", error)) + .orThrow(TooFewOffersConstraintException::new); +``` + +## `ResponseBuilder` + +Another entry-point into {{attr.BRAND}} is the `ResponseBuilder`. It provides a +fluid builder-API that allows users to create responding services or components. + +It is also provided as a bean, when using the `@EnableQueryResponse` annotation +in a Spring application. It can easily be injected as a dependency to provide +access from methods in Spring components. + +The `respondWithAuthors()` method below, shows how the injected builder is used +to create a responding service. It is invoked by the Spring application context, +on the `ApplicationReadyEvent` event. + +<<<@../../examples/responding/src/main/java/examples/OnlyThreeAuthors.java#class{java} + +In the example above the responding service is defined by calling the builder +method `respondTo(..)` with the query **term** parameter `"authors"`. It will +be bound to publish the given 3 authors as `String.class` entries, whenever it +consumes a query for the matching string **term** `"authors"`. + +This is the most basic premiss of Query/Response, that any string or text term +may be interpreted as a query - it is however up to the response publisher to +determine what the query means. + +::: tip +We've tried to provide information around the Query/Response _protocol_ and +philosophy in the later chapter on [The Query/Response Protocol](./the-query-response-protocol.md). +Go there to find out more. +::: + +The second parameter is the the type of each element, that will be published in +the response. It is given both as a type hint for the compiler, as well as a +parameter to the data mapper. Here it's trivial, the three authors are given as +`String.class` entries. + +::: info Note +The data mapper mentioned above, is in fact the +`com.fasterxml.jackson.databind.ObjectMapper` and {{attr.BRAND}} currently uses +JSON as the transport format. This means that type hints, JSON mapping +configuration annotations or custom mappings will apply. However as data +mapping on the consumer side is done by coercion, the published format +must conform to some agreed upon standard, shape or protocol. +::: + +Response publishers are built using the `respondTo(..)` _initial_ method. Any +following call to one of the _terminal_ methods `from(..)` or `suppliedBy(..)` +will create and register it, as its own consumer in another thread. The +builder call returns immediately. + +The `ResponseBuilder` comes with some methods to allow for _partitioning_ or +_batching_, which can be used to control the transfer of data to some degree. + +The table below shows a summary of the builder methods and types. + +### `ResponseBuilder` fluid API method types + +| Method | Type | Description | +| ------------------- | ---------- | ------------------------------------------- | +| `respondTo(..)` | _initial_ | Creates a new builder for a query | +| `withAll()` | _batching_ | Specifies NO batches | +| `withBatchesOf(..)` | _batching_ | Sets the batch size of responses | +| `from(..)` | _terminal_ | Terminates with some given response data | +| `suppliedBy(..)` | _terminal_ | Terminates with some supplied response data | + +Let's take a closer look at each of the builder method types. + +### _Initial_ methods + +At the moment there's only one _initial_ method for building responses. It is +declared as: + +```java +public ChainingResponseBuilder respondTo(String term, Class type) +``` + +So we can create a response for any `String` **term** and declare that we intend +to publish elements of some **type** given as a `Class`. The returned +`ChainingResponseBuilder` provides the capabilities of the fluid API. + +### _Batching_ methods + +Control over how response elements are published can be made by using the +_batching_ methods that the builder provides. + +- `withAll()` - defines that **no** batching should be used, and will publish + all given elements, or try to drain a supplied `Iterator` all at once. + +- `withBatchesOf(int size)` - defines a batch size, which the response publisher + will use, to create a series of response messages, with up-to the given `size` + of elements. + +### _Terminal_ methods + +Only one _terminal_ method can be called on the builder, per response. It will +ensure that a responder is created and added as a query-consumer, a subscriber +to the query **term** as a topic. It is not attached to the calling thread, so +the builder call always returns after the _terminal_ call. + +- `from(..)` - declares the source for the provided response data elements. It + is declared in a few different ways, for alternative use: + + - `from(T... elements)` - vararg elements + - `from(Collection elements)` - provided collection at _build-time_ + - `from(Supplier> elements)` - supplied iterator at _build-time_ + +- `suppliedBy(Supplier> elements)` - declares that response data + is supplied at _run-time_. + +### `ResponseBuilder` examples + +Batch responses provide developers with more options to tune and throttle a +system using Query/Response across many services. It may tune and change the profile +of resource use, in a network. + +```java +responseBuilder.respondTo("offers/monday", Offer.class) + .withBatchesOf(20) + .from(offers.findAllOffersByDayOfWeek(Calendar.MONDAY)); +``` + +Dynamic responses are easy to build, with an API that suits modern Java, using +lazy calls to suppliers of data. + +```java +responseBuilder.respondTo("users/current", Token.class) + .withBatchesOf(128) + .suppliedBy(userTokenService::findAllCurrentUserTokens); +``` diff --git a/xdocs/reference/query-response-maturity-model.md b/xdocs/reference/query-response-maturity-model.md new file mode 100644 index 00000000..9fa59b67 --- /dev/null +++ b/xdocs/reference/query-response-maturity-model.md @@ -0,0 +1,64 @@ +# Query/Response Maturity Model + +Just like with the [Richardson Maturity Model](https://martinfowler.com/articles/richardsonMaturityModel.html), +I've identified an evolution of maturity around the acceptance, use and +implementation of Query/Response. It describes the benefits, opportunities and +also complexities, pretty well. + +## Level 0 - Purgatory + +All communication and exchange is bound to fixed, configured, service end- +points. Synchronous blocking calls exchange information based on formats +declared in project Wiki-pages or Word-documents. Most solutions are stateless, +with I/O bound performance. Changes typically require system wide, +synchronized, upgrades. This lead to development dropping in velocity, as each +module or team will find it hard or impossible to act independently of each +other. + +## Level 1 + +Using the Query/Response pattern for the first time often leads to healthy +temporal decoupling pretty quick. But with a lot of code still written with +a synchronous model in mind, the data exchange tend to look a bit like _sync_. +Solutions move towards being stateful, but loosen their I/O-bound performance +characteristics. It's hard for developer to think about queries and responses +not coming from known components. Already at this level teams and modules gain +a lot in the capability to move independently. Releases and deployment is +practically not a tangle any more, although the view on evolutionary +data-structures or protocols for data, may lag behind and still be +Wiki/Document-based. + +## Level 2 + +At this level a deeper insight into the value of a proper data-structure or +protocol for payload, which can evolve as required, is often gained. With +this comes the extended benefit of seamless upgrades and service evolution. +Developers get to experience how responsibilities can move without breaking +or changing any integration code - response publishers can change owners and +location. + +## Level 3 + +More and more ideas around reactivity and flexibility begin to take form. +Events can immediately trigger queries which may enrich a local context based +on current needs. This moves the design and use beyond a system using sync, +and durable persistent state, to a more ephemeral and _living_ model. The data +structure of payloads tend to be less bound to strict _types_ and more +malleable _data shapes_. + +## Level 4 and beyond... + +Information exchange using the Query/Response pattern allows for almost +limitless evolution of services, or components, no longer bound to versions or +availability. The structure of any data is also very dynamic, information can +be partial, enriched, or come in different sets, from different publishers. No +schema is required at this level, but _data shapes_ are used, which can be +embraced by all collaborators in the architecture. Queries are sent and +responses consumed, sometimes within deliberate timeouts; take-until semantics. +This way modules can provide, and fulfill, explicit SLAs if required. + +::: info +This is of course not supposed to be taken too seriously, but the maturity +levels describes a journey, from a strict and stale model, into one where +evolution and change is quite normal. +::: diff --git a/xdocs/reference/the-query-response-protocol.md b/xdocs/reference/the-query-response-protocol.md new file mode 100644 index 00000000..13ce9810 --- /dev/null +++ b/xdocs/reference/the-query-response-protocol.md @@ -0,0 +1,167 @@ +# Query/Response Protocol + +I'd like to describe the Query/Response pattern in a more formal but not +too strict way, since it's not in any way some type of _standard_ or +_protocol_. This is a pattern derived from the general idea of expressing a +_need_ or _demand_, as previously told. It is shaped here, into a specific +version, or flavour, in the **Query/Response pattern**. It simply contains +my recommendations and suggestions on rules or principles to follow. + +Please, take what you like, leave the rest, and extend as you seem fit. + +Use of the keywords: "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", +"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" are intended +to follow the definitions of [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). + +## Intent + +The Query/Response pattern aims to describe a model for information sharing +in a distributed system. It does so by using strong decoupling of system +actors and establishing asynchronous message-based high-level data exchange, +as the only means of communication. + +The following specifications tries to provide a set of rules and guides, +which can be used as an authoritative source for developer, implementing the +pattern. + +## Components and Collaborators + +| Name | Type | Description | +| ----------- | -------- | ----------- | +| `Query` | message | Very small, published notification. +| `Response` | message | Carries information as payload. +| `Address` | location | Reference to "a mailbox" +| `Publisher` | actor | Initiates _publish_ method calls. +| `Consumer` | actor | Accepts _consume_ method calls. + +### `Query` + +A notification that expresses a specific _need_ or _whish_, which can be +fulfilled by a response, published to a specified return address. The query +MUST state its _need_ or _whish_ in an interpretable way. It may use any +suitable syntax, semantics or language. Most commonly a simple string or term +is used, similar to a message subject, -name or an event _routing-key_. A +query MUST specify an address for responses, which SHOULD be _appropriate_ +for the stated query and, technically _available_, as the query is created. + +::: tip Recommendation +I very much recommend creating queries with expressions or terms from a +domain specific, or ubiquitous language. This allows for broader understanding +and involvement of stakeholders. Keeping queries human readable makes sense. +It's often desirable to use structured terms, with semantics, such as +filters or parameters. This is quite common and not at all bad. +::: + +### `Response` + +A notification, published, as a response to a query, optionally carrying an +information- or data-payload. A response MUST NOT be sent without an intent to +_answer_ a specific query (use event notifications for that). The response +MUST be sent to the address of the query it responds to, without manipulating +it. A response SHOULD carry an appropriate information- or data-payload, with +the intent to answer the query it responds to. Note that this is not a strict +requirement. Responses SHOULD be sent within an appropriate time frame of +seeing a query. + +::: tip +In most cases it's desirable to publish a response as quick as possible, +after consuming a query. +::: + +### `Address` + +Describes and designates an addressable _location_ with the capability to +receive and handle responses. Typically a messaging _mailbox_ or a queue. The +address MUST NOT describe a system actor or collaborator, but instead ensure +decoupling between a publisher and a consumer. + +::: tip +In messaging or broker based systems, the address is typically a routing key, +topic or a queue-name. +::: + +### `Publisher` + +An actor that initiates the publishing of a notification, either a query or +a response depending on its current role. The publisher MUST NOT be responsible +for the arrival of any published information. Publishers MUST NOT know any +consumers. + +::: info Note +The concrete _interpolated_ roles `Query-Publisher` and +`Response-Publisher`, does not have to be bound to a single or unique actor. +::: + +_It is open for the implementation of the Query/Response pattern to solve or +choose how it ensures delivery of messages, e.g. using a broker- or queue- +based messaging system or some other solution for asynchronous communication._ + +### `Consumer` + +An actor that willingly yields to the consumption of notifications, from some +external source, either a response or a query depending on its current role. +Consumers MUST NOT know any publishers. + +::: info Note +The concrete _interpolated_ roles `Query-Consumer` and +`Response-Consumer`, does not have to be bound to a single or unique actor. +::: + +## Methods and Actions + +_Nothing in the Query/Response pattern is synchronous, or based on the notion +of guaranteed delivery (or only-once semantics). The following structured +step-by-step description is only for documentation purposes, and does not, +in any way, define a sequence which can be relied upon._ + +### Prepare `Address` + +Before publishing a query, the query publisher SHOULD ensure that an +appropriate address, specified for the query, can be handled. + +::: info Note +Implementations are free to use a best-effort approach. It may be that the +only option is to use short-lived or temporary resources, which may or may +not fail to be allocated. Therefore there's no strict requirement to ensure +that the address can be handled. +::: + +### Publish `Query` + +The query publisher can, at any time, choose to publish a query. No ACK or +NACK will be provided and the query publisher MUST NOT assume that the query +has been consumed, or that a response will be returned at this time. The +publisher SHOULD consider the case where the query is lost, examine options +to detect and repair this, if possible; _timeouts, retries or fallbacks are +perhaps options to investigate_. + +### Consume `Query` + +A query consumer, that is willingly listening for queries, may at any time +receive, and choose to handle a query. Consuming queries is an unbound +operation. The consumer SHOULD handle queries with an intent to provide a +response, or ignore the query. A consumer MAY decide to publish none, one or +any number of responses to the query - it is optional. A consumer MAY at any +time choose to stop listening for queries. + +::: tip +Please note that the Query/Response pattern does not protect against +query consumers with harmful intent. Implementations should consider issues +like security, encryption and trust as extensions to it. +::: + +### Publish `Response` + +A response publisher MUST use the provided address of the query it responds to, +when publishing responses. No ACK or NACK will be provided and the publisher +MUST NOT assume that the response has been delivered, arrived properly or +consumed. + +### Consume `Response` + +A response consumer, listening for responses at a previously created address, +MAY at any time receive one or several responses - or not at all. Consuming +responses is an unbounded operation. Any received response MAY have a payload +or body of information. The consumer SHOULD assert and validate any +transferred information with great care. A consumer MAY at any time choose to +stop listening for responses.