Plugin Oriented Design with Halia
Tags: javascript, typescript, webdev, showdev
Published: 2021-01-31 19:34:36

Building apps with Plugin Oriented Design (POD) has a lot of advantages (discussed in my recent [blog post](https://dev.to/codalreef/pluggable-apps-with-lenny-the-duck-2oj3))

Today, I'd like to introduce "Halia", an extensible TS / JS Dependency Injection Framework built to manage "Plugins" in your apps.

Building a Pluggable app has its advantages, but it can be challenging to stay organized when you're dynamically importing code that changes other code.

For example, if you build a feature that depends upon another feature (or multiple), you'd likely end up "splitting and spreading" the feature across the app.

Halia can help with this:

[Halia - Extensible TS / JS Dependency Injection Framework](https://github.com/CodalReef/Halia)

![Halia Logo](https://dev-to-uploads.s3.amazonaws.com/i/4shk4wri1g7rsv0s4ceg.png)

> With Halia, your app's core is packaged as a Plugin, and  features are packaged as Plugins.  Each Plugin can then be extended by other Plugins.

We’re also building tools to dynamically load plugins from a URL, activate plugins dynamically, user level managment (like a plugin store), cross-stack and cross-eco plugins, and contracts (for building re-usable plugins).

Halia is responsible for managing this tree of plugins.  Let's see how it works with an example:

## Example
You have a duck that everyone loves:

```typescript
//  duck-app.ts
export const getDuck = () => {
  return "Quack";
}
```

Everyone except Paul.  Paul wants a special **🦄 Disco Duck 🦄**, so you make an update:

```typescript
//  duck-app.ts
import { Paul } from 'client-list';
import { config } from 'config';
export const getDuck = () => {
  if (params.client === Paul) {
    return "Michael Quackson";
  }
  return "Quack";
}
```

While the code works for Paul, it's become more complex, harder to read, and coupled with the "client" concept.

Instead, we can use a Halia Plugin to encapsulate and inject this feature:

```typescript
//  duck-app-plugin.ts
import * as DuckApp from './duck-app';
export const DuckAppPlugin: HaliaPlugin = {
  id: "duckApp",
  name: "Duck App Plugin",
  install: () => ({
    setGetDuck: (getDuck) => DuckApp.getDuck = getDuck
  })
}
```

```typescript
//  disco-duck-plugin.ts
import { Paul } from 'client-list';
import * as config from 'config';
export const DiscoDuckPlugin: HaliaPlugin = {
  id: "discoDuck",
  name: "Disco Duck Plugin",
  dependencies: [DuckAppPlugin.id],
  install: ({ duckApp }) => {
    if (config.client === Paul) {
      duckApp.setGetDuck (() => "Michael Quackson")
    }
  }
}
```



Then we can build the stack and invoke the code:


```typescript
//  main.ts
import { HaliaStack } from Halia;
import { DuckApp } from './DuckApp';
import { DiscoFeature } from './DiscoFeature';

const buildApp = async () => {

  //  Initialize the Stack
  const appStack = new HaliaStack();

  //  Register Plugins
  appStack.register(DuckApp);
  appStack.register(DiscoFeature);

  //  Build the Stack
  await appStack.build();

  //  Call the Method
  const duckApp = appStack.getExports(DuckApp.id);
  duckApp.logNoise();
}

buildApp();
```

With this, the original code is left in-tact and de-coupled.

If Paul longer wants the **🦄 Disco Duck 🦄**  we just don't register the Plugin.  If he needs an additional change, we have a namespace dedicated to his unique needs.

>  This is a simple example that can be solved in other ways.  However, it demonstrates the general idea, and as features become more complex, we've found this pattern helps to keep things organized.



## Conclusion

For more info on Dependency Injection Frameworks (like Angular, Nest, and Halia) see our article:

[Dependency Injection with Doug the Goldfish 🐠](https://dev.to/codalreef/learn-dependency-injection-with-doug-the-goldfish-3j43)

![Doug Image](https://dev-to-uploads.s3.amazonaws.com/i/3tbx7dihrh60d5poo4pt.png)


I hope you enjoy the package and the associated concepts.

Cheers,
CR

*For more articles like this, follow me on:  [Github](https://github.com/CodalReef), [Dev](https://dev.to/codalreef), [Twitter](https://twitter.com/CodalReef), [Reddit](https://www.reddit.com/user/CodalReef)*