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

moleculer-db-typeorm

v0.0.2

Published

Moleculer service to store typeorm entities in database for standard or multi-tenant solutions

Downloads

6

Readme

Moleculer logo

moleculer-db-typeorm NPM version

Moleculer service to store entities in database for typeorm based on moleculer-db. Not to be used in conjunction with moleculer-db, but a drop-in replacement when using typeorm framework that includes multi-tenancy connection methods.

The reasoning behind this new module is that in multi-tenancy micro service applications it can be a lot of work to create a micro service for each entity when using typeorm. The single db connection per service would mean a lot of unnecessary chatter between services with ctx or broker service calls. Furthermore if there is a need to isolate tenant data by means of a database for each tenant, then the onboarding process of each additional tenant would mean creating a new service for each tenant. This module solves that by giving the developer the ability to create additonal connections to other databases within a single service, reducing the need for a service for each database. The service can then also connect to other database engines, given there is an adapter for it through typeorm, and disaster recovery of a tenant is simplified without effecting other tenant's data.

Current work in progress, stable for MongoDB. Only MongoDB adapter created so far for typeorm framework.

Features

  • default CRUD actions for typeorm
  • cached actions
  • pagination support
  • pluggable adapter (NeDB is the default memory adapter for testing & prototyping)
  • adapter for MongoDB (PostgreSQL, SQLite, MySQL, MSSQL in development).
  • fields filtering
  • populating
  • encode/decode IDs
  • entity lifecycle events for notifications
  • single connection or multiple connections for services to connect to typeorm databases

Install

$ npm install moleculer-db-typeorm --save

Usage

"use strict";

const { ServiceBroker } = require("moleculer");
const DbService = require("moleculer-db-typeorm");

const broker = new ServiceBroker();

// Create a DB service for `user` entities
broker.createService({
    name: "users",
    mixins: [DbService],

    // mode needed to switch between "standard" or "mt" (milti-tenant) modes
    mode: "standard",

    settings: {
        fields: ["_id", "username", "name"]
    },

    afterConnected() {
        // Seed the DB with ˙this.create`
    }
});

broker.start()

// Create a new user
.then(() => broker.call("users.create", {
    username: "john",
    name: "John Doe",
    status: 1
}))

// Get all users
.then(() => broker.call("users.find").then(console.log));

// List users with pagination
.then(() => broker.call("users.list", { page: 2, pageSize: 10 }).then(console.log));

// Get a user
.then(() => broker.call("users.get", { id: 2 }).then(console.log));

// Update a user
.then(() => broker.call("users.update", { id: 2, name: "Jane Doe" }).then(console.log));

// Delete a user
.then(() => broker.call("users.remove", { id: 2 }).then(console.log));

Settings

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | idField | String | required | Name of ID field. | | fields | Array.<String> | null | Field filtering list. It must be an Array. If the value is null or undefined doesn't filter the fields of entities. | | populates | Array | null | Schema for population. Read more. | | pageSize | Number | required | Default page size in list action. | | maxPageSize | Number | required | Maximum page size in list action. | | maxLimit | Number | required | Maximum value of limit in find action. Default: -1 (no limit) | | entityValidator | Object, function | null | Validator schema or a function to validate the incoming entity in create & 'insert' actions. |

Note: idField does not work with Sequelize adapter as you can freely set your own ID while creating the model.

Actions

find Cached action

Find entities by query.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | populate | String, Array.<String> | required | Populated fields. | | fields | String, Array.<String> | required | Fields filter. | | limit | Number | - | Max count of rows. | | offset | Number | - | Count of skipped rows. | | sort | String | - | Sorted fields. | | search | String | - | Search text. | | searchFields | String, Array.<String> | required | Fields for searching. | | query | Object | - | Query object. Passes to adapter. |

Results

Type: Array.<Object>

List of found entities.

count Cached action

Get count of entities by query.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | search | String | - | Search text. | | searchFields | String, Array.<String> | required | Fields list for searching. | | query | Object | - | Query object. Passes to adapter. |

Results

Type: Number

Count of found entities.

list Cached action

List entities by filters and pagination results.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | populate | String, Array.<String> | required | Populated fields. | | fields | String, Array.<String> | required | Fields filter. | | page | Number | - | Page number. | | pageSize | Number | - | Size of a page. | | sort | String | - | Sorted fields. | | search | String | - | Search text. | | searchFields | String, Array.<String> | required | Fields for searching. | | query | Object | - | Query object. Passes to adapter. |

Results

Type: Object

List of found entities and count with pagination info.

create

Create a new entity.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | params | Object | required | Entity to save. |

Results

Type: Object

Saved entity.

insert

Create many new entities.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | entity | Object | - | Entity to save. | | entities | Array.<Object> | - | Entities to save. |

Results

Type: Object, Array.<Object>

Saved entity(ies).

get Cached action

Get entity by ID.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | id | any, Array.<any> | required | ID(s) of entity. | | populate | String, Array.<String> | required | Field list for populate. | | fields | String, Array.<String> | required | Fields filter. | | mapping | Boolean | - | Convert the returned Array to Object where the key is the value of id. |

Results

Type: Object, Array.<Object>

Found entity(ies).

update

Update an entity by ID.

After update, clear the cache & call lifecycle events.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | id | any | required | ID of entity. |

Results

Type: Object

Updated entity.

remove

Remove an entity by ID.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | id | any | required | ID of entity. |

