New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

bookshelf-history

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bookshelf-history

Backup and restore utility for Bookshelf.js

  • 2.0.0
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
4
increased by300%
Maintainers
1
Weekly downloads
 
Created
Source

bookshelf-history

bookshelf-history is a plugin for Bookshelf.js that lets you easily handle row backup and restoration. Even automatic backup is supported.

Usage

// Just plug History in bookshelf
bookshelf.plugin(require('bookshelf-history'))

// Now create your model as usual setting the property history to true to allow
// custom methods to work properly and enable automatic backup
let User = bookshelf.Model.extend({ tableName: 'users', history: true })

Methods

  • Model.backup(resourceId, [options]) perform a manual backup on a model that has history enabled. resourceId must be the ID from the row to be backed up and options is an optional object where you can pass a transaction object as options.transacting.
  • Model.revert(resourceId, [sequence], [options]) restores a resource to a specific back-up sequence. If no sequence is provided the resource will be restored to the latest known sequence. options is an optional object where you can pass a transaction object as options.transacting.
  • Model.historyModel() returns the history model being used for query operations in the Model or false if history is disabled.

Default options

let defaults = {
  fields: {
    sequence: Integer,
    resource_id: Any,
    resource_type: String,
    metadata: Object,
    diff: Object,
    data: Object,
    patch: Boolean,
    operation: String,
    getMetadata: Function
  },
  model: bookshelf.Model.extend({ tableName: 'history' })
  autoHistory: [ 'created', 'updated' ],

}

These options can be globally overwritten when adding the plugin to bookshelf

bookshelf.plugin(require('bookshelf-history'), {
  fields: {
    sequence: 'version',
    data: 'row_content'
  },
  model: bookshelf.Model.extend({ tableName: 'backups' })
})

Or also when creating each subsequent model

let User = bookshelf.Model.extend({
  tableName: 'user',
  history: {
    autoHistory: false
  }
})

Additional Metadata

History now supports a getMetadata(model) option that will allow you to implement a function to return additional key value pairs to be stored with the history. In the example below, we use the continuation pattern, to fetch the logged in user / admin who initiated a HTTP request that is mutating the model. The data is saved as metadata in the History table.

const getNamespace = require('cls-hooked').getNamespace
const localStorage = getNamespace('app')
history: {
  getMetadata: () => {
    if (!localStorage) {
      return
    }

    return {
      author_id: localStorage.get('author_id'),
      author_type: localStorage.get('author_type')
    }
  }
}

Migration

Below is an example migration. All fields are required with the exception of created_at. You can also specify custom field names using the configuration as shown in the section above.

History also supports JSON and JSONB field types out of the box for the data field when running with PostgreSQL. With other databases the data field gets stringifyed with JSON.stringify() so make sure your data field is long enough to store all data you need.

exports.up = async (knex) => {
  await knex.schema.createTable('history', function (t) {
    t.uuid('id')
      .primary()
      .notNullable()
      .defaultTo(knex.raw('uuid_generate_v4()'))
    t.integer('sequence').notNullable()
    t.string('operation').notNullable()
    t.boolean('patch').notNullable()
    t.string('resource_type').notNullable()
    t.uuid('resource_id').notNullable()
    t.jsonb('metadata')
    t.jsonb('diff')
    t.jsonb('data')
    t.timestamp(true, true)
  })
}

exports.down = async (knex) => {
  await knex.schema.dropTable('history')
}

Bypassing backups

If you want to perform an operation inside a History enabled model but don't want to trigger an automatic backup you can make it two ways:

// Disable automatic backups entirely for the model
let User = bookshelf.Model.extend({
  tableName: 'users',
  history: {
    autoHistory: false
  }
})

// Or disable for a single operation
User.forge({
  name: 'John',
  email: 'john@doe.com'
})
.save(null, { history: false })

Testing

cd ./bookshelf-history
npm install

In .env place the DATABASE_URL that will be used for tests. Or you can pass it on the command line.

DATABASE_URL=postgres://postgres:postgres@localhost/bookshelf_history npm test

Keywords

FAQs

Package last updated on 05 Mar 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

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