Writing a DecentCMS service

In previous posts, I’ve shown the structure of a DecentCMS module, and how to describe such a module through its manifest. In this post, I’ll go into the meat of the matter by showing how to write an actual service. DecentCMS services are just classes that fulfill a specific named contract. Services can consume other services, using existing or new contracts, thus providing a generic mechanism for extensibility, where extensions to core services can expose their own extensibility points.

The constructor for a service class must take the scope object as its parameter.

/**
 * My service implements the "do-something-custom" service contract.
 */
var MyService = function MyService(scope) {
  this.scope = scope;
}

The scope will act as the service locator for the service's methods:

MyService.prototype.doSomething = function doSomething(a, b) {
  var myDependency = this.scope.require('my-dependency');
  // do something with myDependency if it's not null.
}

The scope can also be used to obtain the settings for the feature the service is part of:

var site = this.scope.require('shell');
var settings = site.features['my-feature'];
var mySetting = settings['my-setting'];

The mySetting variable will then contain the value defined in the site's settings.json file under the features.my-featuresection:

"features": {
  "my-feature": {
    "my-setting": "The value for my setting"
  }

A service must export its constructor:

module.exports = MyService;

It should also declare the feature it's part of, the service contract it implements, and the scope it should depend on:

MyService.feature = 'my-feature';
MyService.service = 'do-something-custom';
MyService.scope = 'shell';

The scope is especially important to define for services that must persist throughout the lifetime of their scope. For example, a service the instances of which must remain available for the duration of the request would have a declared scope of "request", and should be marked as scope singletons:

MyService.isScopeSingleton = true;

This way, all code that requires that service during a given request will get the same instance. Within two distinct requests however, you'll get distinct instances.

Features should also be declared in the module manifest, under the features section of the package.json file:

"features": {
  "my-feature": {
    "name": "My feature",
    "description": "A specific implementation of 'do-something-custom'."
  },

A DecentCMS service is easy to declare and write. It’s also a central concept, as almost every piece of functionality above bootstrapping code is written as a set of loosely-coupled services. In the next post, I’ll show how to write a new content part, which will involve writing a special kind of service.

No Comments