diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a9aba1865..03a60abf4d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -387,6 +387,22 @@ jobs: docker push hashicorp/consul-website fi + algolia-index: + docker: + - image: node:12 + steps: + - checkout + - run: + name: Push content to Algolia Index + command: | + if [ "$CIRCLE_REPOSITORY_URL" != "git@github.com:hashicorp/consul.git" ]; then + echo "Not Consul OSS Repo, not indexing Algolia" + exit 0 + fi + cd website/ + npm install + node scripts/index_search_content.js + # build frontend yarn cache frontend-cache: docker: @@ -708,6 +724,13 @@ workflows: branches: only: - master + + - algolia-index: + context: consul-docs + filters: + branches: + only: + - stable-website frontend: jobs: - frontend-cache: diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..b7ef8bc2b1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,217 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@algolia/cache-browser-local-storage": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.3.0.tgz", + "integrity": "sha512-91Cf3IPUk84PF2wvR8ys8XO42FqaJEtIh/dyR0WvwMdv0x13GORkAvoBJgkFI2wofZqUY86jNimvHWfsWzPQ+g==", + "requires": { + "@algolia/cache-common": "4.3.0" + } + }, + "@algolia/cache-common": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.3.0.tgz", + "integrity": "sha512-AHTbOn9lk0f5IkjssXXmDgnaZfsUJVZ61sqOH1W3LyJdAscDzCj0KtwijELn8FHlLXQak7+K93/O3Oct0uHncQ==" + }, + "@algolia/cache-in-memory": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.3.0.tgz", + "integrity": "sha512-8BZS5IFEtiSFkA6vNQUXJXIWABDbSanQdkGX5LArlhbCjuykZqF68yaCjXWG10EZTySnkZLmKc+5ozYVOktJaQ==", + "requires": { + "@algolia/cache-common": "4.3.0" + } + }, + "@algolia/client-account": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.3.0.tgz", + "integrity": "sha512-8LJSvWooc+fe+XZXeu+h4dhpo9lsu3sb7rV9cpPhymYSHgEJAHaDkZEcPM1u/PBMvFe0mZXaW6nabeb3jeIRcw==", + "requires": { + "@algolia/client-common": "4.3.0", + "@algolia/client-search": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/client-analytics": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.3.0.tgz", + "integrity": "sha512-BFH4ddyrqI2pE3bUctn5KtJgYqgvO0Ap9vJEHBNj6mjSKqFbTnZeVEPG3yWrOuWRCqPHR3ewcWRisNwJHG3+Mw==", + "requires": { + "@algolia/client-common": "4.3.0", + "@algolia/client-search": "4.3.0", + "@algolia/requester-common": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/client-common": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.3.0.tgz", + "integrity": "sha512-8Ohj6zXZkpwDKc8ZWVTZo2wPO4+LT5D258suGg/C6nh4UxOrFOp6QaqeQo8JZ1eqMqtfb3zv5SHgW4fZ00NCLQ==", + "requires": { + "@algolia/requester-common": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/client-recommendation": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-recommendation/-/client-recommendation-4.3.0.tgz", + "integrity": "sha512-jCMIAWPA2hsxc5CCtoTtQAcohaG+10CxXK122Tc47t4w1K8qzSJnCjC2cHvM4UNJO+k7NrmjOYW0EXp9RKc7SQ==", + "requires": { + "@algolia/client-common": "4.3.0", + "@algolia/requester-common": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/client-search": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.3.0.tgz", + "integrity": "sha512-KCgcIsNMW1/0F5OILiFTddbTAKduJHRvXQS4NxY1H9gQWMTVeWJS7VZQ/ukKBiUMLatwUQHJz2qpYm9fmqOjkQ==", + "requires": { + "@algolia/client-common": "4.3.0", + "@algolia/requester-common": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/logger-common": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.3.0.tgz", + "integrity": "sha512-vQ+aukjZkRAyO9iyINBefT366UtF/B9QoA1Kw8PlY67T6fYmklFgYp3LNH/e7h/gz0py5LYY/HIwSsaTKk8/VQ==" + }, + "@algolia/logger-console": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.3.0.tgz", + "integrity": "sha512-7pWtcv1cSSa7F48gRBOZLcEWN073+WbnKjbpRrIGej+abZppw/h+22jtVZZORC8EIjFffGqz2/2e6bZiX+Jg7A==", + "requires": { + "@algolia/logger-common": "4.3.0" + } + }, + "@algolia/requester-browser-xhr": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.3.0.tgz", + "integrity": "sha512-CpUwgQhXZsnZmjEd5DTwQv1BKQNCt83bzyVdUqvljsFxZOsNQacS6lOYs0B1eD18tKHCwVMuwbYqTaLPGBXTKQ==", + "requires": { + "@algolia/requester-common": "4.3.0" + } + }, + "@algolia/requester-common": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.3.0.tgz", + "integrity": "sha512-1v73KyspJBiTzfyXupjHxikxTYjh5MoxI6mOIvAtQxRqc4ehUPAEdPCNHEvvLiCK96iKWzZaULmV0U7pj3yvTw==" + }, + "@algolia/requester-node-http": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.3.0.tgz", + "integrity": "sha512-Hg9Y8sUeSGQgoO1FpoL5jbkDzCtXI/8HXHybU6bimsX93DAz3HZWaoQFKmIpQDNhQ8G9FLgAtzDAxS6eckDxzg==", + "requires": { + "@algolia/requester-common": "4.3.0" + } + }, + "@algolia/transporter": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.3.0.tgz", + "integrity": "sha512-BTKHAtdQdfOJ0xzZkiyEK/2QVQJTiVgBZlOBfXp2gBtztjV26OqfW4n6Xz0o7eBRzLEwY1ot3mHF5QIVUjAsMg==", + "requires": { + "@algolia/cache-common": "4.3.0", + "@algolia/logger-common": "4.3.0", + "@algolia/requester-common": "4.3.0" + } + }, + "algoliasearch": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.3.0.tgz", + "integrity": "sha512-H2woXyqmd1nFYDrQKLZXgghNkLBTcBXJ7Q/bxQ+F9WWS4H0Kb7IlQvNi7bDzHyldhDhIthImaUwcKqr5iiyMFQ==", + "requires": { + "@algolia/cache-browser-local-storage": "4.3.0", + "@algolia/cache-common": "4.3.0", + "@algolia/cache-in-memory": "4.3.0", + "@algolia/client-account": "4.3.0", + "@algolia/client-analytics": "4.3.0", + "@algolia/client-common": "4.3.0", + "@algolia/client-recommendation": "4.3.0", + "@algolia/client-search": "4.3.0", + "@algolia/logger-common": "4.3.0", + "@algolia/logger-console": "4.3.0", + "@algolia/requester-browser-xhr": "4.3.0", + "@algolia/requester-common": "4.3.0", + "@algolia/requester-node-http": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, + "gray-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.2.tgz", + "integrity": "sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw==", + "requires": { + "js-yaml": "^3.11.0", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "requires": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + } + } +} diff --git a/website/.env b/website/.env index f29b5d725c..49d070016e 100644 --- a/website/.env +++ b/website/.env @@ -1,3 +1,6 @@ NEXT_PUBLIC_SEGMENT_WRITE_KEY='IyzLrqXkox5KJ8XL4fo8vTYNGfiKlTCm' NEXT_PUBLIC_BUGSNAG_CLIENT_KEY='01625078d856ef022c88f0c78d2364f1' NEXT_PUBLIC_BUGSNAG_SERVER_KEY='be8ed0d0fc887d547284cce9e98e60e5' +NEXT_PUBLIC_ALGOLIA_APP_ID=YY0FFNI7MF +NEXT_PUBLIC_ALGOLIA_INDEX=product_CONSUL +NEXT_PUBLIC_ALGOLIA_SEARCH_ONLY_API_KEY=5037da4824714676226913c65e961ca0 diff --git a/website/.gitignore b/website/.gitignore index 1d23ce1de1..507cbf4e57 100644 --- a/website/.gitignore +++ b/website/.gitignore @@ -3,3 +3,6 @@ node_modules .next out .mdx-data + +# As per Next.js conventions (https://nextjs.org/docs/basic-features/environment-variables#default-environment-variables) +.env*.local diff --git a/website/package-lock.json b/website/package-lock.json index 27015a8c9a..3f9f104413 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -4,6 +4,121 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@algolia/cache-browser-local-storage": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.3.0.tgz", + "integrity": "sha512-91Cf3IPUk84PF2wvR8ys8XO42FqaJEtIh/dyR0WvwMdv0x13GORkAvoBJgkFI2wofZqUY86jNimvHWfsWzPQ+g==", + "requires": { + "@algolia/cache-common": "4.3.0" + } + }, + "@algolia/cache-common": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.3.0.tgz", + "integrity": "sha512-AHTbOn9lk0f5IkjssXXmDgnaZfsUJVZ61sqOH1W3LyJdAscDzCj0KtwijELn8FHlLXQak7+K93/O3Oct0uHncQ==" + }, + "@algolia/cache-in-memory": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.3.0.tgz", + "integrity": "sha512-8BZS5IFEtiSFkA6vNQUXJXIWABDbSanQdkGX5LArlhbCjuykZqF68yaCjXWG10EZTySnkZLmKc+5ozYVOktJaQ==", + "requires": { + "@algolia/cache-common": "4.3.0" + } + }, + "@algolia/client-account": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.3.0.tgz", + "integrity": "sha512-8LJSvWooc+fe+XZXeu+h4dhpo9lsu3sb7rV9cpPhymYSHgEJAHaDkZEcPM1u/PBMvFe0mZXaW6nabeb3jeIRcw==", + "requires": { + "@algolia/client-common": "4.3.0", + "@algolia/client-search": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/client-analytics": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.3.0.tgz", + "integrity": "sha512-BFH4ddyrqI2pE3bUctn5KtJgYqgvO0Ap9vJEHBNj6mjSKqFbTnZeVEPG3yWrOuWRCqPHR3ewcWRisNwJHG3+Mw==", + "requires": { + "@algolia/client-common": "4.3.0", + "@algolia/client-search": "4.3.0", + "@algolia/requester-common": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/client-common": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.3.0.tgz", + "integrity": "sha512-8Ohj6zXZkpwDKc8ZWVTZo2wPO4+LT5D258suGg/C6nh4UxOrFOp6QaqeQo8JZ1eqMqtfb3zv5SHgW4fZ00NCLQ==", + "requires": { + "@algolia/requester-common": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/client-recommendation": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-recommendation/-/client-recommendation-4.3.0.tgz", + "integrity": "sha512-jCMIAWPA2hsxc5CCtoTtQAcohaG+10CxXK122Tc47t4w1K8qzSJnCjC2cHvM4UNJO+k7NrmjOYW0EXp9RKc7SQ==", + "requires": { + "@algolia/client-common": "4.3.0", + "@algolia/requester-common": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/client-search": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.3.0.tgz", + "integrity": "sha512-KCgcIsNMW1/0F5OILiFTddbTAKduJHRvXQS4NxY1H9gQWMTVeWJS7VZQ/ukKBiUMLatwUQHJz2qpYm9fmqOjkQ==", + "requires": { + "@algolia/client-common": "4.3.0", + "@algolia/requester-common": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, + "@algolia/logger-common": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.3.0.tgz", + "integrity": "sha512-vQ+aukjZkRAyO9iyINBefT366UtF/B9QoA1Kw8PlY67T6fYmklFgYp3LNH/e7h/gz0py5LYY/HIwSsaTKk8/VQ==" + }, + "@algolia/logger-console": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.3.0.tgz", + "integrity": "sha512-7pWtcv1cSSa7F48gRBOZLcEWN073+WbnKjbpRrIGej+abZppw/h+22jtVZZORC8EIjFffGqz2/2e6bZiX+Jg7A==", + "requires": { + "@algolia/logger-common": "4.3.0" + } + }, + "@algolia/requester-browser-xhr": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.3.0.tgz", + "integrity": "sha512-CpUwgQhXZsnZmjEd5DTwQv1BKQNCt83bzyVdUqvljsFxZOsNQacS6lOYs0B1eD18tKHCwVMuwbYqTaLPGBXTKQ==", + "requires": { + "@algolia/requester-common": "4.3.0" + } + }, + "@algolia/requester-common": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.3.0.tgz", + "integrity": "sha512-1v73KyspJBiTzfyXupjHxikxTYjh5MoxI6mOIvAtQxRqc4ehUPAEdPCNHEvvLiCK96iKWzZaULmV0U7pj3yvTw==" + }, + "@algolia/requester-node-http": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.3.0.tgz", + "integrity": "sha512-Hg9Y8sUeSGQgoO1FpoL5jbkDzCtXI/8HXHybU6bimsX93DAz3HZWaoQFKmIpQDNhQ8G9FLgAtzDAxS6eckDxzg==", + "requires": { + "@algolia/requester-common": "4.3.0" + } + }, + "@algolia/transporter": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.3.0.tgz", + "integrity": "sha512-BTKHAtdQdfOJ0xzZkiyEK/2QVQJTiVgBZlOBfXp2gBtztjV26OqfW4n6Xz0o7eBRzLEwY1ot3mHF5QIVUjAsMg==", + "requires": { + "@algolia/cache-common": "4.3.0", + "@algolia/logger-common": "4.3.0", + "@algolia/requester-common": "4.3.0" + } + }, "@ampproject/toolbox-core": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/toolbox-core/-/toolbox-core-2.3.0.tgz", @@ -2493,6 +2608,27 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" }, + "algoliasearch": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.3.0.tgz", + "integrity": "sha512-H2woXyqmd1nFYDrQKLZXgghNkLBTcBXJ7Q/bxQ+F9WWS4H0Kb7IlQvNi7bDzHyldhDhIthImaUwcKqr5iiyMFQ==", + "requires": { + "@algolia/cache-browser-local-storage": "4.3.0", + "@algolia/cache-common": "4.3.0", + "@algolia/cache-in-memory": "4.3.0", + "@algolia/client-account": "4.3.0", + "@algolia/client-analytics": "4.3.0", + "@algolia/client-common": "4.3.0", + "@algolia/client-recommendation": "4.3.0", + "@algolia/client-search": "4.3.0", + "@algolia/logger-common": "4.3.0", + "@algolia/logger-console": "4.3.0", + "@algolia/requester-browser-xhr": "4.3.0", + "@algolia/requester-common": "4.3.0", + "@algolia/requester-node-http": "4.3.0", + "@algolia/transporter": "4.3.0" + } + }, "ally.js": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/ally.js/-/ally.js-1.4.1.tgz", @@ -5521,6 +5657,11 @@ } } }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, "download": { "version": "6.2.5", "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz", diff --git a/website/package.json b/website/package.json index 86ab747843..55f70ff8ef 100644 --- a/website/package.json +++ b/website/package.json @@ -34,7 +34,10 @@ "@hashicorp/react-text-split-with-logo-grid": "^1.1.0", "@hashicorp/react-use-cases": "^1.0.4", "@hashicorp/react-vertical-text-block-list": "^2.0.1", + "algoliasearch": "^4.3.0", "babel-plugin-import-glob-array": "^0.2.0", + "dotenv": "^8.2.0", + "gray-matter": "^4.0.2", "imagemin-mozjpeg": "^8.0.0", "imagemin-optipng": "^7.1.0", "imagemin-svgo": "^7.1.0", diff --git a/website/scripts/index_search_content.js b/website/scripts/index_search_content.js new file mode 100644 index 0000000000..871b542dcf --- /dev/null +++ b/website/scripts/index_search_content.js @@ -0,0 +1,101 @@ +require('dotenv').config() + +const algoliasearch = require('algoliasearch') +const glob = require('glob') +const matter = require('gray-matter') +const path = require('path') + +// In addition to the content of the page, +// define additional front matter attributes that will be search-indexable +const SEARCH_DIMENSIONS = ['page_title', 'description'] + +main() + +async function main() { + const pagesFolder = path.join(__dirname, '../pages') + + // Grab all search-indexable content and format for Algolia + const searchObjects = glob + .sync(path.join(pagesFolder, '**/*.mdx')) + .map((fullPath) => { + const { content, data } = matter.read(fullPath) + + // Get path relative to `pages` + const __resourcePath = fullPath.replace(`${pagesFolder}/`, '') + + // Use clean URL for Algolia id + const objectID = __resourcePath.replace('.mdx', '') + + const searchableDimensions = Object.keys(data) + .filter((key) => SEARCH_DIMENSIONS.includes(key)) + .map((dimension) => ({ + [dimension]: data[dimension], + })) + + return { + ...searchableDimensions, + content, + __resourcePath, + objectID, + } + }) + + try { + await indexSearchContent(searchObjects) + } catch (e) { + console.error(e) + process.exit(1) + } +} + +async function indexSearchContent(objects) { + const { + NEXT_PUBLIC_ALGOLIA_APP_ID: appId, + NEXT_PUBLIC_ALGOLIA_INDEX: index, + ALGOLIA_API_KEY: apiKey, + } = process.env + + if (!apiKey || !appId || !index) { + throw new Error( + `[*** Algolia Search Indexing Error ***] Received: ALGOLIA_API_KEY=${apiKey} ALGOLIA_APP_ID=${appId} ALGOLIA_INDEX=${index} \n Please ensure all Algolia Search-related environment vars are set in CI settings.` + ) + } + + console.log(`updating ${objects.length} indices...`) + + try { + const searchClient = algoliasearch(appId, apiKey) + const searchIndex = searchClient.initIndex(index) + + await searchIndex.partialUpdateObjects(objects, { + createIfNotExists: true, + }) + + // Remove indices for items that aren't included in the new batch + const newObjectIds = objects.map(({ objectID }) => objectID) + let staleObjects = [] + + await searchIndex.browseObjects({ + query: '', + batch: (batch) => { + staleObjects = staleObjects.concat( + batch.filter(({ objectID }) => !newObjectIds.includes(objectID)) + ) + }, + }) + + const staleIds = staleObjects.map(({ objectID }) => objectID) + + if (staleIds.length > 0) { + console.log(`deleting ${staleIds.length} stale indices:`) + console.log(staleIds) + + await searchIndex.deleteObjects(staleIds) + } + + console.log('done') + process.exit(0) + } catch (error) { + throw new Error(error) + } +}