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 🙏

© 2026 – Pkg Stats / Ryan Hefner

jorm

v2.2.5

Published

Simple orm - just orm

Readme

jorm

Simple orm - just orm.

Init

Just init jorm parameters:

var jormParams = {
	connectionString: "postgres://user:[email protected]:5432/base", // required
	logger: custom_logger, // optional object with log, error, warn and info methods
}

db config:

var config = {
	User: {
		table: 'user',
		fields: {
			id            : {pk: true}, // this is primary key to CRUD operations
			created       : {default: function(params){ return new Date() }}, // field allows auto init default values
			name          : {public: true }, // this field will be in public object by .getPublic() method with any parameter
			hpassword     : {},
			email         : {public: 'lite'}, // this field will be in public object by .getPublic() and .getPublic('lite') method
			phone         : {public: ['lite', 'full']}, // this field will be in public object by .getPublic(), .getPublic('lite'), .getPublic('full') and .getPublic('lite','anyOther') methods
			is_alex       : {db: false, default: function(params){ return params.name == 'Alex' }}, // this field will be ignored in all db CRUD operations, but will be filled while user object created
			post_count_cache: {sql: 'COALESCE(post_count_cache, 0)'}, // custom sql part for select column post_count_cache
			comments_count: { db: 'demand', sql: 'COALESCE((SELECT count(*) FROM "comment" WHERE "comment"."user_id" = "user"."id"),0)' }, // this field including in query only by demand. All tables and columns must be with quotes (")
			current_geo_id: {public:true, alias:'GeoCurrent'},
			birth_geo_id  : {public:true, alias:'GeoBirth'} // specify alias to separete fields in get request with joined objects (this is alternate method for 'alias' in 'join' params)
			link          : { db:false, getPublic: function(_this) { return 'href://site.com/user/'+_this.id; } }, // getPublic - function for field, which calling while getPublic method for essence executing
		},

		// Optional possible DB triggers - all combinations of 'select', 'insert', 'update', 'delete' commands, and 'after', 'before', 'error' events
		select_before	: function(params, client, callback){
			if(params.make_ext_request){ // make_ext_request - just for example
				// ... make some action, incl. sql request with [client] ...
				callback(err)
			}
			else callback();
		};
		insert_after	: function(params, client, dataFromDB, callback){
			if(params.make_ext_request){ // make_ext_request - just for example
				// ... make some action, incl. sql request with [client] ...
				callback(null, dataFromDB)
			};
			else callback(null, dataFromDB); 
		},
		update_error	: function(err, params, client, callback){
			if(params.make_ext_request){ // make_ext_request - just for example
				// ... make some action, incl. sql request with [client] ...
				callback(err)
			};
			else callback(err); 
		},

		init 			: function() {this.hpassword = someFuncToHashPass(this.email, this.password)} // called after object created
	}
};

and init jorm:

var jorm = require('jorm');
var dto = new jorm(jormParams, config);

CRUD

Create

var newUser = jorm.User.create({name: 'John', email: '[email protected]'})

Save

If object's primary key field is null or undefined, then make insert. Else make update

save and delete supports optional params, which will be transfered to handlers

newUser.save(function(err, user){
	if(err) return console.error(err);
	console.log(user.getPublic());
});
// or
newUser.save({make_ext_request: true}, callback);

Update

user.name = newName;
user.save(function(err, user){
	if(err) return console.error(err);
	console.log(user.getPublic());
});

Delete

Just delete it

user.delete(function(err){
	if(err) return console.error(err);
	console.log('deleted');
})
// or
user.delete({make_ext_request: true});

Get it from DB

Simple get by field

jorm.User.get({
	id: userId // simple 'where' by id
}, function(err, users) {
	if(err) return console.error(err);
	if(users.length == 0)return console.log('UNKNOWN_USER_ID');
	
	console.log(users[0].getPublic());
})

Custom get by fields

jorm.User.get({
	name 				:{comparsion: 'LIKE', value: '%a%'}, // 'where' by custom comparsion
	email 				:{comparsion: 'is not null'}, // 'is null' comparsion
	phone 				:{comparsion: 'is null'}, // 'is not null' comparsion
	age_xyz				:{columns: ['age'], comparsion: '>', value: 20},	// 'columns' fields override key,  ...
	any_field			:{comparsion: 'LIKE', columns: ['name','description'], value: '%b%', and_or: 'OR'} // LIKE over name+description with "OR" clause
	post_count			: [1,2,3] // 'in' clause
	gender				: ['m','f', null] // => gender in ('m','f') or gender is null
}, {
	and_or: 'or',	// where by fields with 'OR' clause
	fields: ['id', 'name'] // get from db only this fields
	},function(err, users) {
	if(err) return console.error(err);
	console.log(users.getPublic()); // getPublic() work for arrays too
})

Avaliable comparsions: 'not in', '=', '<>', '<', '>', '<=', '=<', '>=', '=>', 'is null', 'is not null' and full set from https://github.com/brianc/node-sql/blob/master/lib/node/valueExpression.js

Order, Limit and Offset

jorm.User.get({
	// empty fields params must be specified
	}, {
	demand: ['comments_count'], // get all fields from User, and 'demand' fields
	limit: 10,
	offset: 100,
	order: {field: 'id', direction: 'asc'} // asc - default value for direction
}, function(err, users) {
	if(err) return console.error(err);
	console.log(users.getPublic());
})

Join essences

Simple join table with minimum options

jorm.Post.get({
	},{
	order: [
		{field: 'id'},
		{dto: dto.User, field: 'id'}
	], // Order can be defined multiply times and can be over joined dto too
	join: [
		{join: dto.User, field: 'id', parent_field: 'user_id'}
	]}, function(err, posts){
	if(err) return console.error(err);
	console.log(posts.getPublic()); // each post contains user creator
});

Join same table twice (join to joined table) with WHERE cluase by two tables

jorm.Post.get({
		created: {comparsion: '>', value: new Date()}
	},{
	join: [
		{join: dto.User, to:dto.Post, field: 'id', parent_field: 'user_id', alias: 'Author'},
		{join: dto.Comment, field: 'id', parent_field: 'user_id'}, // if 'to' omitted, main essence implied (Post in this example)
		{join: dto.User, to: dto.Comment, field: 'id', parent_field: 'user_id', where: {created: {comparsion: '>', value: new Date()}}, alias: 'CommentUser'}, // join-to-join to first dto.Comment as parent
		{join: dto.Post, to:'CommentUser', field: 'user_id', parent_field: 'id',  }, // join to parent join with alias "CommentUser" (we can't use just "to:dto.User", because User already joined twice, and we need second one)
	]}, function(err, posts){
	if(err) return console.error(err);
	console.log(posts.getPublic()); // each post contains User and Comment fields, each Comment contains User itself
});

#CRUD Handlers Each CRUD function can be wrapped with before and after handler.

Additionaly, parameter {transaction: true} for get, save and delete make handlers transaction safe.

var config = {
	User: {
		table: 'user',
		fields: {
		},
		insert_before	: function(params, client, callback) { 
			client.query('INSERT INTO "trace_log"(entry) values($1)', ["this_log_for_test_transactions"], function(err) {
				callback(err);
			});
		},
	}
};
// ...
var user = dto.User.create();
user.save({transaction: true}, function(err, user){
	// if inserting this user fails, no trace log entry added in insert_before because of automatic rollback transaction in error handler
})

#Tests See 'test' folder