Skip to content

Commit

Permalink
add plugin-engine
Browse files Browse the repository at this point in the history
  • Loading branch information
antoniopresto committed Nov 1, 2023
1 parent ea863e5 commit d101039
Show file tree
Hide file tree
Showing 33 changed files with 1,080 additions and 16 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "powership",
"version": "3.1.5",
"version": "3.1.6",
"private": true,
"scripts": {
"pack": "run-s pack:*",
Expand Down
2 changes: 1 addition & 1 deletion packages/accounts/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powership/accounts",
"version": "3.1.5",
"version": "3.1.6",
"description": "Powership accounts",
"#type": "module",
"main": "./out/index.cjs",
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-plugins/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powership/babel-plugins",
"version": "3.1.5",
"version": "3.1.6",
"main": "out",
"sideEffects": false,
"typings": "out",
Expand Down
2 changes: 1 addition & 1 deletion packages/boilerplate/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powership/boilerplate",
"version": "3.1.5",
"version": "3.1.6",
"author": "antoniopresto <[email protected]>",
"sideEffects": false,
"#type": "module",
Expand Down
2 changes: 1 addition & 1 deletion packages/deepstate/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powership/deepstate",
"version": "3.1.5",
"version": "3.1.6",
"main": "out/index.js",
"module": "out/module/index.mjs",
"sideEffects": false,
Expand Down
2 changes: 1 addition & 1 deletion packages/entity/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powership/entity",
"version": "3.1.5",
"version": "3.1.6",
"#type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
Expand Down
2 changes: 1 addition & 1 deletion packages/helpers/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powership/helpers",
"version": "3.1.5",
"version": "3.1.6",
"#type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
Expand Down
2 changes: 1 addition & 1 deletion packages/logstorm/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "logstorm",
"version": "3.1.5",
"version": "3.1.6",
"typings": "out",
"author": "antoniopresto <[email protected]>",
"#type": "module",
Expand Down
2 changes: 1 addition & 1 deletion packages/mongo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@powership/mongo",
"version": "3.1.5",
"version": "3.1.6",
"#type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-engine/.babelrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@powership/boilerplate/babel-config.cjs')
1 change: 1 addition & 0 deletions packages/plugin-engine/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@powership/boilerplate/eslintrc.cjs')
77 changes: 77 additions & 0 deletions packages/plugin-engine/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# See https://help.github.com/ignore-files/ for more about ignoring files.

.idea
/lib

# VisualStudioCode.gitignore
# See https://github.com/github/gitignore/blob/master/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
/generated

# dependencies
/node_modules

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Xcode
#
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
*.moved-aside
DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace

# Android/IJ
#
.gradle
local.properties

# node.js
#
npm-debug.log
yarn-error.log

# BUCK
buck-out/
\.buckd/
android/app/libs
android/keystores/debug.keystore

lib/
webpack-assets.json
webpack-stats.json
*.swp

# Modern Relay
__generated__
1 change: 1 addition & 0 deletions packages/plugin-engine/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18
4 changes: 4 additions & 0 deletions packages/plugin-engine/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"singleQuote": true,
"printWidth": 80
}
125 changes: 125 additions & 0 deletions packages/plugin-engine/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# PluginEngine

PluginEngine is designed to facilitate the extensibility of
applications by providing a simple and minimalist pattern
to manage events and middleware. It's crucial for creating
loosely coupled systems which are essential for maintaining
a scalable and maintainable codebase.

By leveraging a middleware system with an event-driven
architecture, different parts of an application can
communicate with each other in a decoupled way. This enables
easier feature additions and modifications without causing a
ripple effect of changes throughout the codebase.

### Defining Events

Define the events that your application will exec and the data associated with those events.

```typescript
type MyEvents = {
userRegistered: { username: string; email: string };
userLoggedIn: { username: string };
};
```

### Creating a Plugin

Create a plugin to handle an event. A plugin can have `enter`, `exit`, and `error` handlers.

```typescript
const userNotificationPlugin = {
name: 'UserNotificationPlugin',
enter: (data, context) => {
// Send a welcome email on user registration
if (data.username && data.email) {
sendWelcomeEmail(data.email);
}
},
};
```

### Registering a Plugin

Register the plugin to handle a specific event.

```typescript
const engine = new PluginEngine<MyEvents>();

engine.on('userRegistered', userNotificationPlugin);
```

### Executing Events

Exec an event when a particular action occurs in your application.

```typescript
engine.exec('userRegistered', {
username: 'johndoe',
email: '[email protected]',
});
```

#### Express.js Example

```typescript
import express from 'express';
import { PluginEngine } from 'plugin-engine';

const app = express();
const engine = new PluginEngine<MyEvents>();

app.use((req, res, next) => {
engine
.exec('requestReceived', { req, res })
.then(({ req, res }) => {
next();
})
.catch((error) => {
res.status(500).send(error.message);
});
});

// Register a plugin
engine.on('requestReceived', authenticationPlugin);

app.listen(3000, () => {
console.log('Server is running on port 3000');
});
```

