npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

entity-api

v0.1.1

Published

Entity API for Node.JS.

Downloads

10

Readme

entity-api

entity-api provides easy to use Entity API for Node.js applications.

Creating, loading, updating and deleting entities can be messy operation behind the scenes, if there is no proper way to do it. This module aims to help you formalize these basic entity operations by defining required Entity types, Entities and specialized handlers like View handler, List handler, Storage handler and Access handler.

Field API provides tools to define, manage, view and validate entity fields.

Supported storage backends

Entities are stored to storage backend. This module is shipped with in-memory storage backend called ConfigStorageBackend.

Storage backends are provided as own modules. At the moment there is support for following storage backends:

Please contribute to get more storage backends.

Installation

Using npm:

$ npm install --save entity-api

Usage example

Here is an example how to create a custom entity type called message to store some notes with content. See example.js for more examples with descriptions.

import {
  Entity,
  EntityAPI,
  EntityType,
  EntityStorageHandler,
  ConfigStorageBackend,
  EntityViewHandler,
  fieldAPI
} from 'entity-api'

class MessageEntity extends Entity {

  create(variables = {}, callback) {
    this.set('created', Date.now())
    callback(null)
  }

  describe() {
    return `This message says: "${this.get('body')}"`
  }
 
  static getFieldDefinitions() {
    const fields = new Map()

    fields.set('id', fieldAPI.createBasefield('text')
      .setName('ID')
      .setDescription('Entity identifier')
      .setProtected(true)
      .setProperty('view_properties', {
        full: { view_field: true },
        list: { view_field: true }
      }))

    fields.set('body', fieldAPI.createBasefield('text')
      .setName('Message')
      .setDescription('Message body')
      .setProperty('view_properties', {
        full: { view_field: true }
      }))

    fields.set('created', fieldAPI.createBasefield('integer')
      .setName('Created time')
      .setDescription('Created time for message')
      .setProperty('view_properties', {
        full: { view_field: true },
        list: { view_field: true }
      }))
    return fields
  }

  static getFieldIndexDefinitions() {
    return [
      { 'fieldName': 'id', 'indexType': 'HASH', 'auto': true }
    ]
  }
}

class MessageEntityType extends EntityType {

  constructor(variables = {}) {
    variables.entityTypeId = 'message'
    variables.entityClass = MessageEntity
    variables.handlers = {
      storage: new EntityStorageHandler({
        storageBackend: ConfigStorageBackend
      }),
      view: new EntityViewHandler(variables),
    }
    super(variables)
  }
}

const entityAPI = EntityAPI.getInstance({}, true)
entityAPI.registerEntityType(new MessageEntityType())

Now you can create, store and load message entities. You can also view entities using view modes defined within fields. Viewed entity is Data Transfer Object (DTO).


const data = {
  body: 'Hi there'
}

// Create and view entity
entityAPI.getStorage('message').create(data)
  .then((entity) => {
    return entity.view({ viewMode: 'full' })
  })
  .then((viewedEntity) => {
    console.log(viewedEntity)
    // --> {id: '00112233-4455-6677-8899-aabbccddeeff', body': 'Hi there', created: 1234567890 }
  })

// Save and update entity
entityAPI.getStorage('message').createAndSave(data)
  .then((entity) => {
    console.log(entity.describe())
    // --> This message says: "Hi there"

    entity.set('body', 'Wohoo')
    return entity.save()
  })
  .then((entity) => {
    console.log(entity.describe())
    // --> This message says: "Wohoo"
  })

// Load entity
const entityId = {id: '00112233-4455-6677-8899-aabbccddeeff'}

entityAPI.getStorage('message').load(entityId)
  .then((entity) => {
    console.log(entity.describe())
    // --> This message says: "Hi there"
  })

Error handling with entities:

entityAPI.getStorage('message').create(data)
  .then((entity) => {
    if (!entity) {
      throw new Error('Unable to create entity')
    }
  })
  .catch((err) => {
    // If there was an error when creating entity, 
    console.error(err)
  })

Methods and hooks

Entity API

EntityAPI has following methods:

entityAPI.getInstance(options = {}, reset = false) Returns entity API instance

entityAPI.registerEntityType(entityType) Register new entity type

entityAPI.registerEntityTypes(entityTypes) Register multiple entity types at once

entityAPI.getEntityType(entitTypeName) Returns entity type by name

entityAPI.getEntityTypeHandler(entitTypeName, handlerName) Returns entity type handler by handler name

entityAPI.getEntityTypeIds() Returns list of entity types

entityAPI.getStorage(name) Returns storage handler for entity type

entityAPI.getViewHandler(name) Returns view handler for entity type

entityAPI.getListHandler(name) Returns list handler for entity type

