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

@alt-javascript/cdi

v2.0.2

Published

Application Contexts and Dependency Injection =============================================================

Downloads

34

Readme

Application Contexts and Dependency Injection

NPM Language Badge Package Badge release notes

Introduction

A familiar application context and dependency injection package for JavaScript, supporting simple singleton and prototype component factory definitions, with a choice of manual or auto wiring (injection) of property references and config placeholders.

Usage

Browser

The module is also able to be used directly in the browser, in combination with the logger and config modules. You can either import the ApplicationContext globally as an IIFE (Immediately Invoked Function Expression), as follows:

   <script src="https://cdn.jsdelivr.net/npm/@alt-javascript/cdi/dist/alt-javascript-applicationcontext-iife.js"></script>
    <script>
        import { SimpleClass } from'./index.js';

        const applicationContext = new ApplicationContext(SimpleClass);
    </script>

Or import the ES6 module bundle from a module, as follows:

import { ApplicationContext } from 'https://cdn.jsdelivr.net/npm/@alt-javascript/cdi/dist/alt-javascript-cdi-esm.js'
import { SimpleClass } from'./index.js';

const applicationContext = new ApplicationContext(SimpleClass);

Singleton Components

To configure a simple singleton service object, simply instantiate an ApplicationContext and pass it the class definition. The default scope is singleton, and the component name defaults to lowerCamelCase of the class name.

import { ApplicationContext } from '@alt-javascript/cdi';
import { SimpleClass } from'./index.js';

const applicationContext = new ApplicationContext(SimpleClass);
applicationContext.start();
applicationContext.get('simpleClass');

Simple types, objects and functions can be registered as components.

import { ApplicationContext } from '@alt-javascript/cdi';
import { SimpleClass } from './index.js';

const applicationContext = new ApplicationContext([
    {name: 'someData', attr:'aValue', behave: () => {}},
    {Reference : (what) => { console.log (`Hello ${what}`)},
      name : 'aFunc'}]);
applicationContext.start();
applicationContext.get('someData').behave();
applicationContext.get('aFunc')('world!');

Singletons can also be defined with the common alias names Service,Component and Singleton

import { ApplicationContext, Singleton, Service, Component } from '@alt-javascript/cdi';
const { SimpleSingleton, SimpleService, SimpleSingleton } from './index.js';

const context = new Context([
    new Singleton(SimpleSingleton), 
    new Service(SimpleService),
    new Component(SimpleSingleton)]);
const applicationContext = new ApplicationContext([context]);
applicationContext.start();
applicationContext.get('simpleSingleton');
applicationContext.get('simpleService');
applicationContext.get('simpleComponent');

Prototype (transient) Components

Prototype, or transient scoped objects can be defined with Prototype definition, or Transient definition. These objects are created each time they are requested from the context, or wired by the context lifecycle.

import { ApplicationContext, Prototype, Transient }  from '@alt-javascript/cdi';
import { SimpleClass, SimpleTransient }  from './index.js';

const applicationContext = new ApplicationContext(new Prototype(SimpleClass));
const applicationContext = new ApplicationContext(new Transient(SimpleTransient));
applicationContext.start();
applicationContext.get('simpleClass');

Explicit Component Definitions

Use the Component class to declare the full explicit definition of a component, allow full control.

import { ApplicationContext, Component }  from '@alt-javascript/cdi';
import { SimpleClass, SimpleTransient } from './index.js';

const applicationContext = new ApplicationContext(
    new Component({
        Reference : SimpleClass,
        name : 'useAnExplicitName',
        qualifier : '@my-scope/SimpleClass',
        scope : Scopes.SERVICE,
    }));

applicationContext.start();
applicationContext.get('useAnExplicitName');

Component Factory Definitions

A component can be created by referencing a factory function directly.

import { ApplicationContext, Component } from '@alt-javascript/cdi';
import { MyClass }  from './index.js';

const applicationContext = new ApplicationContext(
    new Component({
        factory : MyClass.someStaticFunction(),
        name : 'fromAFactory',
        qualifier : '@my-scope/SimpleClass',
        scope : Scopes.SERVICE,
    }));

applicationContext.start();
applicationContext.get('useAnExplicitName');

Component Property Injection (wiring)

Component properties are autowired by name, by default. In the example classB and classC will be autowired, but classD, which is non-null will be let alone. The attribute will remain null if not found in the application context.

export default class ClassA {
  constructor() {
    this.classB = null;
    this.classC = 'autowired';
    this.classD = new new ClassD();
    this.attribute = null;
  }
};

Configuration values that are booted with @alt-javascript/boot are injected with the familiar placeholder syntax.

export default class ClassA {
  constructor() {
    this.attribute = '${get.this.from.config}';
  }
};

Advanced Component Property Injection, factory and wireFactory functions

Properties can be injected, directly from functions, or from references to functions on other components using the explicit Property declaration class.

    const context = new Context([
      {
        name: 'singletonFactory',
        generator: (param) => ({ name: 'simplePrototype', attr: param }),
      },
      new Service({
        Reference: 'MyServiceService',
          properties: [new Property({
              name:'myServiceProperty',
              factory: 'singletonFactory',
              factoryFunction: 'generator',
              factoryArgs: 'one'})]
      })]);

    const applicationContext = new ApplicationContext([context]);
    applicationContext.start();
    const myServiceService = applicationContext.get('myServiceService');
    assert.exists(myServiceService, 'myServiceService exists');
    assert.equal(myServiceService.myServiceProperty.attr, 'one', 'myServiceService.myServiceProperty.attr == one');

Where the context of the target component being wired is required, a wireFactory can be declared on a prototype and the target Component instance is passed as an argument by default. The ApplicationContext declares a logger prototype with the loggerFactory component as the wireFactory, allowing the component qualifier to be used as the logger category (true).

Global components:

The ApplicationContext is designed to play nicely with other projects in the @alt-javascript scope, so the booted config, loggerFactory, logger, loggerCategoryCache are available.

Any component declared with a logger and qualifier properties will be injected with an appropriate logger, as if by magic.

License

May be freely distributed under the MIT license.

Copyright (c) 2021 Craig Parravicini