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

boldr-orm

v0.1.7

Published

ORM for Boldr on top of ObjectionJS with additional utilities for GraphQL

Downloads

3

Readme

boldr-orm

Commitizen friendly styled with prettier

ORM for Boldr on top of ObjectionJS with additional utilities for GraphQL

ObjectionJS documentation: http://vincit.github.io/objection.js/
ObjectionJS Repo: https://github.com/Vincit/objection.js/

Extra Features

Boldr ORM (BORM) adds additional functionality on top of ObjectionJS.

  • Automatically added timestamps
  • Table name generated from model name automatically
  • Soft delete functionality
  • GraphQL helpers

Automatic Timestamps

By default all models are assumed to reference tables with createdAt and updatedAt fields. These fields are managed by Boldr ORM and updated whenever data is added or removed.

To disable time stamps:

Add static addTimestamps = false; on to your model.

Two additional helper methods are included for times when you might not want to modify the timestamp.

modify: updates the updatedAt column of the table to current time (new Date().toISOString()).
dontModify: keeps the current timestamps in place when the query is executed.

Default Table Name

Leave the table name generation to the ORM if you're feeling like it.

class Article extends Model {
	static tableName = 'Article';
	...
}

class Article extends Model {
	...
}

Soft Delete

To enable soft delete functionality, add static softDelete = true; to the model.

Don't forget your table must contain a deletedAt column, as a nullable timestamp.

Soft delete enabled models, aren't actually removed when the delete method is called. Instead the value of the deletedAt column is filled with the current timestamp. Queries don't return data which have a timestamp in the deletedAt field.

Helper methods implemented for Soft Delete:
delete: archive or delete a row (depending on whether softDelete is true or false)
archive: archive (soft delete) a row (use delete it's the same thing)
withArchived: return all data regardless of whether or not they been "deleted" or archived.
onlyArchived: return only the data which has been deleted with softDelete enabled. restore: restore (unarchive) an archived set of data.
forceDelete: actually delete a row from the database

If you want to use some other column name instead of deletedAt you can do static softDelete = 'deleted_at';

class Post extends Model {
	// Enable soft delete
	static softDelete = true;
}

// soft delete
Post.query().where('id', 1).delete();
// restore an archived row
Post.query().where('id', 1).restore();
// get all non-archived posts
Post.query();
// get all posts (including archived / "soft deleted" ones)
Post.query().withArchived();
// retrieve only archived posts
Post.query().onlyArchived();
// completely remove a post from the database
Post.query().forceDelete();

GraphQL Helpers

getDeleteByIdResolver()

returns a resolver for GraphQL delete mutation deleteCategory(id: ID) { DeletedItem } Mutation: { deleteCategory: Category.getDeleteByIdResolver() }

getFindByIdSubResolver()

returns a resolver for finding model by id. It optionally takes a propName argument which denotes the name of the field containing the id. type Store { id: ID!, name: String!, category: Category} Query: { Store: { category: Category.getFindByIdSubResolver() } } Query: { Store: { category: Category.getFindByIdSubResolver('categoryId') } }

save and saveAndFetch

save: inserts a model if the id column does not exist, otherwise updates it.
saveAndFetch: saves the model and then fetches it.

wrapWhere

Wraps the where condition till now into braces
so builder.where('a', 'b').orWhere('c', 'd').wrapWhere().where('e', 'f'); becomes "WHERE (a = 'b' OR c = 'd') AND e = 'f'"

whereByOr(obj)

creates an and (or - or - or) condition

q.where('id', 1).whereByOr({posts: 100, user: 'admin'})
// where `id` = 1 and (`posts` = 100 or `user` = 'admin')

whereByAnd(obj)

creates an or (and - and - and) condition

q.where('id', 1).whereByAnd({posts: 100, user: 'admin'})
// where `id` = 1 or (`posts` = 100 and `user` = 'admin')

find Method

find: find is like where except if only a single argument is given, it treats the argument as an id.

// all three are equivalent
Person.query().find(1);
Person.query().where('id', 1);
Person.query().findById(1);

// both are equivalent
Person.query().find('name', 'John');
Person.query().where('name', 'John');

where and find methods on model

Instead of doing Person.query().where() you can do Person.where()
Instead of doing Person.query().find() you can do Person.find()

Easier Relationships

You can define all your relationships in the $relations method.

Methods for defining relations

belongsTo(model, options) hasOne(model, options) hasMany(model, options) hasManyThrough(model, options)

options are totally optional. they can be:

name: name of the relationship (by default name of the model in camelCase)
joinFrom: join field from (by default ModelTableName.camelCasedModelNameId)
joinTo: join field to (by default ModelTableName.id)
filter: apply this filter to the model
through: {
	model: if there is a model for the through table
    table: tableName of the table to join through
    from: join through from
    to: join through to
    filter: filter to apply on the join table
    extra: extra fields to select from the through table
}
class Pet extends Model {
	static $relations() {
    	this.hasOne(Pet);
        this.hasMany(Toy, {name: 'toys'});
        this.belongsTo(Person);
        this.hasManyThrough(Pet, {
        	name: 'siblings',
            through: {
            	table: 'Pet_Siblings',
                from: 'pet_id',
                to: 'sibling_id',
            },
        });
    }
}

Model can be a model object, or an absolute path to a model class. It can also be a relative path if you set the basePath of all models using Model.setBasePath(path)

InputError Class

import {InputError} from 'boldr-orm';

async function saveStore(store) {
	if (!store.name) {
		throw new InputError({
			name: 'Name is required',
		});
	}
}

// Alternatively instead of importing InputError you can simply throw Model.Error
async function saveStore(store) {
	if (!store.name) {
		throw new Store.Error({
			name: 'Name is required',
		});
	}
}