Git Product home page Git Product logo

tsxper / service-manager Goto Github PK

View Code? Open in Web Editor NEW
0.0 0.0 0.0 146 KB

Extension to the Service Locator design pattern, that helps to manage application dependencies.

Home Page: https://www.npmjs.com/package/@tsxper/service-manager

License: MIT License

Smarty 0.76% Makefile 3.65% Shell 3.43% TypeScript 92.16%
dependency-injection javascript service-manager typescript service-locator

service-manager's Introduction

Service-Manager

NPM Version License: MIT npm type definitions NPM Downloads

@tsxper/service-manager is a TypeScript extension to the Service Locator design pattern, that helps with managing application dependencies.

Service manager can be helpful for apps and services that do not require big frameworks with complex dependency injection setup.

It's designed to be used in browser and NodeJS apps.

Advantages of using ServiceManager:

  • Easy setup.
  • Comfortable integration testing.
  • Small size (ServiceManager is implemented as one class).
  • CommonJS and ESM modules support.
  • Aimed to be used in all JavaScript projects (NodeJS and browsers).
  • Doesn't use code generators.
  • Doesn't rely on experimental technology, like decorators.

Examples

See other examples in GitHub.

With using registered factories you can easily inject required dependencies in your services.

Imaging you have a service "DownstreamService" which depends on "LoggerService" and "VaultService".

// define your applications services
export class DownstreamService {
  constructor(logger: LoggerService, vault: VaultService) {
    // ...
  }
}


// sm.ts - add Service Manager configuration with factories
export const sm = new ServiceManager({
  'logger': () => new LoggerService(),
  'vault': () => {
    const url = process.env.VAULT_URL;
    if (!url) throw new Error('VAULT_URL is not set');
    return new VaultService(url);
  },
}).add('downstream', async (sm) => {
  // place for some async calls
  return new DownstreamService(sm.get('logger'), sm.get('vault'));
});


// app.ts - use Service Manager in your app
const downstream = await sm.get('downstream'); // we use "await" because associated factory is async function
await downstream.sendData(records);
sm.get('logger').log('Success');


// __tests__/app.test.ts - easily change behavior in tests
sm.replace(
  'vault',
  () => new VaultFake('http://test/')
);

Caching Instances

By default, all created instances are cached (shared instances). To retrieve a private instance of a service, pass "true" as second argument to "get()" method. See example below.

const privateInstance = sm.get('logger', true);

Disable/Enable Caching

Service instances cache is enabled by default.

Calling disableCache()/enableCache() does not remove existing cached instances.

sm.disableCache();
sm.enableCache();

Clear Services Cache

Call "cleanCache()" method to clear service cache.

Call "destroy()" method to clear service cache and registered factories.

sm.cleanCache(); // clean cache
// or 
sm.destroy(); // clean cache and registered factories

Local vs Global Cache

ServiceManager supports 2 types of cache: "global" (for runtime) and "local" (for particular app instance). Good use case for a "local" cache is tests isolation. To control cache type, ServiceManager constructor has a "useGlobalCache" as 2nd parameter (default is "true").

const useGlobalCache = false;
new ServiceManager({...}, useGlobalCache);

See builder example.

Types Inference

Types inference for registered services is supported.

// Checks for retrieving only registered services
const vault = sm.get('unregistered');
// TypeScript Error: Argument of type '"unregistered"' is not assignable to parameter of type '"logger" | "vault"'.

const vault = sm.get('vault'); 
// vault: VaultService

Known Limitations

  1. Using strings instead of literals. Example: TypeScript does not derive literal from a class name.
// this code will work
const serviceName = 'LoggerService';
const sm = new ServiceManager({[serviceName]: () => new LoggerService()});
const loggerService = sm.get(serviceName); // serviceName is string literal

// this code will NOT work in TypeScript
const sm = new ServiceManager({ [Fruit.name]: () => new Fruit(1), 'Article': () => new Article('title') });
sm.get(Fruit.name).weight; // Fruit.name is a "string" and can't be associated with a concrete service
// Property 'weight' does not exist on type 'Fruit | Article'.

To solve this issue, define a literal property on your class, for example:

class Fruit {
  static service: 'Fruit' = 'Fruit';
}
const sm = new ServiceManager({[Fruit.service]: () => new Fruit()});
  1. Retrieve services in JavaScript.

In plain JavaScript, sm.get('logger') will not check that 'logger' was set or that 'logger' is associated with Logger service factory. What you can do is to add type guards.

Note. In VS Code you can enable types check for JavaScript files with adding a line // @ts-check ;

// @ts-check 
const sm = new ServiceManager({'logger': () => new Logger()});
const logger = sm.get('logger');
if (!(logger instanceof Logger)) throw new Error('"logger" is not Logger');
logger.log();

License

MIT license.

service-manager's People

Contributors

vbabak avatar

service-manager's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.