Results

Type: Number

Count of removed entities.

Methods

connect

Connect to database.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | mode | * | required | | | options | * | required | | | cb | * | required | |

Results

Type: Connection

returns connection as callback

Examples

// use .connect() for standard single connection (mode: 'mt')
// use .connect(mode, options, cb) to create multiple connecitons in multi-tenant mode (mode: 'mt')

let productsConnection: Connection;
await this.connect('mt', productOpts, (conn: Connection) => {
    return (productsConnection = conn);
});

console.log(await productsConnection!.getMongoRepository(Products).find());

sanitizeParams

Sanitize context parameters at find action.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | | | params | Object | required | |

Results

Type: Object

getById

Get entity(ies) by ID(s).

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | id | any, Array.<any> | required | ID or IDs. | | decoding | Boolean | - | Need to decode IDs. |

Results

Type: Object, Array.<Object>

Found entity(ies).

entityChanged

Clear the cache & call entity lifecycle events

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | type | String | required | | | json | Object, Array.<Object>, Number | required | | | ctx | Context | required | |

Results

Type: Promise

clearCache

Clear cached entities

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | No input parameters.

Results

Type: Promise

transformDocuments

Transform the fetched documents

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | | | params | Object | required | | | docs | Array, Object | required | |

Results

Type: Array, Object

validateEntity

Validate an entity by validator.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | entity | Object | required | |

Results

Type: Promise

encodeID

Encode ID of entity.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | id | any | required | |

Results

Type: any

decodeID

Decode ID of entity.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | id | any | required | |

Results

Type: any

_find

Find entities by query.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | Context instance. | | params | Object | - | Parameters. |

Results

Type: Array.<Object>

List of found entities.

_count

Get count of entities by query.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | Context instance. | | params | Object | - | Parameters. |

Results

Type: Number

Count of found entities.

_list

List entities by filters and pagination results.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | Context instance. | | params | Object | - | Parameters. |

Results

Type: Object

List of found entities and count.

_create

Create a new entity.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | Context instance. | | params | Object | - | Parameters. |

Results

Type: Object

Saved entity.

_insert

Create many new entities.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | Context instance. | | params | Object | - | Parameters. |

Results

Type: Object, Array.<Object>

Saved entity(ies).

_get

Get entity by ID.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | Context instance. | | params | Object | - | Parameters. |

Results

Type: Object, Array.<Object>

Found entity(ies).

_update

Update an entity by ID.

After update, clear the cache & call lifecycle events.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | Context instance. | | params | Object | - | Parameters. |

Results

Type: Object

Updated entity.

_remove

Remove an entity by ID.

Parameters

| Property | Type | Default | Description | | -------- | ---- | ------- | ----------- | | ctx | Context | required | Context instance. | | params | Object | - | Parameters. |

Populating

The service supports to populate fields from other services. E.g.: if you have an author field in post entity, you can populate it with users service by ID of author. If the field is an Array of IDs, it will populate all entities via only one request.

Example of populate schema

broker.createService({
    name: "posts",
    mixins: [DbService],
    settings: {
        populates: {
            // Shorthand populate rule. Resolve the `voters` values with `users.get` action.
            "voters": "users.get",

            // Define the params of action call. It will receive only with username & full name of author.
            "author": {
                action: "users.get",
                params: {
                    fields: "username fullName"
                }
            },

            // Custom populator handler function
            "rate"(ids, docs, rule, ctx) {
                return Promise.resolve(...);
            }
        }
    }
});

// List posts with populated authors
broker.call("posts.find", { populate: ["author"]}).then(console.log);

The populate parameter is available in find, list and get actions.

Lifecycle entity events

There are 3 lifecycle entity events which are called when entities are manipulated.

broker.createService({
    name: "posts",
    mixins: [DbService],
    settings: {},

    afterConnected() {
        this.logger.info("Connected successfully");
    },

    entityCreated(json, ctx) {
        this.logger.info("New entity created!");
    },

    entityUpdated(json, ctx) {
        // You can also access to Context
        this.logger.info(`Entity updated by '${ctx.meta.user.name}' user!`);
    },

    entityRemoved(json, ctx) {
        this.logger.info("Entity removed", json);
    },    
});

Please note! If you manipulate multiple entities (updateMany, removeMany), the json parameter will be a Number instead of entities!

Extend with custom actions

Naturally you can extend this service with your custom actions.

const DbService = require("moleculer-db");

module.exports = {
    name: "posts",
    mixins: [DbService],

    settings: {
        fields: ["_id", "title", "content", "votes"]
    },

    actions: {
        // Increment `votes` field by post ID
        vote(ctx) {
            return this.adapter.updateById(ctx.params.id, { $inc: { votes: 1 } });
        },

        // List posts of an author
        byAuthors(ctx) {
            return this.find({
                query: {
                    author: ctx.params.authorID
                },
                limit: ctx.params.limit || 10,
                sort: "-createdAt"
            });
        }
    }
}

Remove default actions

According to moleculer documentation you can disable an action when override it with false

const DbService = require("moleculer-db");

module.exports = {
    name: "posts",
    mixins: [DbService],

    actions: {
        // Disable find default action
        find: false
    }
}

Test

$ npm test

In development with watching

$ npm run ci

License

The project is available under the MIT license.

Contact

Copyright (c) 2016-2018 MoleculerJS

@moleculerjs @MoleculerJS