102 lines
2.7 KiB
JavaScript
102 lines
2.7 KiB
JavaScript
require('dotenv').config()
|
|
|
|
const algoliasearch = require('algoliasearch')
|
|
const glob = require('glob')
|
|
const path = require('path')
|
|
const matter = require('gray-matter')
|
|
|
|
// 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)
|
|
}
|
|
}
|