UNPKG

gatsby-plugin-typesense

Version:

A gatsby plugin to push site content to a Typesense Search cluster

176 lines (155 loc) 5.03 kB
const fs = require("fs").promises const cheerio = require("cheerio") const TypesenseClient = require("typesense").Client const TYPESENSE_ATTRIBUTE_NAME = "data-typesense-field" let utils = require("./lib/utils") function typeCastValue(fieldDefinition, attributeValue) { if (fieldDefinition.type.includes("int")) { return parseInt(attributeValue); } if (fieldDefinition.type.includes("float")) { return parseFloat(attributeValue); } if (fieldDefinition.type.includes("bool")) { if (attributeValue.toLowerCase() === "false") { return false; } if (attributeValue === "0") { return false; } return attributeValue.trim() !== ""; } return attributeValue; } async function indexContentInTypesense({ fileContents, wwwPath, typesense, newCollectionSchema, reporter, }) { const $ = cheerio.load(fileContents) let typesenseDocument = {} $(`[${TYPESENSE_ATTRIBUTE_NAME}]`).each((index, element) => { const attributeName = $(element).attr(TYPESENSE_ATTRIBUTE_NAME) const attributeValue = $(element).text() const fieldDefinition = newCollectionSchema.fields.find( f => f.name === attributeName ) if (!fieldDefinition) { const errorMsg = `[Typesense] Field "${attributeName}" is not defined in the collection schema` reporter.panic(errorMsg) return Promise.error(errorMsg) } if (fieldDefinition.type.includes("[]")) { typesenseDocument[attributeName] = typesenseDocument[attributeName] || [] typesenseDocument[attributeName].push(typeCastValue(fieldDefinition, attributeValue)) } else { typesenseDocument[attributeName] = typeCastValue(fieldDefinition, attributeValue); } }) if (utils.isObjectEmpty(typesenseDocument)) { reporter.warn( `[Typesense] No HTMLelements had the ${TYPESENSE_ATTRIBUTE_NAME} attribute, skipping page` ) return Promise.resolve() } typesenseDocument["page_path"] = wwwPath typesenseDocument["page_priority_score"] = typesenseDocument["page_priority_score"] || 10 try { reporter.verbose( `[Typesense] Creating document: ${JSON.stringify( typesenseDocument, null, 2 )}` ) await typesense .collections(newCollectionSchema.name) .documents() .create(typesenseDocument) reporter.verbose("[Typesense] ✅") return Promise.resolve() } catch (error) { reporter.panic(`[Typesense] Could not create document: ${error}`) } } exports.onPostBuild = async ( { reporter }, { server, collectionSchema, publicDir, rootDir, exclude, generateNewCollectionName = utils.generateNewCollectionName, } ) => { reporter.verbose("[Typesense] Getting list of HTML files") // backward compatibility rootDir = rootDir || publicDir const htmlFiles = await utils.getHTMLFilesRecursively(rootDir, rootDir, exclude) const typesense = new TypesenseClient(server) const newCollectionName = generateNewCollectionName(collectionSchema) const newCollectionSchema = { ...collectionSchema } newCollectionSchema.name = newCollectionName try { reporter.verbose(`[Typesense] Creating collection ${newCollectionName}`) await typesense.collections().create(newCollectionSchema) } catch (error) { reporter.panic( `[Typesense] Could not create collection ${newCollectionName}: ${error}` ) } for (const file of htmlFiles) { const wwwPath = file.replace(rootDir, "").replace(/index\.html$/, "") reporter.verbose(`[Typesense] Indexing ${wwwPath}`) const fileContents = (await fs.readFile(file)).toString() await indexContentInTypesense({ fileContents, wwwPath, typesense, newCollectionSchema, reporter, }) } let oldCollectionName try { oldCollectionName = ( await typesense.aliases(collectionSchema.name).retrieve() )["collection_name"] reporter.verbose(`[Typesense] Old collection name was ${oldCollectionName}`) } catch (error) { reporter.verbose(`[Typesense] No old collection found, proceeding`) } try { reporter.verbose( `[Typesense] Upserting alias ${collectionSchema.name} -> ${newCollectionName}` ) await typesense .aliases() .upsert(collectionSchema.name, { collection_name: newCollectionName }) reporter.info( `[Typesense] Content indexed to "${collectionSchema.name}" [${newCollectionName}]` ) } catch (error) { reporter.error( `[Typesense] Could not upsert alias ${collectionSchema.name} -> ${newCollectionName}: ${error}` ) } try { if (oldCollectionName) { reporter.verbose( `[Typesense] Deleting old collection ${oldCollectionName}` ) await typesense.collections(oldCollectionName).delete() } } catch (error) { reporter.error( `[Typesense] Could not delete old collection ${oldCollectionName}: ${error}` ) } } exports.onPreInit = ({ reporter }) => reporter.verbose("Loaded gatsby-plugin-typesense")