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

@makhzan/core

v0.0.3

Published

a repository and unit of work abstraction

Downloads

1

Readme

Makhzan Core

Makhzan (Store or Repository in Arabic) is a Unit of Work and Repository abstraction layer. The Core package includes a generic Unit of Work implementation, flexible enough to work with any classes you provide.

Setup

installation: npm i @makhzan/core or yarn add @makhzan/core

import { Manager } from "@makhzan/core"
// placeholders for your own code
import { UserRepository, AccountRepository } from "./repositories"
import { DBConn } from "./db"
import { knex } from "knex";

// using a low level lib like node-postgres
let startTrx = (isolation?: string) => {
        let q = "BEGIN" 
        if (isolation === "serializable")
            q += " TRANSACTION ISOLATION LEVEL SERIALIZABLE";
        return {
            async commit() {
                await q.commit()
            },
            async rollback() {
                await q.rollback();
            },
            async done() {
                await q.isComplete();
            },
            trx: q,
        };
}

// example using knex
let startTrx = (isolationLevel?: string) => {
        let q = knex.transaction({ isolationLevel });
        return {
            async commit() {
                await q.commit()
            },
            async rollback() {
                await q.rollback();
            },
            async done() {
                await q.isComplete();
            },
            trx: q,
        };
}

let UoW = Manager({
    // replace with your own DB layer's transaction code
    startTrx,
    isolations: {
        serialzable: "serializable",
        repeatableReads: "repeatable read"
    }
})
.addRepository("users", UserRepository)
.addRepository("accounts", AccountRepository)
.build();

The manager builds a Unit of Work function, it requires the following:

  • ManagerConfig parameter this sets up the manager to create transactions, it includes two parameters:
    • startTrx A callback that takes an optional string parameter, which is the selected isolation level
    • isolations an object with transaction isolation levels, the keys are how you access the isolation level from the resulting UoW instance, the values are what gets passed to the startTrx callback when used, this is optional if no specific isolation level is required.
  • addRepository this adds new repositories that you're able to access through the UoW callback, the first parameter is the key to access them, the second parameter is the repository class, the only requirement is that you provide a class that expects the same transaction object you're returning from the startTrx callback as its first constructor parameter

Usage

For a real example, check the knex test in the main github repository.

The generated UoW instance is a function that takes a callback, with its parameter being the repositories you've registered while setting it up, they'll be available as function calls as they're instantiated on demand and injected with the current transaction reference.

let newBalance = await UoW(async r => {
    let user = await r.users().findById(userId);
    let account = await r.accounts().findByAccountNumber(user.accountNo);
    account.deduct(200, "new service subscription");
    if (account.balance <= 0) {
        throw new Error("insufficient balance");
    }
    await r.accounts().save(account);
    return account.currentBalance();
})

Every repository referenced inside the UoW callback shares the same transaction reference, as such, would be an atomic operation. The UoW function returns the value returned by the given callback, so you can use whatever values you recieve after you're done with your transaction, the UoW is a generic function and as such the return value is type safe. (in our example, currentBalance returns a number and newBalance will be of type number).

Isolation levels defined earlier are available as methods under the UoW instance, the previous example can be run serializably:

let newBalance = await UoW.serialzable(async r => {
    // snip
})

The UoW type keeps track of both isolations and repositories provided, so you will have compiler and IDE support when using them.