Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

atomic-algolia

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

atomic-algolia - npm Package Compare versions

Comparing version 0.2.1 to 0.3.0

lib/utils/actionAdd.js

98

lib/update.js

@@ -0,14 +1,14 @@

var actionAdd = require("./utils/actionAdd")
var actionUpdate = require("./utils/actionUpdate")
var actionDelete = require("./utils/actionDelete")
var algoliaSearch = require("algoliasearch")
var addAction = require("./utils/addAction")
var chalk = require("chalk")
var deleteAction = require("./utils/deleteAction")
var dotenv = require("dotenv").config()
var fs = require("fs")
var idsFromIndex = require("./utils/idsFromIndex")
var idsFromQuery = require("./utils/idsFromQuery")
var getLocalIndex = require("./utils/getLocalIndex")
var getRemoteIndex = require("./utils/getRemoteIndex")
var calculateOperations = require("./utils/calculateOperations")
var path = require("path")
var title = chalk`[{blue Algolia}]`
module.exports = function update(indexName, indexFile, cb) {
module.exports = function update(indexName, indexData, cb) {
try {

@@ -18,7 +18,4 @@ if (!indexName)

if (!indexFile)
throw new Error("Please provide `indexFile`")
if (!fs.existsSync(indexFile))
throw new Error("Index file `" + indexFile + "` not found")
if (!indexData)
throw new Error("Please provide `indexData`. A valid Javacript object or path to a JSON file.")

@@ -32,45 +29,54 @@ var client = algoliaSearch(

var index = client.initIndex(indexName)
var newIndex = JSON.parse(fs.readFileSync(path.resolve(indexFile), "utf-8"))
var newIndexIds = idsFromIndex(newIndex)
var newIndex = getLocalIndex(indexData)
idsFromQuery(index, function(err, res) {
if (err) throw err
return getRemoteIndex(index)
.then(function(oldIndex) {
// Figure out which records to add or delete
var operations = calculateOperations(newIndex, oldIndex)
// Figure out which records to add or delete
var operations = calculateOperations(newIndexIds, res)
if (verbose === true) {
console.log(title, `Adding ${operations.add.length} hits to ${indexName}`)
onsole.log(title, `Updating ${operations.update.length} hits to ${indexName}`)
console.log(title, `Removing ${operations.delete.length} hits from ${indexName}`)
console.log(title, `${operations.ignore.length} hits unchanged in ${indexName}`)
}
if (verbose === true) {
console.log(title, `Adding ${operations.add.length} hits to ${indexName}`)
console.log(title, `Removing ${operations.delete.length} hits from ${indexName}`)
console.log(title, `${operations.add.length} hits unchanged in ${indexName}`)
}
// Fetch full records from operation ids
var toAddRecords = newIndex.filter(function(hit) {
return operations.add.indexOf(hit.objectID) !== -1
})
// Fetch full records from operations.add ids
var toAddRecords = newIndex.filter(function(hit) {
return operations.add.indexOf(hit.objectID) !== -1
})
var toUpdateRecords = newIndex.filter(function(hit) {
return operations.update.indexOf(hit.objectID) !== -1
})
// Create batch update actions
var toAdd = toAddRecords.map(function(record) {
return addAction(record, indexName)
})
// Create batch update actions
var toAdd = toAddRecords.map(function(record) {
return actionAdd(record, indexName)
})
var toDelete = operations.delete.map(function(id) {
var action = deleteAction(id, indexName)
return action
})
var batchActions = [].concat(toAdd, toDelete)
var toUpdate = toUpdateRecords.map(function(record) {
return actionUpdate(record, indexName)
})
// Perform the batch API call
if (batchActions.length > 0) {
// Notify client this is coming from this script
client.setExtraHeader("X-FORWARDED-BY", "HUGO-ALGOLIA")
client.batch(batchActions, function(err, res) {
if (err) throw err
var toDelete = operations.delete.map(function(id) {
return actionDelete(id, indexName)
})
var batchActions = [].concat(toAdd, toUpdate, toDelete)
cb(null, res)
})
}
})
// Perform the batch API call
if (batchActions.length > 0) {
// Notify client this is coming from this script
client.setExtraHeader("X-FORWARDED-BY", "HUGO-ALGOLIA")
client.batch(batchActions, function(err, res) {
if (err) throw err
cb(null, res)
})
}
})
.catch(function(err) {
cb(err)
})
} catch (err) {

@@ -77,0 +83,0 @@ cb(err)

@@ -1,19 +0,83 @@

module.exports = function calculateOperations(newIndexIds, oldIndexIds) {
var operations = {unchanged: [], add: newIndexIds, delete: oldIndexIds}
var idsFromIndex = require("./idsFromIndex")
var md5 = require("md5")
module.exports = function calculateOperations(newIndex, oldIndex) {
var newIndexIds = idsFromIndex(newIndex)
var oldIndexIds = idsFromIndex(oldIndex)
var existingHits = []
var operations = {ignore: [], update: [], add: newIndexIds, delete: oldIndexIds}
if (newIndexIds.length > 0 && oldIndexIds.length > 0) {
operations.unchanged = newIndexIds.filter(function(hit) {
return oldIndexIds.indexOf(hit) !== -1
})
existingHits = findExistingHits(newIndexIds, oldIndexIds)
operations.add = findNewHits(newIndexIds, oldIndexIds)
operations.delete = findExpiredHits(newIndexIds, oldIndexIds)
}
operations.add = newIndexIds.filter(function(hit) {
return oldIndexIds.indexOf(hit) === -1
})
if (existingHits.length > 0) {
operations.ignore = findUnchangedHits(existingHits, newIndex, oldIndex)
operations.update = findChangedHits(existingHits, newIndex, oldIndex)
}
operations.delete = oldIndexIds.filter(function(hit) {
return newIndexIds.indexOf(hit) === -1
})
console.log(operations)
return operations
}
function findNewHits(newIndexIds, oldIndexIds) {
return newIndexIds.filter(function(hit) {
return oldIndexIds.indexOf(hit) === -1
})
}
function findExpiredHits(newIndexIds, oldIndexIds) {
return oldIndexIds.filter(function(hit) {
return newIndexIds.indexOf(hit) === -1
})
}
function findExistingHits(newIndexIds, oldIndexIds) {
return newIndexIds.filter(function(hit) {
return oldIndexIds.indexOf(hit) !== -1
})
}
function findUnchangedHits(existingHits, newIndex, oldIndex) {
return existingHits.filter(function(id) {
var shouldUpdate = compareHitFromIndexes(id, newIndex, oldIndex)
if (shouldUpdate !== true) {
return id
}
})
}
function findChangedHits(existingHits, newIndex, oldIndex) {
return existingHits.filter(function(id) {
var shouldUpdate = compareHitFromIndexes(id, newIndex, oldIndex)
if (shouldUpdate === true) {
return id
}
})
}
function compareHitFromIndexes(id, newIndex, oldIndex) {
var newHit = newIndex.filter(function(hit) {
return hit.objectID === id
})
var oldHit = oldIndex.filter(function(hit) {
return hit.objectID === id
})
if (newHit.length > 0 && oldHit.length > 0 ) {
var newHitSorted = JSON.stringify(newHit, Object.keys(newHit).sort())
var oldHitSorted = JSON.stringify(oldHit, Object.keys(oldHit).sort())
var newHash = md5(newHitSorted)
var oldHash = md5(oldHitSorted)
return newHash !== oldHash
}
return operations
return null
}

@@ -1,11 +0,11 @@

module.exports = function idsFromIndex(newIndex) {
return newIndex.reduce(function(hits, hit) {
if (hit !== null && hit !== undefined) {
return hits.concat(hit)
}
}, []).reduce(function(hits, hit) {
if (hit.objectID !== null && hit.objectID !== undefined) {
return hits.concat(hit.objectID)
module.exports = function idsFromIndex(index) {
return index.reduce(function(hits, hit) {
if (hit !== null && hit !== undefined) {
return hits.concat(hit)
}
}, [])
}
}, []).reduce(function(hits, hit) {
if (hit.objectID !== null && hit.objectID !== undefined) {
return hits.concat(hit.objectID)
}
}, [])
}
{
"name": "atomic-algolia",
"version": "0.2.1",
"description": "An NPM script for running atomic updates to an Algolia index with a local JSON file",
"version": "0.3.0",
"description": "An NPM package for running atomic updates to an Algolia index",
"main": "lib/index.js",

@@ -13,3 +13,11 @@ "scripts": {

],
"author": "@chrisdmacrae",
"engines": {
"node": ">=7.6.0"
},
"repository": "github:chrisdmacrae/atomic-algolia",
"author": {
"name": "Chris D. Macrae",
"email": "hello@chrisdmacrae.com",
"url": "chrisdmacrae.com"
},
"license": "ISC",

@@ -19,4 +27,5 @@ "dependencies": {

"chalk": "^2.3.0",
"dotenv": "^5.0.0"
"dotenv": "^5.0.0",
"md5": "^2.2.1"
}
}

@@ -5,6 +5,10 @@ # Algolia Atomic

## How it works
This package runs *atomic* updates to an Algolia Index from a local JSON file. **What does that mean?**
This package runs *atomic* updates to an Algolia Index. **What does that mean?**
Simply put, this package reads a local JSON file, and updates the *new* or *updated* records, while removing deleted records. It does this *all at once*, so your index is never out of sync, and you use the smallest amount of operations possible. *(Stay on that free plan as long as you can!)*
Simply put, this package reads your local index, and updates the *new* or *updated* records, while removing deleted records.
It does this *all at once*, so your index is never out of sync with your content, and you use the smallest amount of operations possible.
*(Stay on that free plan as long as you can!)*
## Installation

@@ -20,3 +24,3 @@ To install this script, you must have [Node & NPM installed](https://nodejs.org/en/download/). Once installed, run the following command in your terminal:

It reads a local JSON file with an array of valid records. For example:
It reads an array of objects or local JSON file with an array of valid records. For example:

@@ -35,3 +39,3 @@ ```

> Note, this package can only be used in NPM scripts to update a single index. To update multiple indices, create your own script by following the instructions in [Javascript Files](#javascript-files)
> Note, this package can only be used in NPM scripts to update a single index from a local JSON file. To update multiple indices or pass in a Javascript object, create your own script by following the instructions in [Javascript Files](#javascript-files)

@@ -58,2 +62,4 @@

#### Using with a local JSON file
```

@@ -78,3 +84,31 @@ var atomicalgolia = require("atomic-algolia")

#### Using with an Array of Objects
```
var atomicalgolia = require("atomic-algolia")
var indexName = "example_index"
var indexData = [
{
objectID: "1",
title: "An example record"
}
]
var cb = function(error, result) {
if (err) throw error
console.log(result)
}
atomicalgolia(indexName, indexPath, cb)
```
Then call the script from your terminal as follows:
```
ALGOLIA_APP_ID={{ YOUR_APP_ID}} ALGOLIA_ADMIN_ID={{ YOUR_ADMIN_ID }} YOUR_SCRIPT.js
```
## Using a `.env` file

@@ -81,0 +115,0 @@ A `.env` file can be added to the root of your project with the required environment variables. This way, you don't have to specify them in `package.json` or when running the command.

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc