Coder Social home page Coder Social logo

plug's Introduction

Build Status codecov Carthage compatible Cocoapods Platform Platform License

Plug is a multi-platform plugin architecture micro-framework and plugin manager written in pure Swift. It allows to define rules that has to be met to activate plugins at given plugin point.

Requirements

Development

Project uses following tools for development

  1. XCodeGen
  2. Cocoapods
  3. SwiftLint

Installation

To get started with the Plug you first have to decide how you will integrate it with your project. Plug supports following tools:

Cocoapods

To install Plug using Cocoapods go through following steps:

  1. Add the following entry in your Podfile:
pod 'Plug'
  1. Then run pod install.

Carthage

To install Plug using Carthage go through following steps:

  1. Add the following entry to your Cartfile
github "lewandowskit93/Plug"
  1. Then run carthage update

Swift Package Manager

To install Plug using Swift Package Manager go through following steps:

  1. Add following package dependency in you Package.swift .package(url: "https://github.com/lewandowskit93/Plug.git", from: "0.4.0")
  2. Add following target dependency in your Package.swift dependencies: ["Plug"])

For instance this is how it might look like:

import PackageDescription

let package = Package(
    name: "YourLibrary",
    products: [
        .library(
            name: "YourLibrary",
            targets: ["YourLibrary"])
    ],
    dependencies: [
        .package(url: "https://github.com/lewandowskit93/Plug.git", from: "0.4.0")
    ],
    targets: [
        .target(
            name: "YourLibrary",
            dependencies: ["Plug"])
    ]
)

Overview

Here is a quick overview of functionalities and concepts used in Plug.

Plug example

Plugin

Plugin is anything that implements PPlugin protocol. You can define what your plugins are and what they do.

As an example here you can see ViewPlugin which can return single SwiftUI view:

public final class ViewPlugin<V: View>: PPlugin {
    private let builder: () -> V
    
    public init(builder: @escaping () -> V) {
        self.builder = builder
    }
    
    public var view: some View {
        return builder()
    }
}

RuleResolvingContext

RuleResolvingContext is anything that implements PRuleResolvingContext. Everything in the Plug is generic over PRuleResolvingContext. It can provide additional information to decide if the plugins are enabled.

Rule

Rule decides whether plugins should be returned or not depending on the context. You can define your own rules by implementing PRule protocol. There are a few rules available for you: AtomRule, EnabledRule, DisabledRule, InvertedRule, AllOfRule, AnyOfRule, NoneOfRule, AnyRule.

PluginPoint

PluginPoint defines a single slot to which plugins can be attached. Single plugin point can have multiple plugins and rules that describes them. It has a hierarchical structure meaning that a plugin point can have children plugin points. The rules applied to a plugin point are also applied to it's children. Plugin points can be built with PluginPointBuilder

DSL

Plug defines some operators and DSL to shorten building of plugin points. Available operators are:

  • Adding plugin with operator: Builder <+ Plugin
  • Removign plugin with operator: Builder <- Plugin
  • Adding rule with operator: Builder §+ Rule
  • Removing rule with operator: Builder §- Rule
  • Adding child with operator: Builder |+ PluginPoint
  • Removing child with operator: Builder |- PluginPoint
  • Finalize building with operator: Builder^

There are also operators available for rules building:

  • Inverting a rule: !AnyRule
  • AllOfRule: &&[AnyRule]
  • NoneOfRule: ~~[AnyRule]
  • AnyOfRule: ||[AnyRule]

Example

This is an example definition of plugin point which allows two plugin features to exist if they are enabled in FooContext.

var pluginPoint = PluginPointBuilder()
    .add(child: PluginPointBuilder()
        .add(plugin: pluginFactory.feature1Plugin())
        .add(rule: FeatureEnabledRule(id: "feature_1").any())
        .build()
    )
    .add(child: PluginPointBuilder()
        .add(plugin: pluginFactory.feature2Plugin())
        .add(rule: FeatureEnabledRule(id: "feature_2").any())
        .build()
    ).build()
var availablePlugins = pluginPoint.getAvailablePlugins(context: FooContext())

The same plugin point could be defined using operators as follows:

var pluginPoint = (
        PluginPointBuilder()
        |+ (
            PluginPointBuilder()
            <+ pluginFactory.feature1Plugin()
            §+ FeatureEnabledRule(id: "feature_1").any()
           )^
        |+ (
            PluginPointBuilder()
            <+ pluginFactory.feature2Plugin()
            §+ FeatureEnabledRule(id: "feature_2").any()
           )^
    )^
var availablePlugins = pluginPoint.getAvailablePlugins(context: FooContext())

or using DSL as follows:

var pluginPoint = PluginPoint {
    child {
        PluginPoint {
            plugin(contextType: Context.self) { pluginFactory.feature1Plugin() }
            rule(pluginType: Plugin.self) { FeatureEnabledRule(id: "feature_1").any() }
        }
    }
    child {
        PluginPoint {
            plugin(contextType: Context.self) { pluginFactory.feature2Plugin() }
            rule(pluginType: Plugin.self) { FeatureEnabledRule(id: "feature_2").any() }
        }
    }
}

For more detailed example please see the source code.

Contribution

Project is created and maintained by Tomasz Lewandowski.

If you created some new feature or fixed a bug you can create a pull request. Please feel free to submit your feature requests if you have any.

License

Plug is released under an MIT license. See License.md for more information.

plug's People

Contributors

lewandowskit93 avatar

Stargazers

 avatar

Watchers

 avatar

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.