Moleculer: ES6 service classes support

Created on 18 Jan 2018  路  3Comments  路  Source: moleculerjs/moleculer

Discussion about how Moleculer can support ES6 classes as a Service.

Current Service schema structure

"use strict";

module.exports = {
    name: "greeter",
    version: "v2",
    meta: {
        scalable: true
    },
    dependencies: [
        "auth",
        "users"
    ],

    settings: {
        upperCase: true
    },

    actions: {
        hello() {
            return "Hello Moleculer";
        },

        welcome: {
            cache: {
                keys: ["name"]
            },
            params: {
                name: "string"
            },
            handler(ctx) {
                return this.sayWelcome(ctx.params.name);
            }
        }
    },

    events: {
        "user.created"(user) {
            this.broker.call("mail.send", { user });
        }
    },

    methods: {
        sayWelcome(name) {
            this.logger.debug("Say hello to", name);
            return `Welcome, ${this.settings.upperCase ? name.toUpperCase() : name}`;
        }
    },

    created() {
        this.logger.info("Service created.");
    },

    started() {
        this.logger.info("Service started.");
    },

    stopped() {
        this.logger.info("Service stopped.");
    }   
};

Any idea?

In Progress Question help wanted

Most helpful comment

@rmccallum81 We already have decorators :D

All 3 comments

In the next version it will work:

const Service = require("moleculer").Service;

class GreeterService extends Service {

    constructor(broker) {
        super(broker);

        this._processSchema({
            name: "greeter",
            version: "v2",
            meta: {
                scalable: true
            },
            dependencies: [
                "auth",
                "users"
            ],

            settings: {
                upperCase: true
            },
            actions: {
                hello: this.hello,
                welcome: {
                    cache: {
                        keys: ["name"]
                    },
                    params: {
                        name: "string"
                    },
                    handler: this.welcome
                }
            },
            events: {
                "user.created": this.userCreated
            },
            created: this.serviceCreated,
            started: this.serviceStarted,
            stopped: this.serviceStopped,
        });
    }

    // Action handler
    hello() {
        return "Hello Moleculer";
    }

    // Action handler
    welcome(ctx) {
        return this.sayWelcome(ctx.params.name);
    }

    // Private method
    sayWelcome(name) {
        this.logger.info("Say hello to", name);
        return `Welcome, ${this.settings.upperCase ? name.toUpperCase() : name}`;
    }

    // Event handler
    userCreated(user) {
        this.broker.call("mail.send", { user });
    }

    serviceCreated() {
        this.logger.info("ES6 Service created.");
    }

    serviceStarted() {
        this.logger.info("ES6 Service started.");
    }

    serviceStopped() {
        this.logger.info("ES6 Service stopped.");
    }
}

module.exports = GreeterService;

Have you considered using decorators? This could simplify the structure of the class as the constructor would not hold the definition of the service, it would be within the class.
https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841

const Service = require("moleculer").Service;
const Decorators = require("moleculer").Decorators;

const serviceVersion = Decorators.serviceVersion;
const serviceName = Decorators.serviceName;
const meta = Decorators.meta;
const dependencies = Decorators.dependencies;
const serviceSettings = Decorators.serviceSettings;
const action = Decorators.action;
const cache = Decorators.cache;
const params = Decorators.params;
const event = Decorators.event;
const lifeCycleEvent = Decorators.lifeCycleEvent;

@serviceVersion("v2")
@serviceName("greeter")
@meta({ scalable: true })
@dependencies(["auth", "users"])
@serviceSettings({ upperCase: true })
class GreeterService extends Service {

    constructor(broker) {
        super(broker);
    }

    // Action handler
    @action("hello")
    hello() {
        return "Hello Moleculer";
    }

    // Action handler
    @action("welcome")
    @cache({ keys: ["name"] })
    @params({ name: "string" })
    welcome(ctx) {
        return this.sayWelcome(ctx.params.name);
    }

    // Private method
    sayWelcome(name) {
        this.logger.info("Say hello to", name);
        return `Welcome, ${this.settings.upperCase ? name.toUpperCase() : name}`;
    }

    // Event handler
    @event("user.created")
    userCreated(user) {
        this.broker.call("mail.send", { user });
    }

    @lifeCycleEvent("created")
    serviceCreated() {
        this.logger.info("ES6 Service created.");
    }

    @lifeCycleEvent("started")
    serviceStarted() {
        this.logger.info("ES6 Service started.");
    }

    @lifeCycleEvent("stopped")
    serviceStopped() {
        this.logger.info("ES6 Service stopped.");
    }
}

module.exports = GreeterService;

@rmccallum81 We already have decorators :D

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ngraef picture ngraef  路  4Comments

Kamil93 picture Kamil93  路  3Comments

ngraef picture ngraef  路  3Comments

slinkardbrandon picture slinkardbrandon  路  4Comments

HighSoftWare96 picture HighSoftWare96  路  4Comments