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

birchtree

v0.4.2

Published

Repository system and helper functions for knexjs

Downloads

39

Readme

BirchTree Build Status

BirchTree is mainly a helper library for knexjs. It takes an instance of knex and adds two helper functions: grow and nest. These functions make it easy to get nested objects as results when running join queries.

BirchTree is also a repository library built on knexjs. It provides base Repo and Model classes that can be extended to create a basic model system.

Install

npm install --save birchtree

TypeScript

BirchTree is written in typescript and should just work. You can import the type for birchtree like this

import { BirchTree } from 'birchtree'

Helper Functions

Basic Usage

import birchtree from 'birchtree';
import * as Knex from 'knex';

const knex = Knex({
    client: 'mysql',
    debug: false,
    connection,
    pool
});

const birch = birchtree(knex);

const songs = 'albums:songs';
const author = 'albums:songs:author';
const select = await birch.grow('artists', 'albums', `songs AS ${songs}`, `authors AS ${author}`);
const results = await birch('users')
    .select(select)
    .leftJoin('albums', 'albums.artist_id', 'artists.id')
    .leftJoin(`songs AS ${songs}`, `${songs}.album_id`, `albums.id`)
    .leftJoin(`authors as ${author}`, `${author}.id`, `${songs}.author_id`)
    .where('artists.id', '=', 1);
const nestedResults = birch.nest(results);

Results will look like

[{
    id: 1,
    name: 'The Beatles',
    albums: [{
        id: 1,
        name: 'Rubber Soul',
        songs: [{
            id: 1,
            name: 'Drive My Car',
            author: {
                id: 2,
                name: 'Paul McCartney'
            }
        }, {
            id: 2,
            name: 'Norwegian Wood (This Bird has Flown)',
            author: {
                id: 1,
                name: 'John Lennon'
            }
        }]
    }, {
        id: 2,
        name: 'Revolver',
        songs: [{
            id: 3,
            name: 'Taxman',
            author: {
                id: 3,
                name: 'George Harrison'
            }
        }, {
            id: 4,
            name: 'Eleanor Rigby',
            author: {
                id: 2,
                name: 'Paul McCartney'
            }
        }]
    }]
}]

Important

There are some important things to note from the example.

  • In order for things more than 1 layer deep to nest they must be aliased in a nested way. The delimiter is :
  • If a name or alias is plural than the results will form an array correctly
  • If the name or alias is singular than it will not form a collection
  • You will only get 1 result if you use a singular alias for something you want multiple results for

grow

Asynchronous: Takes any number of table names with or without aliases as arguments and returns an array for knex's select function that will make sure columns don't get overwritten. It will select every column in each table given.

nest

Takes the results from a select query and nests them using treeize

Repository System

Basic Setup

import { default as birchtree, BirchTree, Repo, Model } from 'birchtree';

// let's just pretend we set knex up
const birch = birchtree(knex);

// let's make a user repo
const userRepo = new UserRepo(birch);

class User extends Model {
    static tableName = 'users';

    private id: number;
    private email: string;
    private username: string;

    constructor(props) {
        super();
        Object.assign(this, props);
    }

    toJSON() {
        return {
            id: this.id,
            email: this.email,
            username: this.username
        }
    }
}

class UserRepo extends Repo<User> {
    constructor(birch) {
        super(User, birch);
    }

    async findDuplicate(user: User, trx: BirchTree.Transaction) {
        return this.createQuery(trx)
            .where({ email: user.email })
            .orWhere({ username: user.username });
    }
}

Important

  • Models
    • The models must have static tableName property equal to the name of the corresponding database table
    • models must have a toJSON function. This function is used to get the object to persist in repo.create, repo.update and repo.save
    • models must have an id property
  • Repos
    • Must pass the model class and birch to super in the constructor
    • can access birch with this.birch in extended repos

Create

const user = new User({
    email: '[email protected]',
    username: 'fry'
});
await userRepo.create(user);

Update

user.username = 'bender';
await userRepo.update(user);

Save

user.email = '[email protected]';
await userRepo.save(user);

const leela = new User({
    email: '[email protected]',
    username: 'leela'
});
await userRepo.save(leela);

findOneById

const bender = await userRepo.findOneById(user.id);

findByIds

const benderAndLeela = await userRepo.findByIds([bender.id, leela.id]);

exterminate

await userRepo.exterminate(bender);

findOne

const leelaAgain = await userRepo.findOne({ email: '[email protected]' });

find

const leelaAsAnArray = await userRepo.find({ email: '[email protected]' });

createQuery

This returns a birchtree/knex querybuilder.

const results = await userRepo.createQuery().where('email', '=', '[email protected]');

Transactions

birch.transaction(trx => {
    const bender = await userRepo.findOne({ username: 'bender' }, trx);
    bender.username = 'coilette';
    await userRepo.save(bender, trx);

    const leela = await userRepo.createQuery(trx).where({ username: 'leela' });
    leela.username = 'Turanga';
    await userRepo.save(leela, trx);
    return [ bender, leela ];
})
.then(results => console.log(results))
.catch(err => console.error(err));