Skip to main content

Services

Service is an entity defined in the feature's API, and it represents an 'output' of the feature.

Each feature defines integration points and services, which other features will be able to use.

A service is defined by the feature, for an environment, meaning that the implementation to that service should return from the setup function of that feature in that environment.

so a service declaration in a feature would look something like

interface IEchoService {
echo(): string
}

const f1 = new Feature({
id: 'f1',
api: {
echoService: Service.withType<IEchoService>().providedFrom(myEnv)
}
});

In the feature's setup function, in the myEnv environment, We will need to provide an implementation for the declared echoService;

f1.setup(myEnv, () => {
const echoService = {
echo: () => {
return 'hello from f1';
},
};

return {
echoService,
};
});

After f1 declared this service other features in myEnv can access the service.

First let's craete a new feature with a dependency on f1

const f2 = new Feature({
id: 'f2',
api: {},
dependencies: [f1],
});

This will allow f2, when running in myEnv, to access the services of f1.

f2.setup(myEnv, (_, { f1: { echoService } }) => {
console.log(echoService.echo());
});

Remote service

Now let's say we have 2 environments, myEnv and otherEnv. f1 wants the echoService to be available also in otherEnv. Let's tweak the declaration of f1

interface IEchoService {
echo(): string
}

const f1 = new Feature({
id: 'f1',
api: {
echoService: Service.withType<IEchoService>().providedFrom(myEnv).allowRemoteAccess()
}
});

This will allow f1 (or any other feature) to access the echoService provided from myEnv.

Because echoService is provided from the feature currently being setup, it will be accessible from the first argument of the [[runtime.entities.feature#^setup_handler]]

f1.setup(otherEnv, ({ echoService }) => {
// because the service is provided from myEnv, the service will ba async in this environment
echoService
.echo()
.then((echoData) => {
console.log('received', echoData);
})
.catch(console.error);
});

If any other feature which has a direct dependency on f1 wants to access that service from any other environment that is not myEnv, the usage will be the same as [[runtime.entities.service#^dependency_setup]] but, again, all the services would be async.

.allowRemoteAccess(options)

The allowRemoteAccess is the only method exposed from the service instance, and it notifies the engine, that for any other environment we should proxy this api call to the environment where the service is provided from.

The options object structure is as follows:

  • every key of the object is a method name on the service
  • the value is an object with the following optional arguments
argumenttypeexplanation
emitOnlybooleantells the communication that a response for a call to this method is not required
listenerbooleanwhether this method is a registration to an event emitter method
removeListenerstring (the name of the 'listener' method in this service)the method which removes a listener provided to 'listener' method
removeAllListenersstring (the name of the 'listener' method in this service)the method which removes all the listeners provided to the 'listener' method
  • currently we support only methods which provide only a callback method as a valid subscriber when subscribing to events across environments