node package manager



Storage Module

Build Status

A storage framework for Nxus applications using waterline.


"config": {
  "storage": {
    "adapter": {
      "default": "sails-mongo"
    "connections": {
      "default": {
        "adapter": "default",
        "url": "mongodb://...."
    "modelsDir": "./src/models"

Creating models

Inherit your models from BaseModel

import {BaseModel} from '@nxus/storage'

var User = BaseModel.extend({
  identity: 'user',
  attributes: {
    name: 'string'

Register models

Either import your model class and pass it to model():


Or register all models in a directory with modelDir():


Model events

The storage model emits events for create, update, and destroy, you can register a handler for all events:

  storage.on('model.create', (identity, record) => {})
  storage.on('model.update', (identity, record) => {})
  storage.on('model.destroy', (identity, record) => {})

Or just a specific model identity:

  storage.on('model.create.user', (identity, record) => {})
  storage.on('model.update.user', (identity, record) => {})
  storage.on('model.destroy.user', (identity, record) => {})

Lifecycle notes

  • load

    • Models should be registered during load, e.g. var User = BaseModel.extend({ identity: 'user', ... }); application.get('storage').model(User)
  • startup

    • The configured database is connected during load.after

    • You can query models from startup and beyond, retrieve the model by the 'identity':

      application.get('storage').getModel('user').then((User) => {



Extends NxusModule

Storage provides a common interface for defining models. Uses the Waterline ORM.


Register a model


  • model object A Waterline-compatible model class




Request a model based on its identity (name)


  • id (string | array) The identity of a registered model, or array of identities



Returns Promise The model class(es)


Register all models in a directory


  • dir string Directory containing model files



Returns Promise Array of model identities


Base for Waterline models containing a GeoJSON geographic field.

It provides methods for performing geo queries on the GeoJSON field – findWithin() selects records that lie within specified coordinates, and findIntersects() selects records that intersect.

To implement the geo queries, the GeoJSON data must be indexed. And because the MongoDB 2dsphere index can handle only GeoJSON geometry features, the index is applied to a derived features field that contains just the geometry features from the primary GeoJSON field.

The GeoModel provides the machinery for keeping the features field synchronized with the primary GeoJSON field. It also attempts to ensure the features field is well-formed and has a consistent organization. For Polygon objects, it discards duplicate points, closes open paths and ensures clockwise winding order. It combines Geometry objects so there is at most one of each geometry type: Polygon/MultiPolygon, Point/MultiPoint and LineString/MultiLineString.

The createGeoIndex() method should be invoked to ensure the index is created. Typically, after the startup lifecycle phase.

Configuration is through these model properties:

  • geometryField (string) - Name of the primary GeoJSON field (default is geo).
  • geometryFeatureField (string) - Name of the geometry features field (default is geoFeatures). Both of these fields must also be defined as model attributes with type json.


Ensures index is defined for geographic field. (Actually, on the field specified by geometryFeatureField.)

Returns Promise A promise that resolves or rejects when index creation completes. It's worthwhile attaching a .catch() clause to this promise to log errors; index creation can fail for a variety of reasons, including invalid data in the geometry feature field.


Finds records within specified geographic coordinates.

The method goes through some odd gyrations in order to mesh the MongoDB geographic query with Waterline query handling.

First, it indirectly returns a Waterline query, by returning a promise that resolves to a function that evaluates to the query. This due to the fact that the query has promise semantics. Returning it indirectly defers evaluation, allowing you to refine it (using the chainable methods such as .populate(),.where(), and.sort()`) before evaluating it.

Second, it actually evaluates the MongoDB geographic query to produce a list of matching record ids, and the returned Waterline query is a second query based on these ids. Again, this to allow you to refine the query before evaluation. Be aware that this won't scale well to huge record sets, but should work for any of moderate size.


  • coordinates Object A GeoJSON geometry object specifying the geographic region to select; it must be of type Polygon or MultiPolygon.


      model.findWithin({ 'type': 'Polygon', 'coordinates': ... }).then((query) => {
        return query().where(...).populate(...)
      }).then((records) => {

Returns Promise A promise that resolves to a function that returns a Waterline query for the specified coordinates.


Finds records intersecting specified geographic coordinates.


  • coordinates Object A GeoJSON geometry object specifying the geographic region to select.

Returns Promise A promise that resolves to a function that returns a Waterline query for the specified coordinates. See findWithin() for further explanation.


Gets GeoJSON geometry object from the GeoJSON geographic field. Typical use is to extract Polygon geometry objects for use as coordinates for the findWithin() or findIntersects() methods.


  • record Object GeoModel record containing geographic field
  • types ...string geometry types to include (default is all types: Polygon, Point and LineString)

Returns Object GeoJSON geometry object; undefined if no matching geometry objects were present


Gets the centroid of the GeoJSON geographic field.


  • record Object GeoModel record containing geographic field

Returns Object GeoJSON Point object; undefined if no geometry objects were present from which to derive a centroid


Extends NxusModule

The HasModels class is a Base class for defining helper classes with Models. All models contained in a ./models directory will be registered automatically, and are the default list of model identities made available in the this.models object. You may override or extend this list of model identities, or a mapping of model identities to variable names, by overriding .modelNames()


  • $0 Object (optional, default {})
    • $0.modelNames (optional, default null)


Deprecated: Override to define the model names to access


modelNames() { 
  return ['user']

Returns (array | object) Model identities to add to this.models, or object of {identity: name}