Skip to content

Commit

Permalink
feat: add plugin mechanism
Browse files Browse the repository at this point in the history
- Load plugin and record its method, path, and function
  • Loading branch information
Chinlinlee committed Jan 4, 2023
1 parent d24a5f7 commit 7e57425
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 8 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@
/python/__pycache__

# ignore windwos's dcmtk execuable binary
/models/DICOM/dcmtk/dcmtk-3.6.5-win64-dynamic
/models/DICOM/dcmtk/dcmtk-3.6.5-win64-dynamic

/plugins/config.js
30 changes: 23 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"passport": "^0.5.2",
"passport-local": "^1.0.0",
"polka": "^0.5.2",
"regexparam": "^2.0.1",
"run-script-os": "^1.1.6",
"sharp": "^0.30.4",
"shorthash2": "^1.0.3",
Expand Down
16 changes: 16 additions & 0 deletions plugins/config.template.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports.pluginsConfig = {
"helloWorld": {
enable: true,
before: true,
routers: [
{
path: "/dicom-web/studies",
method: "get"
},
{
path: "/dicom-web/studies/:studyUID/instances",
method: "get"
}
]
}
};
160 changes: 160 additions & 0 deletions plugins/plugin.class.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/**
* @typedef PluginOptions
* @property {boolean} enable
* @property {boolean} before
* @property {PluginRouter[]} routers
*/

/**
* @typedef PluginRouter
* @property {string} path
* @property {string} method
*
*/

const _ = require("lodash");
const regexparam = require("regexparam");

class Plugin {
/**
*
* @param {string} name
* @param {PluginOptions} options
*/
constructor(name, options) {
this.name = name;
this.options = options;
this.fns = [];
this.preProcessGroup = [];
this.postProcessGroup = [];
}

load() {
try {
if (!this.options.enable) return;

let pluginFuncs = require(`./${this.name}`);
pluginFuncs = this.singleFuncToArray(pluginFuncs);

this.fns = [...pluginFuncs];
this.checkIsAllFunc();

if (this.options.before) {
this.loadPrePlugin_();
} else {
this.loadPostPlugin_();
}
} catch(e) {
throw e;
}
}

/**
* @private
*/
loadPrePlugin_() {
for(let fn of this.fns) {
this.preProcessGroup.push(fn);
}
}

/**
* @private
*/
loadPostPlugin_() {
for(let fn of this.fns) {
this.postProcessGroup.push(fn);
}
}

singleFuncToArray(funcs) {
if(!Array.isArray(funcs)) {
return [funcs];
}
return funcs;
}

checkIsAllFunc() {
let isAllFunc = this.fns.every(v => v instanceof Function);

if (!isAllFunc) {
throw new Error("The plugin must be function or function array");
}
}

}

class LocalPlugin {
constructor(path, method, preFns=[], postFns=[]) {
this.path = path;
this.method = method;
this.preFns = preFns;
this.postFns = postFns;
}
}

class PluginGroup {
constructor() {
/** @type {LocalPlugin[]} */
this.plugins = [];
}


add(plugin) {
let localPlugins = this.convertToLocalPlugins(plugin);

for(let localPlugin of localPlugins) {
let hitLocalPlugin = this.findLocalPlugin(localPlugin.path, localPlugin.method);
if (hitLocalPlugin) {
this.addFnsToExistPlugin(hitLocalPlugin, localPlugin);
} else {
this.plugins.push(localPlugin);
}
}

}

/**
*
* @param {LocalPlugin} hitLocalPlugin
* @param {LocalPlugin} plugin
*/
addFnsToExistPlugin(hitLocalPlugin, plugin) {
if (plugin.postFns.length > 0) {
hitLocalPlugin.postFns.push(...plugin.postFns);
} else if (plugin.preFns.length > 0) {
hitLocalPlugin.preFns.push(...plugin.preFns);
}
}

/**
*
* @param {Plugin} plugin
* @return {LocalPlugin[]}
*/
convertToLocalPlugins(plugin) {
let localPlugins = [];
for(let router of plugin.options.routers) {
let localPlugin = new LocalPlugin(router.path, router.method, plugin.preProcessGroup, plugin.postProcessGroup);
localPlugins.push(localPlugin);
}

return localPlugins;
}

/**
* @param {string} path
* @param {string} method
*/
findLocalPlugin(path, method) {
return this.plugins.find(
v => regexparam.parse(v.path).pattern.exec(path) &&
v.method.toUpperCase() === method.toUpperCase()
);
}
}

module.exports.Plugin = Plugin;
module.exports.LocalPlugin = LocalPlugin;
const pluginGroup = new PluginGroup();
module.exports.pluginGroup = pluginGroup;
14 changes: 14 additions & 0 deletions routes.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
const { Plugin, pluginGroup } = require("./plugins/plugin.class");
const { pluginsConfig } = require("./plugins/config");

function loadAllPlugin() {
for (let pluginName in pluginsConfig) {
let plugin = new Plugin(pluginName, pluginsConfig[pluginName]);
plugin.load();
pluginGroup.add(plugin);
}
}

module.exports = function (app) {

loadAllPlugin();

app.use("/dicom-web", require("./api/dicom-web"));
};

0 comments on commit 7e57425

Please sign in to comment.