entityAPI.getAccessHandler(name) Returns access handler for entity type

entityAPI.install(options) Perform install storage operation for all entity types

entityAPI.uninstall(options) Perform uninstall storage operation for all entity types

entityAPI.update(options) Perform update storage operation for all entity types

Entity

Entity object has following methods:

entity.id() Returns entity id as object, {key: '...', second_key: '...'}

entity.idString(delimiter = ':') Returns entity id as string using delimiter: 'key:second_key'

entity.getEntityTypeId() Returns entity type identifier

entity.getEntityTag() Returns entity tag. Tag is not saved, but it's available to pass data for entity

entity.getEntityContext() Returns entity context

entity.isNew() Returns boolean flag to indicate if entity is just created

entity.getFields() Returns fields assosiated with this entity

entity.get(fieldName) Returns field by name

entity.set(fieldName, value) Set field value

entity.setDangerously(fieldName, value) Set also protected field value

Entity object has following hooks:

class CustomEntity extends Entity {

  // Construct new entity
  constructor(variables = {}) {
    super(variables)
  }

  // Define list of fields for this entity
  static getFieldDefinitions() {
    const fields = new Map()
    return fields
  }

  // Entity is about to be created
  create(variables, callback) {
    callback(null)
  }

  finalize(callback) {
    callback(null)
  }

  // is called after entity is loaded
  postLoad(callback) {
    callback(null)
  }

  // is called before entity is saved
  preSave(callback) {
    callback(null)
  }

  // is called after entity is saved
  postSave(callback) {
    callback(null)
  }

  // is called before entity is deleted
  preDelete(callback) {
    callback(null)
  }

  // is called after entity is deleted
  postDelete(callback) {
    callback(null)
  }

  // Returns base DTO object for when entity is about to be viewed 
  getViewContent() {
    return {}
  }

  // Allows entity to alter viewed entity content, for example add dynamic data
  alterViewContent(container, options, callback) {
    callback(null, container)
  }
}

EntityHandler

By default Entity API provides following special handlers: EntityStorageHandler, EntityListHandler, EntityViewHandler and EntityAccessHandler handlers.

Extend EntityHandler class to provide custom handlers for you entity type.

EntityViewHandler

EntityViewHandler has following methods:

handler.viewEntity(entity, options, callback)

handler.view(entity, options = {}) Returns promise

viewMultipleEntities(entities, options = {}, callback)

handler.viewMultiple(entity, options = {}) Returns promise

EntityAccessHandler

EntityAccessHandler has following hooks to manage access to given entity. You should extend EntityAccessHandler class to override this behaviour.

class EntityAccessHandler extends EntityHandler {

  /**
  * Create access for entity
  *
  * @param object
  *   Source object who want's to create entity.
  * @param options
  * @return promise
  *   Resolves boolean has access
  */
  createAccess(object, _options = {}) {
    return Promise.resolve(false)
  }

  /**
  * Access check for entity.
  *
  * @param entity
  * @param op
  *   Operation to be executed for entity.
  * @param object
  *   Source object who want's to access entity.
  * @param options
  *   Options for current access check
  * @return promise
  *   Resolves boolean has access
  */
  access(entity, op, object, _options = {}) {
    return Promise.resolve(false)
  }
}

EntityStorageHandler

EntityStorageHandler has following methods to manage storage.

Promise based methods:

storage.create(data) Create new entity

storage.load(id) Load entity by id

storage.loadMultiple(ids) Load multiple entities

storage.save(entity) Save entity

storage.createAndSave(data) Create and save entity

storage.delete(entity) Delete entity

storage.deleteMultiple(entities) Delete multiple entities

Storage has Following methods to manage general storage issues

storage.getSchemas() Retursn schema

storage.getStorageDatabaseName() Returns storage database name for entity

storage.getStorageDatabasePrefix() Returns database prefix for storage

storage.getStorageTableName() Returns table name for storage

storage.getStorageTablePrefix() Returns storage table prefix

storage.getStorageBackend() Returns storage backend object

storage.getEntityFieldDefinitions() Returns list of entity field definitions

storage.getEntityFieldIndexDefinitions() Returns list of entity field index definitions

storage.extractEntityId(indexes, data) Extracts entity if from indexes

storage.isValidEntityId(entityId) Checks if entity id is valid

storage.install(options)

storage.uninstall(options)

storage.update(options)

Callback based storage methods:

storage.createEntity(data, callback)

storage.loadEntity(id, callback)

storage.loadMultipleEntities(ids, callback)

storage.saveEntity(entity, callback)

storage.deleteEntity(entity, callback)

storage.deleteMultipleEntities(entities, callback)

Test

Run tests using npm:

$ npm run test