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

loopback-orm

v1.0.1

Published

Standalone Loopback ORM

Downloads

8

Readme

Use Loopback/StrongLoop Database Connector Standalone

Loopback is great. But sometimes all you want is the database abstraction part of it, not the entire application framework. The use case that modivated me to write this little module is the following; I have a full blown web application server written in Loopback with a database, but I also have small satellite application "services" that I want to run serverless (as in AWS Lambda) that capture small messages from IoT devices and write those into the database. I have no need for the entire Loopback application framework in these small services, but I still want to use the Loopback ORM to write the data. These services do not need to update or migrate the database, they do not need swagger interfaces, they do not need ACLs or any of that stuff ... the web application server takes care of all that.

Usage

npm install loopback-orm
const connector = {
  name: "postgres",
  connector: "postgresql",
  host: "192.168.99.100",
  port: 5432,
  url: "",
  database: "be",
  password: "secret",
  user: "admin",
};

const modelsPath = "/home/ubuntu/loopback-app/common/models";

const models = require('loopback-orm')({ connector, modelsPath });

models.MyModel.findOne({
  where: { id: 55 },
  fields: { type: true, timestamp: true },
  include: [ "relation1", "relation2" ]
}).then((res) => {
  console.log( JSON.stringify( res, null, 2 ) );
});

The connector specification is as described here. The modelsPath can be a path in the file system to the models directory created in a loopback app, typically "common/models", described here.

NOTE If you employ custom base classes for your models, see Custom Base Classes below

Discovery is also supported, and is triggered if you pass discovery: true as an option to this module. In this case, an attempt is made to discover the models from just inspecting the database. This is somewhat limited however in regards to relations. It handles belongsTo relations so long as you explicity describe your foreign keys and what they point to when you design the database schema. In addition, this module cannot inflate and deflate "object" columns, since those are done only if a schema is known.

In discovery mode, the call is asynchronious and returns a promise, so the usage is a little different:

const db = require('loopback-orm');
db({ connector, discovery: true}).then((models) => {
  models.MyModel.findOne({
    where: { id: 55 },
    fields: { type: true, timestamp: true },
  }).then((res) => {
    console.log( JSON.stringify( res, null, 2 ) );
  });
});

You can make the relations situation better in discovery mode by passing in relations option, a partial schema where each model has "relations" but no "properties". Like so:

const db = require('loopback-orm');

const relations = [
  {
    "name": "Config",
    "relations": {
      "State": {
        "type": "hasOne",
        "model": "State",
        "foreignKey": "configId"
      }
    }
  }
];

db({ connector, discovery: true, relations }).then((models) => {
  models.Config.findOne({
    where: { id: 55 },
    include: "State"
  }).then((m) => {
    console.log( JSON.stringify( m, null, 2 ) );
    process.exit(0);
  }).catch((err) => {
    console.log(err);
    process.exit(1);
  });
}).catch((err) => {
  console.log(err);
  process.exit(1);
});

See the Loopback documentation for how to describe relations.

Database Sync

This module now supports database syncing ... schema creation and schema modifications based on the supplied models. You just add a sync: true in the options, and treat this module as a promise.

const connector = {
  sync: true,
  name: "postgres",
  connector: "postgresql",
  host: "192.168.99.100",
  port: 5432,
  url: "",
  database: "be",
  password: "secret",
  user: "admin",
};
const modelsPath = require('path').resolve('./models');
const p = require('loopback-orm');
p({ connector, modelsPath, sync: true }).then((res) => {
  console.log( res.status );
  const models = res.models;
  Object.keys(models).forEach((modelName) => {
    console.log( `=> ${modelName}` );
  });
  process.exit();
}).catch((err) => {
  console.log( 'Error:', err.message );
});

Custom Base Classes

If you are using custom base classes in your model definitions, you have to so something a little different or things won't work.
You need to create your own array of model definitions with base class definitions at the front of the array, and call ({ connector, schemas: array-of-schemas, modelsPath }).

When building your own array of model definitions, you must ensure your custom base classes come first in the array, before any classes that use them. And you must specify the "base" classname in the "options" section of each model in addition to it being at the top of the model definition hierarchy. Here is some reference code you can use for reading your "/common/models" directory and dealing with a custom base class named "MyBase":

const lodash = require('lodash');

function loadSchemas( dirPath ) {
  let schemas = [];
  let files = require('fs').readdirSync( dirPath );
  files.forEach((f) => {
    if ( f.match(/\.json$/ ) ) {
      let s = require( require('path').join( dirPath, f ) );
      // If it has a custom base, copy it to options
      if ( s.base === "MyBase" ) {
        if ( ! s.options ) s.options = {};
        s.options.base = s.base;
      }
      schemas.push( s );
    }
  });

  // Move "MyBase" model definition to the front of the schemas array
  let myBase = _.find(schemas, {name: "MyBase"});
  schemas = _.reject(schemas, {name: "MyBase"});
  schemas.unshift(MyBase);

  return schemas;
}

models = require('loopback-orm')({
  connector,
  schemas: loadSchemas(require('path').resolve("./common/models")),
  modelsPath: require('path').resolve("./common/models")
});

Mixins

If your model schemas use mixins, then you can pass in a mixins option to the call. "TimeStamp" is a popular mixin for adding createdAt and updatedAt properties to model instances on creaton and update. Here is an example that supports the TimeStamp mixin (you must npm install loopback-ds-timestamp-mixin for this):

models = require('loopback-orm')({
  mixins: {
    TimeStamp: require("./node_modules/loopback-ds-timestamp-mixin/time-stamp")
  },
  ...
});