## FAQ

### How do I handle errors?

Use the `abortWith` method provided in the context argument to the event handler to terminate the processing of subsequent handlers for a particular event and immediately return the current state of the event data. This provides a mechanism to short-circuit the event processing chain when a certain condition is met.

```typescript
const errorHandlingPlugin = {
name: 'ErrorHandlingPlugin',
enter: (data, context) => {
if (someErrorCondition) {
context.abortWith({
error: 'An error occurred',
});
}
},
};

engine.on('someEvent', errorHandlingPlugin);
```

### Can I use PluginEngine on the client-side?

Yes, PluginEngine can be used on the client-side. The usage is the same as shown in the basic examples. The `exec`, `on`, and `abortWith` methods, along with the plugin structure, remain consistent whether you are working on the client-side or server-side.

### How to unregister a plugin?

When you register a plugin using the `on` method, it returns a function that you can call to unregister the plugin.

```typescript
const unregister = engine.on('someEvent', somePlugin);

// Later...
unregister();
```
8 changes: 8 additions & 0 deletions packages/plugin-engine/jest.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
preset: 'ts-jest',
testRegex: '(spec|test)\\.tsx?$',
modulePathIgnorePatterns: ['node_modules', 'testing.d.ts'],
testEnvironment: 'node',
testTimeout: +(process.env.TEST_TIMEOUT || 30000),
setupFilesAfterEnv: ['<rootDir>/setupTests.cjs'],
};
97 changes: 97 additions & 0 deletions packages/plugin-engine/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"name": "plugin-engine",
"version": "3.1.6",
"#type": "module",
"main": "./out/index.cjs",
"module": "./out/module/index.mjs",
"types": "./out/index.d.ts",
"exports": {
".": {
"types": "./out/index.d.ts",
"import": "./out/module/index.mjs",
"require": "./out/index.cjs"
}
},
"browser": {
"out/module/index.mjs": "./out/browser/module/index.mjs",
"out/index.cjs": "./out/browser/index.cjs"
},
"author": "antoniopresto <[email protected]>",
"license": "MIT",
"sideEffects": false,
"scripts": {
"test": "jest",
"build": "run-s clear && run-p declarations build:*",
"clear": "rimraf out",
"fix": "run-s fix:* ",
"fix:prettier": "prettier \"src/**/*.ts\" --write",
"fix:lint": "eslint src --ext .ts --fix",
"prepublishOnly": "run-s build fix && run-p test",
"build-targets": "run-p build:*",
"build:browser": "TARGET=browser npm run babild -- --out-dir out/browser --out-file-extension .cjs",
"build:module-browser": "TARGET=module-browser npm run babild -- --out-dir out/browser/module --out-file-extension .mjs",
"build:node": "TARGET=node npm run babild -- --out-dir out --out-file-extension .cjs",
"build:module-node": "TARGET=module-node npm run babild -- --out-dir out/module --out-file-extension .mjs",
"declarations": "tsc -p tsconfig.declarations.json",
"babild": "babel 'src' --extensions '.ts,.tsx' --source-maps=true --ignore '**/__tests__'"
},
"description": "Powership server-utils",
"repository": {
"type": "git",
"url": "https://github.com/antoniopresto/powership/tree/master/packages/"
},
"keywords": [
"typescript",
"schema",
"graphql",
"validation",
"type",
"inference"
],
"dependencies": {
"@powership/utils": "workspace:*",
"@powership/schema": "workspace:*",
"@powership/entity": "workspace:*",
"highlight.js": "11.7.0"
},
"devDependencies": {
"@powership/boilerplate": "workspace:*",
"@babel/cli": "7.19.3",
"@babel/plugin-transform-typescript": "7.19.3",
"@babel/preset-env": "7.19.3",
"@babel/preset-typescript": "7.18.6",
"@powership/babel-plugins": "workspace:*",
"@powership/mongo": "workspace:*",
"@types/jest": "29.5.3",
"@types/node": "16.18.3",
"@typescript-eslint/eslint-plugin": "5.39.0",
"@typescript-eslint/parser": "5.39.0",
"conditional-type-checks": "1.0.6",
"eslint": "8.25.0",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-eslint-comments": "3.2.0",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-sort-keys-fix": "1.1.2",
"eslint-plugin-typescript-sort-keys": "2.1.0",
"graphql": "16.6.0",
"jest": "29.6.2",
"npm-run-all": "4.1.5",
"prettier": "2.8.8",
"prettier-plugin-multiline-arrays": "^1.1.3",
"rimraf": "3.0.2",
"ts-jest": "29.1.0",
"typedoc": "^0.23.24",
"typescript": "4.9.3"
},
"files": [
"package.json",
"out/*",
"README.md"
],
"typedoc": {
"entryPoint": "./src/index.ts",
"readmeFile": "./README.md",
"displayName": ".",
"tsconfig": "./tsconfig.module.json"
}
}
Loading

0 comments on commit d101039

Please sign in to comment.